[llvm] 2432465 - [VPlan] Support isa/dyn_cast from VPRecipeBase to VPIRMetadata (NFC). (#166245)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 18 03:31:15 PST 2025
Author: Florian Hahn
Date: 2025-11-18T11:31:11Z
New Revision: 2432465d99d5740bc335bcce50024878134fcc08
URL: https://github.com/llvm/llvm-project/commit/2432465d99d5740bc335bcce50024878134fcc08
DIFF: https://github.com/llvm/llvm-project/commit/2432465d99d5740bc335bcce50024878134fcc08.diff
LOG: [VPlan] Support isa/dyn_cast from VPRecipeBase to VPIRMetadata (NFC). (#166245)
Implement CastInfo from VPRecipeBase to VPIRMetadata to support
isa/dyn_Cast. This is similar to CastInfoVPPhiAccessors, supporting
dyn_cast by down-casting to the concrete recipe types inheriting from
VPIRMetadata.
Can be used for more generalized VPIRMetadata printing following
https://github.com/llvm/llvm-project/pull/165825.
PR: https://github.com/llvm/llvm-project/pull/166245
Added:
Modified:
llvm/lib/Transforms/Vectorize/VPlan.h
llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index a88ddf217da9b..fc29ab0c84093 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -3876,6 +3876,75 @@ template <>
struct CastInfo<VPPhiAccessors, const VPRecipeBase *>
: CastInfoVPPhiAccessors<const VPRecipeBase *> {};
+/// Casting from (const) VPRecipeBase -> (const) VPIRMetadata is supported for
+/// all recipe types implementing VPIRMetadata. Used by isa<> & co.
+namespace detail {
+template <typename DstTy, typename RecipeBasePtrTy>
+static inline auto castToVPIRMetadata(RecipeBasePtrTy R) -> DstTy {
+ switch (R->getVPDefID()) {
+ case VPDef::VPInstructionSC:
+ return cast<VPInstruction>(R);
+ case VPDef::VPWidenSC:
+ return cast<VPWidenRecipe>(R);
+ case VPDef::VPWidenCastSC:
+ return cast<VPWidenCastRecipe>(R);
+ case VPDef::VPWidenIntrinsicSC:
+ return cast<VPWidenIntrinsicRecipe>(R);
+ case VPDef::VPWidenCallSC:
+ return cast<VPWidenCallRecipe>(R);
+ case VPDef::VPWidenSelectSC:
+ return cast<VPWidenSelectRecipe>(R);
+ case VPDef::VPReplicateSC:
+ return cast<VPReplicateRecipe>(R);
+ case VPDef::VPInterleaveSC:
+ case VPDef::VPInterleaveEVLSC:
+ return cast<VPInterleaveBase>(R);
+ case VPDef::VPWidenLoadSC:
+ case VPDef::VPWidenLoadEVLSC:
+ case VPDef::VPWidenStoreSC:
+ case VPDef::VPWidenStoreEVLSC:
+ return cast<VPWidenMemoryRecipe>(R);
+ default:
+ llvm_unreachable("invalid recipe for VPIRMetadata cast");
+ }
+}
+} // namespace detail
+
+/// Support casting from VPRecipeBase -> VPIRMetadata, by down-casting to the
+/// recipe types implementing VPIRMetadata. Used by cast<>, dyn_cast<> & co.
+template <typename DstTy, typename SrcTy>
+struct CastInfoVPIRMetadata : public CastIsPossible<DstTy, SrcTy> {
+ static inline bool isPossible(SrcTy R) {
+ // NOTE: Each recipe inheriting from VPIRMetadata must be listed here and
+ // also handled in castToVPIRMetadata.
+ return isa<VPInstruction, VPWidenRecipe, VPWidenCastRecipe,
+ VPWidenIntrinsicRecipe, VPWidenCallRecipe, VPWidenSelectRecipe,
+ VPReplicateRecipe, VPInterleaveRecipe, VPInterleaveEVLRecipe,
+ VPWidenLoadRecipe, VPWidenLoadEVLRecipe, VPWidenStoreRecipe,
+ VPWidenStoreEVLRecipe>(R);
+ }
+
+ using RetTy = DstTy *;
+
+ /// doCast is used by cast<>.
+ static inline RetTy doCast(SrcTy R) {
+ return detail::castToVPIRMetadata<RetTy, SrcTy>(R);
+ }
+
+ /// doCastIfPossible is used by dyn_cast<>.
+ static inline RetTy doCastIfPossible(SrcTy R) {
+ if (!isPossible(R))
+ return nullptr;
+ return doCast(R);
+ }
+};
+template <>
+struct CastInfo<VPIRMetadata, VPRecipeBase *>
+ : CastInfoVPIRMetadata<VPIRMetadata, VPRecipeBase *> {};
+template <>
+struct CastInfo<VPIRMetadata, const VPRecipeBase *>
+ : CastInfoVPIRMetadata<const VPIRMetadata, const VPRecipeBase *> {};
+
/// VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph. It
/// holds a sequence of zero or more VPRecipe's each representing a sequence of
/// output IR instructions. All PHI-like recipes must come before any non-PHI recipes.
diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
index 0e76c64f09f59..3842ba235ead3 100644
--- a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
@@ -996,7 +996,7 @@ TEST_F(VPRecipeTest, CastVPInstructionToVPUser) {
VPValue *Op2 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 2));
VPInstruction Recipe(Instruction::Add, {Op1, Op2});
- checkVPRecipeCastImpl<VPInstruction, VPUser>(&Recipe);
+ checkVPRecipeCastImpl<VPInstruction, VPUser, VPIRMetadata>(&Recipe);
}
TEST_F(VPRecipeTest, CastVPWidenRecipeToVPUser) {
@@ -1011,7 +1011,7 @@ TEST_F(VPRecipeTest, CastVPWidenRecipeToVPUser) {
Args.push_back(Op2);
VPWidenRecipe WidenR(*AI, Args, VPIRMetadata(), DebugLoc());
- checkVPRecipeCastImpl<VPWidenRecipe, VPUser>(&WidenR);
+ checkVPRecipeCastImpl<VPWidenRecipe, VPUser, VPIRMetadata>(&WidenR);
delete AI;
}
@@ -1030,7 +1030,7 @@ TEST_F(VPRecipeTest, CastVPWidenCallRecipeToVPUserAndVPDef) {
Args.push_back(CalledFn);
VPWidenCallRecipe Recipe(Call, Fn, Args);
- checkVPRecipeCastImpl<VPWidenCallRecipe, VPUser>(&Recipe);
+ checkVPRecipeCastImpl<VPWidenCallRecipe, VPUser, VPIRMetadata>(&Recipe);
VPValue *VPV = &Recipe;
EXPECT_TRUE(VPV->getDefiningRecipe());
@@ -1056,7 +1056,8 @@ TEST_F(VPRecipeTest, CastVPWidenSelectRecipeToVPUserAndVPDef) {
VPWidenSelectRecipe WidenSelectR(*SelectI,
make_range(Args.begin(), Args.end()));
- checkVPRecipeCastImpl<VPWidenSelectRecipe, VPUser>(&WidenSelectR);
+ checkVPRecipeCastImpl<VPWidenSelectRecipe, VPUser, VPIRMetadata>(
+ &WidenSelectR);
VPValue *VPV = &WidenSelectR;
EXPECT_EQ(&WidenSelectR, VPV->getDefiningRecipe());
@@ -1094,7 +1095,7 @@ TEST_F(VPRecipeTest, CastVPWidenCastRecipeToVPUser) {
VPValue *Op1 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 1));
VPWidenCastRecipe Recipe(Instruction::ZExt, Op1, Int64, *Cast, {});
- checkVPRecipeCastImpl<VPWidenCastRecipe, VPUser>(&Recipe);
+ checkVPRecipeCastImpl<VPWidenCastRecipe, VPUser, VPIRMetadata>(&Recipe);
delete Cast;
}
@@ -1105,7 +1106,7 @@ TEST_F(VPRecipeTest, CastVPWidenIntrinsicRecipeToVPUser) {
VPValue *Op2 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 2));
VPWidenIntrinsicRecipe Recipe(Intrinsic::smax, {Op1, Op2}, Int32);
- checkVPRecipeCastImpl<VPWidenIntrinsicRecipe, VPUser>(&Recipe);
+ checkVPRecipeCastImpl<VPWidenIntrinsicRecipe, VPUser, VPIRMetadata>(&Recipe);
}
TEST_F(VPRecipeTest, CastVPBlendRecipeToVPUser) {
@@ -1135,7 +1136,7 @@ TEST_F(VPRecipeTest, CastVPInterleaveRecipeToVPUser) {
InterleaveGroup<Instruction> IG(4, false, Align(4));
VPInterleaveRecipe Recipe(&IG, Addr, {}, Mask, false, {}, DebugLoc());
- checkVPRecipeCastImpl<VPInterleaveRecipe, VPUser>(&Recipe);
+ checkVPRecipeCastImpl<VPInterleaveRecipe, VPUser, VPIRMetadata>(&Recipe);
}
TEST_F(VPRecipeTest, CastVPReplicateRecipeToVPUser) {
@@ -1151,7 +1152,7 @@ TEST_F(VPRecipeTest, CastVPReplicateRecipeToVPUser) {
auto *Call = CallInst::Create(FTy, PoisonValue::get(FTy));
VPReplicateRecipe Recipe(Call, make_range(Args.begin(), Args.end()), true);
- checkVPRecipeCastImpl<VPReplicateRecipe, VPUser>(&Recipe);
+ checkVPRecipeCastImpl<VPReplicateRecipe, VPUser, VPIRMetadata>(&Recipe);
delete Call;
}
@@ -1175,7 +1176,7 @@ TEST_F(VPRecipeTest, CastVPWidenMemoryRecipeToVPUserAndVPDef) {
VPValue *Mask = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 2));
VPWidenLoadRecipe Recipe(*Load, Addr, Mask, true, false, {}, {});
- checkVPRecipeCastImpl<VPWidenLoadRecipe, VPUser>(&Recipe);
+ checkVPRecipeCastImpl<VPWidenLoadRecipe, VPUser, VPIRMetadata>(&Recipe);
VPValue *VPV = Recipe.getVPSingleValue();
EXPECT_TRUE(isa<VPRecipeBase>(VPV->getDefiningRecipe()));
@@ -1194,7 +1195,7 @@ TEST_F(VPRecipeTest, CastVPInterleaveEVLRecipeToVPUser) {
VPInterleaveRecipe BaseRecipe(&IG, Addr, {}, Mask, false, {}, DebugLoc());
VPInterleaveEVLRecipe Recipe(BaseRecipe, *EVL, Mask);
- checkVPRecipeCastImpl<VPInterleaveEVLRecipe, VPUser>(&Recipe);
+ checkVPRecipeCastImpl<VPInterleaveEVLRecipe, VPUser, VPIRMetadata>(&Recipe);
}
TEST_F(VPRecipeTest, CastVPWidenLoadEVLRecipeToVPUser) {
@@ -1209,7 +1210,7 @@ TEST_F(VPRecipeTest, CastVPWidenLoadEVLRecipeToVPUser) {
VPWidenLoadRecipe BaseLoad(*Load, Addr, Mask, true, false, {}, {});
VPWidenLoadEVLRecipe Recipe(BaseLoad, Addr, *EVL, Mask);
- checkVPRecipeCastImpl<VPWidenLoadEVLRecipe, VPUser>(&Recipe);
+ checkVPRecipeCastImpl<VPWidenLoadEVLRecipe, VPUser, VPIRMetadata>(&Recipe);
delete Load;
}
@@ -1225,7 +1226,7 @@ TEST_F(VPRecipeTest, CastVPWidenStoreRecipeToVPUser) {
VPValue *Mask = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 2));
VPWidenStoreRecipe Recipe(*Store, Addr, StoredVal, Mask, true, false, {}, {});
- checkVPRecipeCastImpl<VPWidenStoreRecipe, VPUser>(&Recipe);
+ checkVPRecipeCastImpl<VPWidenStoreRecipe, VPUser, VPIRMetadata>(&Recipe);
delete Store;
}
@@ -1244,7 +1245,7 @@ TEST_F(VPRecipeTest, CastVPWidenStoreEVLRecipeToVPUser) {
{});
VPWidenStoreEVLRecipe Recipe(BaseStore, Addr, *EVL, Mask);
- checkVPRecipeCastImpl<VPWidenStoreEVLRecipe, VPUser>(&Recipe);
+ checkVPRecipeCastImpl<VPWidenStoreEVLRecipe, VPUser, VPIRMetadata>(&Recipe);
delete Store;
}
More information about the llvm-commits
mailing list