[llvm] [VPlan] Manage instruction medata in VPlan. (PR #135272)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 10 15:23:17 PDT 2025
https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/135272
Add a new helper to manage IR metadata that can be progated to generated instructions for recipes.
This helps to remove a number of remaining uses of getUnderlyingInstr during VPlan execution.
>From 091158594e9c806ed047257482bd2180ba99a6d1 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Wed, 9 Apr 2025 12:35:39 +0100
Subject: [PATCH] [VPlan] Manage instruction medata in VPlan.
Add a new helper to manage IR metadata that can be progated to generated
instructions for recipes.
This helps to remove a number of remaining uses of getUnderlyingInstr
during VPlan execution.
---
llvm/lib/Transforms/Vectorize/VPlan.cpp | 20 ++-----
llvm/lib/Transforms/Vectorize/VPlan.h | 52 +++++++++++++------
llvm/lib/Transforms/Vectorize/VPlanHelpers.h | 9 +---
.../lib/Transforms/Vectorize/VPlanRecipes.cpp | 35 +++++++++----
4 files changed, 65 insertions(+), 51 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index 9474e7a171dff..229949725128a 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -356,23 +356,13 @@ BasicBlock *VPTransformState::CFGState::getPreheaderBBFor(VPRecipeBase *R) {
return VPBB2IRBB[LoopRegion->getPreheaderVPBB()];
}
-void VPTransformState::addNewMetadata(Instruction *To,
- const Instruction *Orig) {
+void VPTransformState::addNewMetadata(Value *To, const Instruction *Orig) {
+
// If the loop was versioned with memchecks, add the corresponding no-alias
// metadata.
- if (LVer && isa<LoadInst, StoreInst>(Orig))
- LVer->annotateInstWithNoAlias(To, Orig);
-}
-
-void VPTransformState::addMetadata(Value *To, Instruction *From) {
- // No source instruction to transfer metadata from?
- if (!From)
- return;
-
- if (Instruction *ToI = dyn_cast<Instruction>(To)) {
- propagateMetadata(ToI, From);
- addNewMetadata(ToI, From);
- }
+ Instruction *ToI = dyn_cast<Instruction>(To);
+ if (ToI && LVer && isa<LoadInst, StoreInst>(Orig))
+ LVer->annotateInstWithNoAlias(ToI, Orig);
}
void VPTransformState::setDebugLocFrom(DebugLoc DL) {
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 669e8f371d3d3..11f637f7b1518 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -1114,18 +1114,33 @@ struct VPIRPhi : public VPIRInstruction {
#endif
};
+/// Helper to manage IR metadata for recipes. It filters out metadata that
+/// cannot be proagated.
+class VPWithIRMetadata {
+ SmallVector<std::pair<unsigned, MDNode *>> Metadata;
+
+public:
+ VPWithIRMetadata() {}
+
+ VPWithIRMetadata(Instruction &I) { getMetadataToPropagate(&I, Metadata); }
+
+ /// Add all metadata to \p V if it is an instruction.
+ void setMetadata(Value *V) const;
+};
+
/// VPWidenRecipe is a recipe for producing a widened instruction using the
/// opcode and operands of the recipe. This recipe covers most of the
/// traditional vectorization cases where each recipe transforms into a
/// vectorized version of itself.
-class VPWidenRecipe : public VPRecipeWithIRFlags {
+class VPWidenRecipe : public VPRecipeWithIRFlags, public VPWithIRMetadata {
unsigned Opcode;
protected:
template <typename IterT>
VPWidenRecipe(unsigned VPDefOpcode, Instruction &I,
iterator_range<IterT> Operands)
- : VPRecipeWithIRFlags(VPDefOpcode, Operands, I), Opcode(I.getOpcode()) {}
+ : VPRecipeWithIRFlags(VPDefOpcode, Operands, I), VPWithIRMetadata(I),
+ Opcode(I.getOpcode()) {}
public:
template <typename IterT>
@@ -1160,7 +1175,7 @@ class VPWidenRecipe : public VPRecipeWithIRFlags {
};
/// VPWidenCastRecipe is a recipe to create vector cast instructions.
-class VPWidenCastRecipe : public VPRecipeWithIRFlags {
+class VPWidenCastRecipe : public VPRecipeWithIRFlags, public VPWithIRMetadata {
/// Cast instruction opcode.
Instruction::CastOps Opcode;
@@ -1170,15 +1185,15 @@ class VPWidenCastRecipe : public VPRecipeWithIRFlags {
public:
VPWidenCastRecipe(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy,
CastInst &UI)
- : VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op, UI), Opcode(Opcode),
- ResultTy(ResultTy) {
+ : VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op, UI), VPWithIRMetadata(UI),
+ Opcode(Opcode), ResultTy(ResultTy) {
assert(UI.getOpcode() == Opcode &&
"opcode of underlying cast doesn't match");
}
VPWidenCastRecipe(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy)
- : VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op), Opcode(Opcode),
- ResultTy(ResultTy) {}
+ : VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op), VPWithIRMetadata(),
+ Opcode(Opcode), ResultTy(ResultTy) {}
~VPWidenCastRecipe() override = default;
@@ -1260,7 +1275,8 @@ class VPScalarCastRecipe : public VPSingleDefRecipe {
};
/// A recipe for widening vector intrinsics.
-class VPWidenIntrinsicRecipe : public VPRecipeWithIRFlags {
+class VPWidenIntrinsicRecipe : public VPRecipeWithIRFlags,
+ public VPWithIRMetadata {
/// ID of the vector intrinsic to widen.
Intrinsic::ID VectorIntrinsicID;
@@ -1281,8 +1297,8 @@ class VPWidenIntrinsicRecipe : public VPRecipeWithIRFlags {
ArrayRef<VPValue *> CallArguments, Type *Ty,
DebugLoc DL = {})
: VPRecipeWithIRFlags(VPDef::VPWidenIntrinsicSC, CallArguments, CI),
- VectorIntrinsicID(VectorIntrinsicID), ResultTy(Ty),
- MayReadFromMemory(CI.mayReadFromMemory()),
+ VPWithIRMetadata(CI), VectorIntrinsicID(VectorIntrinsicID),
+ ResultTy(Ty), MayReadFromMemory(CI.mayReadFromMemory()),
MayWriteToMemory(CI.mayWriteToMemory()),
MayHaveSideEffects(CI.mayHaveSideEffects()) {}
@@ -1346,7 +1362,7 @@ class VPWidenIntrinsicRecipe : public VPRecipeWithIRFlags {
};
/// A recipe for widening Call instructions using library calls.
-class VPWidenCallRecipe : public VPRecipeWithIRFlags {
+class VPWidenCallRecipe : public VPRecipeWithIRFlags, public VPWithIRMetadata {
/// Variant stores a pointer to the chosen function. There is a 1:1 mapping
/// between a given VF and the chosen vectorized variant, so there will be a
/// different VPlan for each VF with a valid variant.
@@ -1357,7 +1373,7 @@ class VPWidenCallRecipe : public VPRecipeWithIRFlags {
ArrayRef<VPValue *> CallArguments, DebugLoc DL = {})
: VPRecipeWithIRFlags(VPDef::VPWidenCallSC, CallArguments,
*cast<Instruction>(UV)),
- Variant(Variant) {
+ VPWithIRMetadata(*cast<Instruction>(UV)), Variant(Variant) {
assert(
isa<Function>(getOperand(getNumOperands() - 1)->getLiveInIRValue()) &&
"last operand must be the called function");
@@ -1443,10 +1459,12 @@ class VPHistogramRecipe : public VPRecipeBase {
};
/// A recipe for widening select instructions.
-struct VPWidenSelectRecipe : public VPRecipeWithIRFlags {
+struct VPWidenSelectRecipe : public VPRecipeWithIRFlags,
+ public VPWithIRMetadata {
template <typename IterT>
VPWidenSelectRecipe(SelectInst &I, iterator_range<IterT> Operands)
- : VPRecipeWithIRFlags(VPDef::VPWidenSelectSC, Operands, I) {}
+ : VPRecipeWithIRFlags(VPDef::VPWidenSelectSC, Operands, I),
+ VPWithIRMetadata(I) {}
~VPWidenSelectRecipe() override = default;
@@ -2564,7 +2582,7 @@ class VPPredInstPHIRecipe : public VPSingleDefRecipe {
/// A common base class for widening memory operations. An optional mask can be
/// provided as the last operand.
-class VPWidenMemoryRecipe : public VPRecipeBase {
+class VPWidenMemoryRecipe : public VPRecipeBase, public VPWithIRMetadata {
protected:
Instruction &Ingredient;
@@ -2588,8 +2606,8 @@ class VPWidenMemoryRecipe : public VPRecipeBase {
VPWidenMemoryRecipe(const char unsigned SC, Instruction &I,
std::initializer_list<VPValue *> Operands,
bool Consecutive, bool Reverse, DebugLoc DL)
- : VPRecipeBase(SC, Operands, DL), Ingredient(I), Consecutive(Consecutive),
- Reverse(Reverse) {
+ : VPRecipeBase(SC, Operands, DL), VPWithIRMetadata(I), Ingredient(I),
+ Consecutive(Consecutive), Reverse(Reverse) {
assert((Consecutive || !Reverse) && "Reverse implies consecutive");
}
diff --git a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
index bebea1915690f..4826dfd562c2d 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
@@ -288,14 +288,7 @@ struct VPTransformState {
/// Currently this is used to add the noalias annotations based on the
/// inserted memchecks. Use this for instructions that are *cloned* into the
/// vector loop.
- void addNewMetadata(Instruction *To, const Instruction *Orig);
-
- /// Add metadata from one instruction to another.
- ///
- /// This includes both the original MDs from \p From and additional ones (\see
- /// addNewMetadata). Use this for *newly created* instructions in the vector
- /// loop.
- void addMetadata(Value *To, Instruction *From);
+ void addNewMetadata(Value *To, const Instruction *Orig);
/// Set the debug location in the builder using the debug location \p DL.
void setDebugLocFrom(DebugLoc DL);
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 35e141ed01267..077867cbc7a92 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -1159,6 +1159,14 @@ void VPIRPhi::print(raw_ostream &O, const Twine &Indent,
}
#endif
+void VPWithIRMetadata::setMetadata(Value *V) const {
+ auto *I = dyn_cast<Instruction>(V);
+ if (!I)
+ return;
+ for (const auto &[Kind, Node] : Metadata)
+ I->setMetadata(Kind, Node);
+}
+
void VPWidenCallRecipe::execute(VPTransformState &State) {
assert(State.VF.isVector() && "not widening");
@@ -1189,7 +1197,7 @@ void VPWidenCallRecipe::execute(VPTransformState &State) {
if (!V->getType()->isVoidTy())
State.set(this, V);
- State.addMetadata(V, CI);
+ setMetadata(V);
}
InstructionCost VPWidenCallRecipe::computeCost(ElementCount VF,
@@ -1268,7 +1276,7 @@ void VPWidenIntrinsicRecipe::execute(VPTransformState &State) {
if (!V->getType()->isVoidTy())
State.set(this, V);
- State.addMetadata(V, CI);
+ setMetadata(V);
}
InstructionCost VPWidenIntrinsicRecipe::computeCost(ElementCount VF,
@@ -1465,7 +1473,7 @@ void VPWidenSelectRecipe::execute(VPTransformState &State) {
State.set(this, Sel);
if (isa<FPMathOperator>(Sel))
setFlags(cast<Instruction>(Sel));
- State.addMetadata(Sel, dyn_cast_or_null<Instruction>(getUnderlyingValue()));
+ setMetadata(Sel);
}
InstructionCost VPWidenSelectRecipe::computeCost(ElementCount VF,
@@ -1601,7 +1609,7 @@ void VPWidenRecipe::execute(VPTransformState &State) {
// Use this vector value for all users of the original instruction.
State.set(this, V);
- State.addMetadata(V, dyn_cast_or_null<Instruction>(getUnderlyingValue()));
+ setMetadata(V);
break;
}
case Instruction::ExtractValue: {
@@ -1634,7 +1642,7 @@ void VPWidenRecipe::execute(VPTransformState &State) {
C = Builder.CreateICmp(getPredicate(), A, B);
}
State.set(this, C);
- State.addMetadata(C, dyn_cast_or_null<Instruction>(getUnderlyingValue()));
+ setMetadata(C);
break;
}
default:
@@ -1750,9 +1758,10 @@ void VPWidenCastRecipe::execute(VPTransformState &State) {
Value *A = State.get(Op);
Value *Cast = Builder.CreateCast(Instruction::CastOps(Opcode), A, DestTy);
State.set(this, Cast);
- State.addMetadata(Cast, cast_or_null<Instruction>(getUnderlyingValue()));
- if (auto *CastOp = dyn_cast<Instruction>(Cast))
+ if (auto *CastOp = dyn_cast<Instruction>(Cast)) {
setFlags(CastOp);
+ setMetadata(CastOp);
+ }
}
InstructionCost VPWidenCastRecipe::computeCost(ElementCount VF,
@@ -2735,7 +2744,8 @@ void VPWidenLoadRecipe::execute(VPTransformState &State) {
NewLI = Builder.CreateAlignedLoad(DataTy, Addr, Alignment, "wide.load");
}
// Add metadata to the load, but setVectorValue to the reverse shuffle.
- State.addMetadata(NewLI, LI);
+ State.addNewMetadata(NewLI, LI);
+ setMetadata(NewLI);
if (Reverse)
NewLI = Builder.CreateVectorReverse(NewLI, "reverse");
State.set(this, NewLI);
@@ -2795,7 +2805,8 @@ void VPWidenLoadEVLRecipe::execute(VPTransformState &State) {
}
NewLI->addParamAttr(
0, Attribute::getWithAlignment(NewLI->getContext(), Alignment));
- State.addMetadata(NewLI, LI);
+ State.addNewMetadata(NewLI, LI);
+ setMetadata(NewLI);
Instruction *Res = NewLI;
if (isReverse())
Res = createReverseEVL(Builder, Res, EVL, "vp.reverse");
@@ -2871,7 +2882,8 @@ void VPWidenStoreRecipe::execute(VPTransformState &State) {
NewSI = Builder.CreateMaskedStore(StoredVal, Addr, Alignment, Mask);
else
NewSI = Builder.CreateAlignedStore(StoredVal, Addr, Alignment);
- State.addMetadata(NewSI, SI);
+ State.addNewMetadata(NewSI, SI);
+ setMetadata(NewSI);
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -2918,7 +2930,8 @@ void VPWidenStoreEVLRecipe::execute(VPTransformState &State) {
}
NewSI->addParamAttr(
1, Attribute::getWithAlignment(NewSI->getContext(), Alignment));
- State.addMetadata(NewSI, SI);
+ State.addNewMetadata(NewSI, SI);
+ setMetadata(NewSI);
}
InstructionCost VPWidenStoreEVLRecipe::computeCost(ElementCount VF,
More information about the llvm-commits
mailing list