@@ -1030,17 +1030,25 @@ class VPInstruction : public VPRecipeWithIRFlags,
1030
1030
}
1031
1031
};
1032
1032
1033
- // / A specialization of VPInstruction augmenting it with a dedicated result
1034
- // / type, to be used when the opcode and operands of the VPInstruction don't
1035
- // / directly determine the result type.
1036
- class VPInstructionWithType : public VPInstruction {
1033
+ class VPResultType {
1037
1034
// / Scalar result type produced by the recipe.
1038
1035
Type *ResultTy;
1039
1036
1037
+ public:
1038
+ VPResultType (Type *ResultTy) : ResultTy(ResultTy) {}
1039
+ virtual ~VPResultType () = default ;
1040
+
1041
+ Type *getResultType () const { return ResultTy; }
1042
+ };
1043
+
1044
+ // / A specialization of VPInstruction augmenting it with a dedicated result
1045
+ // / type, to be used when the opcode and operands of the VPInstruction don't
1046
+ // / directly determine the result type.
1047
+ class VPInstructionWithType : public VPInstruction , public VPResultType {
1040
1048
public:
1041
1049
VPInstructionWithType (unsigned Opcode, ArrayRef<VPValue *> Operands,
1042
1050
Type *ResultTy, DebugLoc DL, const Twine &Name = " " )
1043
- : VPInstruction(Opcode, Operands, DL, Name), ResultTy (ResultTy) {}
1051
+ : VPInstruction(Opcode, Operands, DL, Name), VPResultType (ResultTy) {}
1044
1052
1045
1053
static inline bool classof (const VPRecipeBase *R) { return isCast (R); }
1046
1054
@@ -1065,15 +1073,45 @@ class VPInstructionWithType : public VPInstruction {
1065
1073
return 0 ;
1066
1074
}
1067
1075
1068
- Type *getResultType () const { return ResultTy; }
1069
-
1070
1076
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1071
1077
// / Print the recipe.
1072
1078
void print (raw_ostream &O, const Twine &Indent,
1073
1079
VPSlotTracker &SlotTracker) const override ;
1074
1080
#endif
1075
1081
};
1076
1082
1083
+ template <> struct CastIsPossible <VPResultType, const VPRecipeBase *> {
1084
+ static inline bool isPossible (const VPRecipeBase *f) {
1085
+ return isa<VPInstructionWithType>(f);
1086
+ }
1087
+ };
1088
+
1089
+ template <>
1090
+ struct CastInfo <VPResultType, const VPRecipeBase *>
1091
+ : public CastIsPossible<VPResultType, const VPRecipeBase *> {
1092
+ using Self = CastInfo<VPResultType, const VPRecipeBase *>;
1093
+
1094
+ using CastReturnType =
1095
+ typename cast_retty<VPResultType, VPRecipeBase *>::ret_type;
1096
+
1097
+ static inline VPResultType *doCast (const VPRecipeBase *f) {
1098
+ auto *VPI =
1099
+ const_cast <VPInstructionWithType *>(dyn_cast<VPInstructionWithType>(f));
1100
+ return VPI;
1101
+ }
1102
+
1103
+ // This assumes that you can construct the cast return type from `nullptr`.
1104
+ // This is largely to support legacy use cases - if you don't want this
1105
+ // behavior you should specialize CastInfo for your use case.
1106
+ static inline VPResultType *castFailed () { return nullptr ; }
1107
+
1108
+ static inline VPResultType *doCastIfPossible (const VPRecipeBase *f) {
1109
+ if (!Self::isPossible (f))
1110
+ return castFailed ();
1111
+ return doCast (f);
1112
+ }
1113
+ };
1114
+
1077
1115
// / A recipe to wrap on original IR instruction not to be modified during
1078
1116
// / execution, except for PHIs. PHIs are modeled via the VPIRPhi subclass.
1079
1117
// / Expect PHIs, VPIRInstructions cannot have any operands.
0 commit comments