@@ -969,16 +969,40 @@ compound=true
969969#endif
970970
971971using VPRecipeTest = VPlanTestBase;
972+
973+ namespace {
974+ template <typename RecipeT, typename T, typename ... Rest>
975+ void checkVPRecipeCastImpl (RecipeT *R) {
976+ // Direct checks on recipe pointer
977+ EXPECT_TRUE (isa<T>(R));
978+ EXPECT_EQ (R, dyn_cast<T>(R));
979+ (void )cast<T>(R); // Verify cast succeeds (asserts on failure)
980+
981+ // Check through base pointer
982+ VPRecipeBase *BaseR = R;
983+ EXPECT_TRUE (isa<T>(BaseR));
984+ EXPECT_EQ (R, dyn_cast<T>(BaseR));
985+ (void )cast<T>(BaseR);
986+
987+ // Check through const base pointer
988+ const VPRecipeBase *ConstBaseR = R;
989+ EXPECT_TRUE (isa<T>(ConstBaseR));
990+ EXPECT_EQ (R, dyn_cast<T>(ConstBaseR));
991+ (void )cast<T>(ConstBaseR);
992+
993+ if constexpr (sizeof ...(Rest) > 0 )
994+ checkVPRecipeCastImpl<RecipeT, Rest...>(R);
995+ }
996+ } // namespace
997+
972998TEST_F (VPRecipeTest, CastVPInstructionToVPUser) {
973999 IntegerType *Int32 = IntegerType::get (C, 32 );
9741000 VPlan &Plan = getPlan ();
9751001 VPValue *Op1 = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 1 ));
9761002 VPValue *Op2 = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 2 ));
9771003 VPInstruction Recipe (Instruction::Add, {Op1, Op2});
978- EXPECT_TRUE (isa<VPUser>(&Recipe));
979- VPRecipeBase *BaseR = &Recipe;
980- EXPECT_TRUE (isa<VPUser>(BaseR));
981- EXPECT_EQ (&Recipe, BaseR);
1004+
1005+ checkVPRecipeCastImpl<VPInstruction, VPUser>(&Recipe);
9821006}
9831007
9841008TEST_F (VPRecipeTest, CastVPWidenRecipeToVPUser) {
@@ -992,10 +1016,8 @@ TEST_F(VPRecipeTest, CastVPWidenRecipeToVPUser) {
9921016 Args.push_back (Op1);
9931017 Args.push_back (Op2);
9941018 VPWidenRecipe WidenR (*AI, make_range (Args.begin (), Args.end ()));
995- EXPECT_TRUE (isa<VPUser>(&WidenR));
996- VPRecipeBase *WidenRBase = &WidenR;
997- EXPECT_TRUE (isa<VPUser>(WidenRBase));
998- EXPECT_EQ (&WidenR, WidenRBase);
1019+
1020+ checkVPRecipeCastImpl<VPWidenRecipe, VPUser>(&WidenR);
9991021 delete AI;
10001022}
10011023
@@ -1013,10 +1035,8 @@ TEST_F(VPRecipeTest, CastVPWidenCallRecipeToVPUserAndVPDef) {
10131035 Args.push_back (Op2);
10141036 Args.push_back (CalledFn);
10151037 VPWidenCallRecipe Recipe (Call, Fn, Args);
1016- EXPECT_TRUE (isa<VPUser>(&Recipe));
1017- VPRecipeBase *BaseR = &Recipe;
1018- EXPECT_TRUE (isa<VPUser>(BaseR));
1019- EXPECT_EQ (&Recipe, BaseR);
1038+
1039+ checkVPRecipeCastImpl<VPWidenCallRecipe, VPUser>(&Recipe);
10201040
10211041 VPValue *VPV = &Recipe;
10221042 EXPECT_TRUE (VPV->getDefiningRecipe ());
@@ -1041,13 +1061,10 @@ TEST_F(VPRecipeTest, CastVPWidenSelectRecipeToVPUserAndVPDef) {
10411061 Args.push_back (Op3);
10421062 VPWidenSelectRecipe WidenSelectR (*SelectI,
10431063 make_range (Args.begin (), Args.end ()));
1044- EXPECT_TRUE (isa<VPUser>(&WidenSelectR));
1045- VPRecipeBase *BaseR = &WidenSelectR;
1046- EXPECT_TRUE (isa<VPUser>(BaseR));
1047- EXPECT_EQ (&WidenSelectR, BaseR);
1064+
1065+ checkVPRecipeCastImpl<VPWidenSelectRecipe, VPUser>(&WidenSelectR);
10481066
10491067 VPValue *VPV = &WidenSelectR;
1050- EXPECT_TRUE (isa<VPRecipeBase>(VPV->getDefiningRecipe ()));
10511068 EXPECT_EQ (&WidenSelectR, VPV->getDefiningRecipe ());
10521069
10531070 delete SelectI;
@@ -1065,10 +1082,8 @@ TEST_F(VPRecipeTest, CastVPWidenGEPRecipeToVPUserAndVPDef) {
10651082 Args.push_back (Op1);
10661083 Args.push_back (Op2);
10671084 VPWidenGEPRecipe Recipe (GEP, make_range (Args.begin (), Args.end ()));
1068- EXPECT_TRUE (isa<VPUser>(&Recipe));
1069- VPRecipeBase *BaseR = &Recipe;
1070- EXPECT_TRUE (isa<VPUser>(BaseR));
1071- EXPECT_EQ (&Recipe, BaseR);
1085+
1086+ checkVPRecipeCastImpl<VPWidenGEPRecipe, VPUser>(&Recipe);
10721087
10731088 VPValue *VPV = &Recipe;
10741089 EXPECT_TRUE (isa<VPRecipeBase>(VPV->getDefiningRecipe ()));
@@ -1077,6 +1092,28 @@ TEST_F(VPRecipeTest, CastVPWidenGEPRecipeToVPUserAndVPDef) {
10771092 delete GEP;
10781093}
10791094
1095+ TEST_F (VPRecipeTest, CastVPWidenCastRecipeToVPUser) {
1096+ VPlan &Plan = getPlan ();
1097+ IntegerType *Int32 = IntegerType::get (C, 32 );
1098+ IntegerType *Int64 = IntegerType::get (C, 64 );
1099+ auto *Cast = CastInst::CreateZExtOrBitCast (PoisonValue::get (Int32), Int64);
1100+ VPValue *Op1 = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 1 ));
1101+ VPWidenCastRecipe Recipe (Instruction::ZExt, Op1, Int64, *Cast);
1102+
1103+ checkVPRecipeCastImpl<VPWidenCastRecipe, VPUser>(&Recipe);
1104+ delete Cast;
1105+ }
1106+
1107+ TEST_F (VPRecipeTest, CastVPWidenIntrinsicRecipeToVPUser) {
1108+ VPlan &Plan = getPlan ();
1109+ IntegerType *Int32 = IntegerType::get (C, 32 );
1110+ VPValue *Op1 = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 1 ));
1111+ VPValue *Op2 = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 2 ));
1112+ VPWidenIntrinsicRecipe Recipe (Intrinsic::smax, {Op1, Op2}, Int32);
1113+
1114+ checkVPRecipeCastImpl<VPWidenIntrinsicRecipe, VPUser>(&Recipe);
1115+ }
1116+
10801117TEST_F (VPRecipeTest, CastVPBlendRecipeToVPUser) {
10811118 VPlan &Plan = getPlan ();
10821119 IntegerType *Int32 = IntegerType::get (C, 32 );
@@ -1090,9 +1127,9 @@ TEST_F(VPRecipeTest, CastVPBlendRecipeToVPUser) {
10901127 Args.push_back (I2);
10911128 Args.push_back (M2);
10921129 VPBlendRecipe Recipe (Phi, Args, {});
1093- EXPECT_TRUE (isa<VPUser>(&Recipe));
1094- VPRecipeBase *BaseR = &Recipe;
1095- EXPECT_TRUE (isa<VPUser>(BaseR));
1130+
1131+ checkVPRecipeCastImpl<VPBlendRecipe, VPUser>( &Recipe) ;
1132+
10961133 delete Phi;
10971134}
10981135
@@ -1103,10 +1140,8 @@ TEST_F(VPRecipeTest, CastVPInterleaveRecipeToVPUser) {
11031140 VPValue *Mask = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 2 ));
11041141 InterleaveGroup<Instruction> IG (4 , false , Align (4 ));
11051142 VPInterleaveRecipe Recipe (&IG, Addr, {}, Mask, false , {}, DebugLoc ());
1106- EXPECT_TRUE (isa<VPUser>(&Recipe));
1107- VPRecipeBase *BaseR = &Recipe;
1108- EXPECT_TRUE (isa<VPUser>(BaseR));
1109- EXPECT_EQ (&Recipe, BaseR);
1143+
1144+ checkVPRecipeCastImpl<VPInterleaveRecipe, VPUser>(&Recipe);
11101145}
11111146
11121147TEST_F (VPRecipeTest, CastVPReplicateRecipeToVPUser) {
@@ -1121,9 +1156,9 @@ TEST_F(VPRecipeTest, CastVPReplicateRecipeToVPUser) {
11211156 FunctionType *FTy = FunctionType::get (Int32, false );
11221157 auto *Call = CallInst::Create (FTy, PoisonValue::get (FTy));
11231158 VPReplicateRecipe Recipe (Call, make_range (Args.begin (), Args.end ()), true );
1124- EXPECT_TRUE (isa<VPUser>(&Recipe));
1125- VPRecipeBase *BaseR = &Recipe;
1126- EXPECT_TRUE (isa<VPUser>(BaseR));
1159+
1160+ checkVPRecipeCastImpl<VPReplicateRecipe, VPUser>( &Recipe) ;
1161+
11271162 delete Call;
11281163}
11291164
@@ -1132,10 +1167,8 @@ TEST_F(VPRecipeTest, CastVPBranchOnMaskRecipeToVPUser) {
11321167 IntegerType *Int32 = IntegerType::get (C, 32 );
11331168 VPValue *Mask = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 1 ));
11341169 VPBranchOnMaskRecipe Recipe (Mask, {});
1135- EXPECT_TRUE (isa<VPUser>(&Recipe));
1136- VPRecipeBase *BaseR = &Recipe;
1137- EXPECT_TRUE (isa<VPUser>(BaseR));
1138- EXPECT_EQ (&Recipe, BaseR);
1170+
1171+ checkVPRecipeCastImpl<VPBranchOnMaskRecipe, VPUser>(&Recipe);
11391172}
11401173
11411174TEST_F (VPRecipeTest, CastVPWidenMemoryRecipeToVPUserAndVPDef) {
@@ -1147,10 +1180,8 @@ TEST_F(VPRecipeTest, CastVPWidenMemoryRecipeToVPUserAndVPDef) {
11471180 VPValue *Addr = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 1 ));
11481181 VPValue *Mask = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 2 ));
11491182 VPWidenLoadRecipe Recipe (*Load, Addr, Mask, true , false , {}, {});
1150- EXPECT_TRUE (isa<VPUser>(&Recipe));
1151- VPRecipeBase *BaseR = &Recipe;
1152- EXPECT_TRUE (isa<VPUser>(BaseR));
1153- EXPECT_EQ (&Recipe, BaseR);
1183+
1184+ checkVPRecipeCastImpl<VPWidenLoadRecipe, VPUser>(&Recipe);
11541185
11551186 VPValue *VPV = Recipe.getVPSingleValue ();
11561187 EXPECT_TRUE (isa<VPRecipeBase>(VPV->getDefiningRecipe ()));
@@ -1159,6 +1190,71 @@ TEST_F(VPRecipeTest, CastVPWidenMemoryRecipeToVPUserAndVPDef) {
11591190 delete Load;
11601191}
11611192
1193+ TEST_F (VPRecipeTest, CastVPInterleaveEVLRecipeToVPUser) {
1194+ VPlan &Plan = getPlan ();
1195+ IntegerType *Int32 = IntegerType::get (C, 32 );
1196+ VPValue *Addr = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 1 ));
1197+ VPValue *Mask = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 2 ));
1198+ VPValue *EVL = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 8 ));
1199+ InterleaveGroup<Instruction> IG (4 , false , Align (4 ));
1200+ VPInterleaveRecipe BaseRecipe (&IG, Addr, {}, Mask, false , {}, DebugLoc ());
1201+ VPInterleaveEVLRecipe Recipe (BaseRecipe, *EVL, Mask);
1202+
1203+ checkVPRecipeCastImpl<VPInterleaveEVLRecipe, VPUser>(&Recipe);
1204+ }
1205+
1206+ TEST_F (VPRecipeTest, CastVPWidenLoadEVLRecipeToVPUser) {
1207+ VPlan &Plan = getPlan ();
1208+ IntegerType *Int32 = IntegerType::get (C, 32 );
1209+ PointerType *Int32Ptr = PointerType::get (C, 0 );
1210+ auto *Load =
1211+ new LoadInst (Int32, PoisonValue::get (Int32Ptr), " " , false , Align (1 ));
1212+ VPValue *Addr = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 1 ));
1213+ VPValue *Mask = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 2 ));
1214+ VPValue *EVL = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 8 ));
1215+ VPWidenLoadRecipe BaseLoad (*Load, Addr, Mask, true , false , {}, {});
1216+ VPWidenLoadEVLRecipe Recipe (BaseLoad, Addr, *EVL, Mask);
1217+
1218+ checkVPRecipeCastImpl<VPWidenLoadEVLRecipe, VPUser>(&Recipe);
1219+
1220+ delete Load;
1221+ }
1222+
1223+ TEST_F (VPRecipeTest, CastVPWidenStoreRecipeToVPUser) {
1224+ VPlan &Plan = getPlan ();
1225+ IntegerType *Int32 = IntegerType::get (C, 32 );
1226+ PointerType *Int32Ptr = PointerType::get (C, 0 );
1227+ auto *Store = new StoreInst (PoisonValue::get (Int32),
1228+ PoisonValue::get (Int32Ptr), false , Align (1 ));
1229+ VPValue *Addr = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 1 ));
1230+ VPValue *StoredVal = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 42 ));
1231+ VPValue *Mask = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 2 ));
1232+ VPWidenStoreRecipe Recipe (*Store, Addr, StoredVal, Mask, true , false , {}, {});
1233+
1234+ checkVPRecipeCastImpl<VPWidenStoreRecipe, VPUser>(&Recipe);
1235+
1236+ delete Store;
1237+ }
1238+
1239+ TEST_F (VPRecipeTest, CastVPWidenStoreEVLRecipeToVPUser) {
1240+ VPlan &Plan = getPlan ();
1241+ IntegerType *Int32 = IntegerType::get (C, 32 );
1242+ PointerType *Int32Ptr = PointerType::get (C, 0 );
1243+ auto *Store = new StoreInst (PoisonValue::get (Int32),
1244+ PoisonValue::get (Int32Ptr), false , Align (1 ));
1245+ VPValue *Addr = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 1 ));
1246+ VPValue *StoredVal = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 42 ));
1247+ VPValue *EVL = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 8 ));
1248+ VPValue *Mask = Plan.getOrAddLiveIn (ConstantInt::get (Int32, 2 ));
1249+ VPWidenStoreRecipe BaseStore (*Store, Addr, StoredVal, Mask, true , false , {},
1250+ {});
1251+ VPWidenStoreEVLRecipe Recipe (BaseStore, Addr, *EVL, Mask);
1252+
1253+ checkVPRecipeCastImpl<VPWidenStoreEVLRecipe, VPUser>(&Recipe);
1254+
1255+ delete Store;
1256+ }
1257+
11621258TEST_F (VPRecipeTest, MayHaveSideEffectsAndMayReadWriteMemory) {
11631259 IntegerType *Int1 = IntegerType::get (C, 1 );
11641260 IntegerType *Int32 = IntegerType::get (C, 32 );
@@ -1606,9 +1702,7 @@ TEST_F(VPRecipeTest, CastVPReductionRecipeToVPUser) {
16061702 VPValue *CondOp = getPlan ().getOrAddLiveIn (ConstantInt::get (Int32, 3 ));
16071703 VPReductionRecipe Recipe (RecurKind::Add, FastMathFlags (), Add, ChainOp,
16081704 CondOp, VecOp, false );
1609- EXPECT_TRUE (isa<VPUser>(&Recipe));
1610- VPRecipeBase *BaseR = &Recipe;
1611- EXPECT_TRUE (isa<VPUser>(BaseR));
1705+ checkVPRecipeCastImpl<VPReductionRecipe, VPUser>(&Recipe);
16121706 delete Add;
16131707}
16141708
@@ -1623,9 +1717,7 @@ TEST_F(VPRecipeTest, CastVPReductionEVLRecipeToVPUser) {
16231717 CondOp, VecOp, false );
16241718 VPValue *EVL = getPlan ().getOrAddLiveIn (ConstantInt::get (Int32, 0 ));
16251719 VPReductionEVLRecipe EVLRecipe (Recipe, *EVL, CondOp);
1626- EXPECT_TRUE (isa<VPUser>(&EVLRecipe));
1627- VPRecipeBase *BaseR = &EVLRecipe;
1628- EXPECT_TRUE (isa<VPUser>(BaseR));
1720+ checkVPRecipeCastImpl<VPReductionEVLRecipe, VPUser>(&EVLRecipe);
16291721 delete Add;
16301722}
16311723} // namespace
0 commit comments