Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions llvm/lib/Transforms/Vectorize/VPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -3869,6 +3869,77 @@ template <>
struct CastInfo<VPPhiAccessors, const VPRecipeBase *>
: CastInfoVPPhiAccessors<const VPRecipeBase *> {};

/// Casting from VPRecipeBase -> VPIRMetadata is supported for all recipe types
/// implementing VPIRMetadata. Used by isa<> & co.
namespace detail {
/// Returns const VPIRMetadata* if input is const, and VPIRMetadata* otherwise.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent consistency follow-up: should the above down-casting to VPPhiAccessors also support non/const-ness.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above supports const/non-const with const_cast. I can update it to use the same approach as here, after this PR lands

template <typename RecipeBasePtrTy>
static inline auto castToVPIRMetadata(RecipeBasePtrTy R) -> std::conditional_t<
std::is_const_v<std::remove_pointer_t<RecipeBasePtrTy>>,
const VPIRMetadata *, VPIRMetadata *> {
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:
return cast<VPInterleaveRecipe>(R);
case VPDef::VPInterleaveEVLSC:
return cast<VPInterleaveEVLRecipe>(R);
case VPDef::VPWidenLoadSC:
return cast<VPWidenLoadRecipe>(R);
case VPDef::VPWidenLoadEVLSC:
return cast<VPWidenLoadEVLRecipe>(R);
case VPDef::VPWidenStoreSC:
return cast<VPWidenStoreRecipe>(R);
case VPDef::VPWidenStoreEVLSC:
return cast<VPWidenStoreEVLRecipe>(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 SrcTy>
struct CastInfoVPIRMetadata : public CastIsPossible<VPIRMetadata, SrcTy> {
static inline bool isPossible(SrcTy R) {
return isa<VPInstruction, VPWidenRecipe, VPWidenCastRecipe,
VPWidenIntrinsicRecipe, VPWidenCallRecipe, VPWidenSelectRecipe,
VPReplicateRecipe, VPInterleaveRecipe, VPInterleaveEVLRecipe,
VPWidenLoadRecipe, VPWidenLoadEVLRecipe, VPWidenStoreRecipe,
VPWidenStoreEVLRecipe>(R);
Comment on lines +3920 to +3924
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to note at VPIRMetadata that any recipe inheriting from it should be listed here. Also for VPPhiAccessors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added thanks

}

using Self = CastInfo<VPIRMetadata, SrcTy>;
using RetTy = decltype(detail::castToVPIRMetadata(std::declval<SrcTy>()));

static inline RetTy doCast(SrcTy R) { return detail::castToVPIRMetadata(R); }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
static inline RetTy doCast(SrcTy R) { return detail::castToVPIRMetadata(R); }
/// doCast is used by cast<>.
static inline RetTy doCast(SrcTy R) { return detail::castToVPIRMetadata(R); }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done thanks


static inline RetTy doCastIfPossible(SrcTy R) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
static inline RetTy doCastIfPossible(SrcTy R) {
/// doCastIfPossible is used by dyn_cast<>.
static inline RetTy doCastIfPossible(SrcTy R) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done thanks

if (!Self::isPossible(R))
return nullptr;
return doCast(R);
}
};
template <>
struct CastInfo<VPIRMetadata, VPRecipeBase *>
: CastInfoVPIRMetadata<VPRecipeBase *> {};
template <>
struct CastInfo<VPIRMetadata, const VPRecipeBase *>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't we casting from a const to a non-const pointer here - is this safe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(somehow my response seem to got lost, but that should be taken care of now)

: CastInfoVPIRMetadata<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.
Expand Down
27 changes: 14 additions & 13 deletions llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -1011,7 +1011,7 @@ TEST_F(VPRecipeTest, CastVPWidenRecipeToVPUser) {
Args.push_back(Op2);
VPWidenRecipe WidenR(*AI, make_range(Args.begin(), Args.end()));

checkVPRecipeCastImpl<VPWidenRecipe, VPUser>(&WidenR);
checkVPRecipeCastImpl<VPWidenRecipe, VPUser, VPIRMetadata>(&WidenR);
delete AI;
}

Expand All @@ -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());
Expand All @@ -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());
Expand Down Expand Up @@ -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;
}

Expand All @@ -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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}
Expand All @@ -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()));
Expand All @@ -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) {
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
Loading