[llvm] [VPlan] Fold VPDef into VPRecipeBase (NFC). (PR #174282)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Sun Jan 11 08:58:45 PST 2026
https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/174282
>From 4065d582bcbab37c6ac09e8747e16faf12734a60 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Fri, 2 Jan 2026 20:18:02 +0000
Subject: [PATCH 1/3] [VPlan] Merge VPDef into VPRecipeBase (NFC).
A separate VDef is not needed any longer, fold i into VPRecipeBase to
simplify code and class hierarchy.
Depends on https://github.com/llvm/llvm-project/pull/172758.
---
llvm/docs/VectorizationPlan.rst | 8 +-
.../Transforms/Vectorize/LoopVectorize.cpp | 66 +--
llvm/lib/Transforms/Vectorize/VPlan.cpp | 12 +-
llvm/lib/Transforms/Vectorize/VPlan.h | 433 +++++++++++-------
.../lib/Transforms/Vectorize/VPlanRecipes.cpp | 14 +-
.../Transforms/Vectorize/VPlanTransforms.cpp | 8 +-
llvm/lib/Transforms/Vectorize/VPlanValue.h | 161 +------
.../Transforms/Vectorize/VPlanTest.cpp | 59 +--
8 files changed, 342 insertions(+), 419 deletions(-)
diff --git a/llvm/docs/VectorizationPlan.rst b/llvm/docs/VectorizationPlan.rst
index 73e9e6098175a..b8db8cab843cf 100644
--- a/llvm/docs/VectorizationPlan.rst
+++ b/llvm/docs/VectorizationPlan.rst
@@ -186,7 +186,8 @@ The low-level design of VPlan comprises of the following classes.
input IR instructions are referred to as "Ingredients" of the Recipe. A Recipe
may specify how its ingredients are to be transformed to produce the output IR
instructions; e.g., cloned once, replicated multiple times or widened
- according to selected VF.
+ according to selected VF. VPRecipeBase also defines zero, one or multiple
+ VPValues, modeling the fact that recipes can produce multiple results.
:VPValue:
The base of VPlan's def-use relations class hierarchy. When instantiated, it
@@ -197,11 +198,6 @@ The low-level design of VPlan comprises of the following classes.
A VPUser represents an entity that uses a number of VPValues as operands.
VPUser is similar in some aspects to LLVM's User class.
-:VPDef:
- A VPDef represents an entity that defines zero, one or multiple VPValues.
- It is used to model the fact that recipes in VPlan can define multiple
- VPValues.
-
:VPInstruction:
A VPInstruction is a recipe characterized by a single opcode and optional
flags, free of ingredients or other meta-data. VPInstructions also extend
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index b61890aaa3ded..92447c737e9c7 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -4111,40 +4111,40 @@ static bool willGenerateVectors(VPlan &Plan, ElementCount VF,
// result. Note that this includes VPInstruction where some opcodes may
// produce a vector, to preserve existing behavior as VPInstructions model
// aspects not directly mapped to existing IR instructions.
- switch (R.getVPDefID()) {
- case VPDef::VPDerivedIVSC:
- case VPDef::VPScalarIVStepsSC:
- case VPDef::VPReplicateSC:
- case VPDef::VPInstructionSC:
- case VPDef::VPCanonicalIVPHISC:
- case VPDef::VPVectorPointerSC:
- case VPDef::VPVectorEndPointerSC:
- case VPDef::VPExpandSCEVSC:
- case VPDef::VPEVLBasedIVPHISC:
- case VPDef::VPPredInstPHISC:
- case VPDef::VPBranchOnMaskSC:
+ switch (R.getVPRecipeID()) {
+ case VPRecipeBase::VPDerivedIVSC:
+ case VPRecipeBase::VPScalarIVStepsSC:
+ case VPRecipeBase::VPReplicateSC:
+ case VPRecipeBase::VPInstructionSC:
+ case VPRecipeBase::VPCanonicalIVPHISC:
+ case VPRecipeBase::VPVectorPointerSC:
+ case VPRecipeBase::VPVectorEndPointerSC:
+ case VPRecipeBase::VPExpandSCEVSC:
+ case VPRecipeBase::VPEVLBasedIVPHISC:
+ case VPRecipeBase::VPPredInstPHISC:
+ case VPRecipeBase::VPBranchOnMaskSC:
continue;
- case VPDef::VPReductionSC:
- case VPDef::VPActiveLaneMaskPHISC:
- case VPDef::VPWidenCallSC:
- case VPDef::VPWidenCanonicalIVSC:
- case VPDef::VPWidenCastSC:
- case VPDef::VPWidenGEPSC:
- case VPDef::VPWidenIntrinsicSC:
- case VPDef::VPWidenSC:
- case VPDef::VPBlendSC:
- case VPDef::VPFirstOrderRecurrencePHISC:
- case VPDef::VPHistogramSC:
- case VPDef::VPWidenPHISC:
- case VPDef::VPWidenIntOrFpInductionSC:
- case VPDef::VPWidenPointerInductionSC:
- case VPDef::VPReductionPHISC:
- case VPDef::VPInterleaveEVLSC:
- case VPDef::VPInterleaveSC:
- case VPDef::VPWidenLoadEVLSC:
- case VPDef::VPWidenLoadSC:
- case VPDef::VPWidenStoreEVLSC:
- case VPDef::VPWidenStoreSC:
+ case VPRecipeBase::VPReductionSC:
+ case VPRecipeBase::VPActiveLaneMaskPHISC:
+ case VPRecipeBase::VPWidenCallSC:
+ case VPRecipeBase::VPWidenCanonicalIVSC:
+ case VPRecipeBase::VPWidenCastSC:
+ case VPRecipeBase::VPWidenGEPSC:
+ case VPRecipeBase::VPWidenIntrinsicSC:
+ case VPRecipeBase::VPWidenSC:
+ case VPRecipeBase::VPBlendSC:
+ case VPRecipeBase::VPFirstOrderRecurrencePHISC:
+ case VPRecipeBase::VPHistogramSC:
+ case VPRecipeBase::VPWidenPHISC:
+ case VPRecipeBase::VPWidenIntOrFpInductionSC:
+ case VPRecipeBase::VPWidenPointerInductionSC:
+ case VPRecipeBase::VPReductionPHISC:
+ case VPRecipeBase::VPInterleaveEVLSC:
+ case VPRecipeBase::VPInterleaveSC:
+ case VPRecipeBase::VPWidenLoadEVLSC:
+ case VPRecipeBase::VPWidenLoadSC:
+ case VPRecipeBase::VPWidenStoreEVLSC:
+ case VPRecipeBase::VPWidenStoreSC:
break;
default:
llvm_unreachable("unhandled recipe");
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index a6a46e36b397d..5f050627a1fbc 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -107,10 +107,8 @@ void VPValue::dump() const {
dbgs() << "\n";
}
-void VPDef::dump() const {
- const VPRecipeBase *Instr = dyn_cast_or_null<VPRecipeBase>(this);
- VPSlotTracker SlotTracker(
- (Instr && Instr->getParent()) ? Instr->getParent()->getPlan() : nullptr);
+void VPRecipeBase::dump() const {
+ VPSlotTracker SlotTracker(getParent() ? getParent()->getPlan() : nullptr);
print(dbgs(), "", SlotTracker);
dbgs() << "\n";
}
@@ -120,14 +118,14 @@ VPRecipeBase *VPValue::getDefiningRecipe() {
auto *DefValue = dyn_cast<VPRecipeValue>(this);
if (!DefValue)
return nullptr;
- return cast<VPRecipeBase>(DefValue->Def);
+ return DefValue->Def;
}
const VPRecipeBase *VPValue::getDefiningRecipe() const {
auto *DefValue = dyn_cast<VPRecipeValue>(this);
if (!DefValue)
return nullptr;
- return cast<VPRecipeBase>(DefValue->Def);
+ return DefValue->Def;
}
Value *VPValue::getLiveInIRValue() const {
@@ -136,7 +134,7 @@ Value *VPValue::getLiveInIRValue() const {
Type *VPIRValue::getType() const { return getUnderlyingValue()->getType(); }
-VPRecipeValue::VPRecipeValue(VPDef *Def, Value *UV)
+VPRecipeValue::VPRecipeValue(VPRecipeBase *Def, Value *UV)
: VPValue(VPVRecipeValueSC, UV), Def(Def) {
assert(Def && "VPRecipeValue requires a defining recipe");
Def->addDefinedValue(this);
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 0fa5180f690ab..c054be345d008 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -377,16 +377,16 @@ class LLVM_ABI_FOR_TEST VPBlockBase {
};
/// VPRecipeBase is a base class modeling a sequence of one or more output IR
-/// instructions. VPRecipeBase owns the VPValues it defines through VPDef
-/// and is responsible for deleting its defined values. Single-value
-/// recipes must inherit from VPSingleDef instead of inheriting from both
-/// VPRecipeBase and VPValue separately.
+/// instructions. VPRecipeBase owns the VPValues it defines and is responsible
+/// for deleting its defined values. Single-value recipes must inherit from
+/// VPSingleDefRecipe instead of inheriting from both VPRecipeBase and VPValue
+/// separately.
class LLVM_ABI_FOR_TEST VPRecipeBase
: public ilist_node_with_parent<VPRecipeBase, VPBasicBlock>,
- public VPDef,
public VPUser {
friend VPBasicBlock;
friend class VPBlockUtils;
+ friend class VPRecipeValue;
/// Each VPRecipe belongs to a single VPBasicBlock.
VPBasicBlock *Parent = nullptr;
@@ -394,12 +394,133 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
/// The debug location for the recipe.
DebugLoc DL;
+ /// Subclass identifier (for isa/dyn_cast).
+ const unsigned char SubclassID;
+
+ /// The VPValues defined by this VPRecipeBase.
+ TinyPtrVector<VPRecipeValue *> DefinedValues;
+
+ /// Add \p V as a defined value by this VPRecipeBase.
+ void addDefinedValue(VPRecipeValue *V) {
+ assert(V->Def == this &&
+ "can only add VPValue already linked with this VPRecipeBase");
+ DefinedValues.push_back(V);
+ }
+
+ /// Remove \p V from the values defined by this VPRecipeBase. \p V must be a
+ /// defined value of this VPRecipeBase.
+ void removeDefinedValue(VPRecipeValue *V) {
+ assert(V->Def == this &&
+ "can only remove VPValue linked with this VPRecipeBase");
+ assert(is_contained(DefinedValues, V) &&
+ "VPValue to remove must be in DefinedValues");
+ llvm::erase(DefinedValues, V);
+ V->Def = nullptr;
+ }
+
public:
+ /// An enumeration for keeping track of the concrete subclass of VPRecipeBase
+ /// that is actually instantiated. Values of this enumeration are kept in the
+ /// SubclassID field of the VPRecipeBase objects. They are used for concrete
+ /// type identification.
+ using VPRecipeTy = enum {
+ VPBranchOnMaskSC,
+ VPDerivedIVSC,
+ VPExpandSCEVSC,
+ VPExpressionSC,
+ VPIRInstructionSC,
+ VPInstructionSC,
+ VPInterleaveEVLSC,
+ VPInterleaveSC,
+ VPReductionEVLSC,
+ VPReductionSC,
+ VPReplicateSC,
+ VPScalarIVStepsSC,
+ VPVectorPointerSC,
+ VPVectorEndPointerSC,
+ VPWidenCallSC,
+ VPWidenCanonicalIVSC,
+ VPWidenCastSC,
+ VPWidenGEPSC,
+ VPWidenIntrinsicSC,
+ VPWidenLoadEVLSC,
+ VPWidenLoadSC,
+ VPWidenStoreEVLSC,
+ VPWidenStoreSC,
+ VPWidenSC,
+ VPWidenSelectSC,
+ VPBlendSC,
+ VPHistogramSC,
+ // START: Phi-like recipes. Need to be kept together.
+ VPWidenPHISC,
+ VPPredInstPHISC,
+ // START: SubclassID for recipes that inherit VPHeaderPHIRecipe.
+ // VPHeaderPHIRecipe need to be kept together.
+ VPCanonicalIVPHISC,
+ VPActiveLaneMaskPHISC,
+ VPEVLBasedIVPHISC,
+ VPFirstOrderRecurrencePHISC,
+ VPWidenIntOrFpInductionSC,
+ VPWidenPointerInductionSC,
+ VPReductionPHISC,
+ // END: SubclassID for recipes that inherit VPHeaderPHIRecipe
+ // END: Phi-like recipes
+ VPFirstPHISC = VPWidenPHISC,
+ VPFirstHeaderPHISC = VPCanonicalIVPHISC,
+ VPLastHeaderPHISC = VPReductionPHISC,
+ VPLastPHISC = VPReductionPHISC,
+ };
+
VPRecipeBase(const unsigned char SC, ArrayRef<VPValue *> Operands,
DebugLoc DL = DebugLoc::getUnknown())
- : VPDef(SC), VPUser(Operands), DL(DL) {}
+ : VPUser(Operands), DL(DL), SubclassID(SC) {}
+
+ virtual ~VPRecipeBase() {
+ for (VPRecipeValue *D : to_vector(DefinedValues)) {
+ assert(
+ D->Def == this &&
+ "all defined VPValues should point to the containing VPRecipeBase");
+ assert(D->getNumUsers() == 0 &&
+ "all defined VPValues should have no more users");
+ delete D;
+ }
+ }
+
+ /// Returns the only VPValue defined by the VPRecipeBase. Can only be called
+ /// for VPRecipeBases with a single defined value.
+ VPValue *getVPSingleValue() {
+ assert(DefinedValues.size() == 1 && "must have exactly one defined value");
+ assert(DefinedValues[0] && "defined value must be non-null");
+ return DefinedValues[0];
+ }
+ const VPValue *getVPSingleValue() const {
+ assert(DefinedValues.size() == 1 && "must have exactly one defined value");
+ assert(DefinedValues[0] && "defined value must be non-null");
+ return DefinedValues[0];
+ }
+
+ /// Returns the VPValue with index \p I defined by the VPRecipeBase.
+ VPValue *getVPValue(unsigned I) {
+ assert(DefinedValues[I] && "defined value must be non-null");
+ return DefinedValues[I];
+ }
+ const VPValue *getVPValue(unsigned I) const {
+ assert(DefinedValues[I] && "defined value must be non-null");
+ return DefinedValues[I];
+ }
+
+ /// Returns an ArrayRef of the values defined by the VPRecipeBase.
+ ArrayRef<VPRecipeValue *> definedValues() { return DefinedValues; }
+ /// Returns an ArrayRef of the values defined by the VPRecipeBase.
+ ArrayRef<VPRecipeValue *> definedValues() const { return DefinedValues; }
- ~VPRecipeBase() override = default;
+ /// Returns the number of values defined by the VPRecipeBase.
+ unsigned getNumDefinedValues() const { return DefinedValues.size(); }
+
+ /// \return an ID for the concrete type of this object.
+ /// This is used to implement the classof checks. This should not be used
+ /// for any other purpose, as the values may change as LLVM evolves.
+ unsigned getVPRecipeID() const { return SubclassID; }
/// Clone the current recipe.
virtual VPRecipeBase *clone() = 0;
@@ -451,11 +572,6 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
iplist<VPRecipeBase>::iterator eraseFromParent();
/// Method to support type inquiry through isa, cast, and dyn_cast.
- static inline bool classof(const VPDef *D) {
- // All VPDefs are also VPRecipeBases.
- return true;
- }
-
static inline bool classof(const VPUser *U) { return true; }
/// Returns true if the recipe may have side-effects.
@@ -485,9 +601,12 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
void setDebugLoc(DebugLoc NewDL) { DL = NewDL; }
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ /// Dump the recipe to stderr (for debugging).
+ LLVM_ABI_FOR_TEST void dump() const;
+
/// Print the recipe, delegating to printRecipe().
void print(raw_ostream &O, const Twine &Indent,
- VPSlotTracker &SlotTracker) const override final;
+ VPSlotTracker &SlotTracker) const;
#endif
protected:
@@ -506,23 +625,20 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
};
// Helper macro to define common classof implementations for recipes.
-#define VP_CLASSOF_IMPL(VPDefID) \
- static inline bool classof(const VPDef *D) { \
- return D->getVPDefID() == VPDefID; \
+#define VP_CLASSOF_IMPL(VPRecipeID) \
+ static inline bool classof(const VPRecipeBase *R) { \
+ return R->getVPRecipeID() == VPRecipeID; \
} \
static inline bool classof(const VPValue *V) { \
auto *R = V->getDefiningRecipe(); \
- return R && R->getVPDefID() == VPDefID; \
+ return R && R->getVPRecipeID() == VPRecipeID; \
} \
static inline bool classof(const VPUser *U) { \
auto *R = dyn_cast<VPRecipeBase>(U); \
- return R && R->getVPDefID() == VPDefID; \
- } \
- static inline bool classof(const VPRecipeBase *R) { \
- return R->getVPDefID() == VPDefID; \
+ return R && R->getVPRecipeID() == VPRecipeID; \
} \
static inline bool classof(const VPSingleDefRecipe *R) { \
- return R->getVPDefID() == VPDefID; \
+ return R->getVPRecipeID() == VPRecipeID; \
}
/// VPSingleDef is a base class for recipes for modeling a sequence of one or
@@ -539,7 +655,7 @@ class VPSingleDefRecipe : public VPRecipeBase, public VPRecipeValue {
: VPRecipeBase(SC, Operands, DL), VPRecipeValue(this, UV) {}
static inline bool classof(const VPRecipeBase *R) {
- switch (R->getVPDefID()) {
+ switch (R->getVPRecipeID()) {
case VPRecipeBase::VPDerivedIVSC:
case VPRecipeBase::VPEVLBasedIVPHISC:
case VPRecipeBase::VPExpandSCEVSC:
@@ -580,7 +696,7 @@ class VPSingleDefRecipe : public VPRecipeBase, public VPRecipeValue {
// the recipes to be able to make widened loads VPSingleDefRecipes.
return false;
}
- llvm_unreachable("Unhandled VPDefID");
+ llvm_unreachable("Unhandled VPRecipeID");
}
static inline bool classof(const VPUser *U) {
@@ -926,17 +1042,17 @@ struct VPRecipeWithIRFlags : public VPSingleDefRecipe, public VPIRFlags {
: VPSingleDefRecipe(SC, Operands, DL), VPIRFlags(Flags) {}
static inline bool classof(const VPRecipeBase *R) {
- return R->getVPDefID() == VPRecipeBase::VPInstructionSC ||
- R->getVPDefID() == VPRecipeBase::VPWidenSC ||
- R->getVPDefID() == VPRecipeBase::VPWidenGEPSC ||
- R->getVPDefID() == VPRecipeBase::VPWidenCallSC ||
- R->getVPDefID() == VPRecipeBase::VPWidenCastSC ||
- R->getVPDefID() == VPRecipeBase::VPWidenIntrinsicSC ||
- R->getVPDefID() == VPRecipeBase::VPReductionSC ||
- R->getVPDefID() == VPRecipeBase::VPReductionEVLSC ||
- R->getVPDefID() == VPRecipeBase::VPReplicateSC ||
- R->getVPDefID() == VPRecipeBase::VPVectorEndPointerSC ||
- R->getVPDefID() == VPRecipeBase::VPVectorPointerSC;
+ return R->getVPRecipeID() == VPRecipeBase::VPInstructionSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPWidenSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPWidenGEPSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPWidenCallSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPWidenCastSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPWidenIntrinsicSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPReductionSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPReductionEVLSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPReplicateSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPVectorEndPointerSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPVectorPointerSC;
}
static inline bool classof(const VPUser *U) {
@@ -945,15 +1061,14 @@ struct VPRecipeWithIRFlags : public VPSingleDefRecipe, public VPIRFlags {
}
static inline bool classof(const VPValue *V) {
- auto *R = dyn_cast_or_null<VPRecipeBase>(V->getDefiningRecipe());
+ auto *R = V->getDefiningRecipe();
return R && classof(R);
}
VPRecipeWithIRFlags *clone() override = 0;
- static inline bool classof(const VPSingleDefRecipe *U) {
- auto *R = dyn_cast<VPRecipeBase>(U);
- return R && classof(R);
+ static inline bool classof(const VPSingleDefRecipe *R) {
+ return classof(static_cast<const VPRecipeBase *>(R));
}
void execute(VPTransformState &State) override = 0;
@@ -1178,7 +1293,7 @@ class LLVM_ABI_FOR_TEST VPInstruction : public VPRecipeWithIRFlags,
const VPIRFlags &Flags = {}, const VPIRMetadata &MD = {},
DebugLoc DL = DebugLoc::getUnknown(), const Twine &Name = "");
- VP_CLASSOF_IMPL(VPDef::VPInstructionSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPInstructionSC)
VPInstruction *clone() override {
auto *New = new VPInstruction(Opcode, operands(), *this, *this,
@@ -1260,7 +1375,7 @@ class LLVM_ABI_FOR_TEST VPInstruction : public VPRecipeWithIRFlags,
/// A specialization of VPInstruction augmenting it with a dedicated result
/// type, to be used when the opcode and operands of the VPInstruction don't
-/// directly determine the result type. Note that there is no separate VPDef ID
+/// directly determine the result type. Note that there is no separate recipe ID
/// for VPInstructionWithType; it shares the same ID as VPInstruction and is
/// distinguished purely by the opcode.
class VPInstructionWithType : public VPInstruction {
@@ -1430,7 +1545,8 @@ class VPIRInstruction : public VPRecipeBase {
/// VPIRInstruction::create() should be used to create VPIRInstructions, as
/// subclasses may need to be created, e.g. VPIRPhi.
VPIRInstruction(Instruction &I)
- : VPRecipeBase(VPDef::VPIRInstructionSC, ArrayRef<VPValue *>()), I(I) {}
+ : VPRecipeBase(VPRecipeBase::VPIRInstructionSC, ArrayRef<VPValue *>()),
+ I(I) {}
public:
~VPIRInstruction() override = default;
@@ -1439,7 +1555,7 @@ class VPIRInstruction : public VPRecipeBase {
/// VPIRInstruction.
LLVM_ABI_FOR_TEST static VPIRInstruction *create(Instruction &I);
- VP_CLASSOF_IMPL(VPDef::VPIRInstructionSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPIRInstructionSC)
VPIRInstruction *clone() override {
auto *R = create(I);
@@ -1526,7 +1642,7 @@ class LLVM_ABI_FOR_TEST VPWidenRecipe : public VPRecipeWithIRFlags,
VPWidenRecipe(Instruction &I, ArrayRef<VPValue *> Operands,
const VPIRFlags &Flags = {}, const VPIRMetadata &Metadata = {},
DebugLoc DL = {})
- : VPRecipeWithIRFlags(VPDef::VPWidenSC, Operands, Flags, DL),
+ : VPRecipeWithIRFlags(VPRecipeBase::VPWidenSC, Operands, Flags, DL),
VPIRMetadata(Metadata), Opcode(I.getOpcode()) {
setUnderlyingValue(&I);
}
@@ -1538,7 +1654,7 @@ class LLVM_ABI_FOR_TEST VPWidenRecipe : public VPRecipeWithIRFlags,
getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPWidenSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPWidenSC)
/// Produce a widened instruction using the opcode and operands of the recipe,
/// processing State.VF elements.
@@ -1579,7 +1695,7 @@ class VPWidenCastRecipe : public VPRecipeWithIRFlags, public VPIRMetadata {
CastInst *CI = nullptr, const VPIRFlags &Flags = {},
const VPIRMetadata &Metadata = {},
DebugLoc DL = DebugLoc::getUnknown())
- : VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op, Flags, DL),
+ : VPRecipeWithIRFlags(VPRecipeBase::VPWidenCastSC, Op, Flags, DL),
VPIRMetadata(Metadata), Opcode(Opcode), ResultTy(ResultTy) {
assert(flagsValidForOpcode(Opcode) &&
"Set flags not supported for the provided opcode");
@@ -1594,7 +1710,7 @@ class VPWidenCastRecipe : public VPRecipeWithIRFlags, public VPIRMetadata {
*this, *this, getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPWidenCastSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPWidenCastSC)
/// Produce widened copies of the cast.
LLVM_ABI_FOR_TEST void execute(VPTransformState &State) override;
@@ -1639,8 +1755,8 @@ class VPWidenIntrinsicRecipe : public VPRecipeWithIRFlags, public VPIRMetadata {
const VPIRFlags &Flags = {},
const VPIRMetadata &MD = {},
DebugLoc DL = DebugLoc::getUnknown())
- : VPRecipeWithIRFlags(VPDef::VPWidenIntrinsicSC, CallArguments, Flags,
- DL),
+ : VPRecipeWithIRFlags(VPRecipeBase::VPWidenIntrinsicSC, CallArguments,
+ Flags, DL),
VPIRMetadata(MD), VectorIntrinsicID(VectorIntrinsicID), ResultTy(Ty),
MayReadFromMemory(CI.mayReadFromMemory()),
MayWriteToMemory(CI.mayWriteToMemory()),
@@ -1653,8 +1769,8 @@ class VPWidenIntrinsicRecipe : public VPRecipeWithIRFlags, public VPIRMetadata {
const VPIRFlags &Flags = {},
const VPIRMetadata &Metadata = {},
DebugLoc DL = DebugLoc::getUnknown())
- : VPRecipeWithIRFlags(VPDef::VPWidenIntrinsicSC, CallArguments, Flags,
- DL),
+ : VPRecipeWithIRFlags(VPRecipeBase::VPWidenIntrinsicSC, CallArguments,
+ Flags, DL),
VPIRMetadata(Metadata), VectorIntrinsicID(VectorIntrinsicID),
ResultTy(Ty) {
LLVMContext &Ctx = Ty->getContext();
@@ -1678,7 +1794,7 @@ class VPWidenIntrinsicRecipe : public VPRecipeWithIRFlags, public VPIRMetadata {
*this, *this, getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPWidenIntrinsicSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPWidenIntrinsicSC)
/// Produce a widened version of the vector intrinsic.
LLVM_ABI_FOR_TEST void execute(VPTransformState &State) override;
@@ -1728,7 +1844,8 @@ class LLVM_ABI_FOR_TEST VPWidenCallRecipe : public VPRecipeWithIRFlags,
ArrayRef<VPValue *> CallArguments,
const VPIRFlags &Flags = {},
const VPIRMetadata &Metadata = {}, DebugLoc DL = {})
- : VPRecipeWithIRFlags(VPDef::VPWidenCallSC, CallArguments, Flags, DL),
+ : VPRecipeWithIRFlags(VPRecipeBase::VPWidenCallSC, CallArguments, Flags,
+ DL),
VPIRMetadata(Metadata), Variant(Variant) {
setUnderlyingValue(UV);
assert(
@@ -1743,7 +1860,7 @@ class LLVM_ABI_FOR_TEST VPWidenCallRecipe : public VPRecipeWithIRFlags,
*this, *this, getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPWidenCallSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPWidenCallSC)
/// Produce a widened version of the call instruction.
void execute(VPTransformState &State) override;
@@ -1779,7 +1896,8 @@ class VPHistogramRecipe : public VPRecipeBase {
public:
VPHistogramRecipe(unsigned Opcode, ArrayRef<VPValue *> Operands,
DebugLoc DL = DebugLoc::getUnknown())
- : VPRecipeBase(VPDef::VPHistogramSC, Operands, DL), Opcode(Opcode) {}
+ : VPRecipeBase(VPRecipeBase::VPHistogramSC, Operands, DL),
+ Opcode(Opcode) {}
~VPHistogramRecipe() override = default;
@@ -1787,7 +1905,7 @@ class VPHistogramRecipe : public VPRecipeBase {
return new VPHistogramRecipe(Opcode, operands(), getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPHistogramSC);
+ VP_CLASSOF_IMPL(VPRecipeBase::VPHistogramSC);
/// Produce a vectorized histogram operation.
void execute(VPTransformState &State) override;
@@ -1828,7 +1946,7 @@ class LLVM_ABI_FOR_TEST VPWidenGEPRecipe : public VPRecipeWithIRFlags {
VPWidenGEPRecipe(GetElementPtrInst *GEP, ArrayRef<VPValue *> Operands,
const VPIRFlags &Flags = {},
DebugLoc DL = DebugLoc::getUnknown())
- : VPRecipeWithIRFlags(VPDef::VPWidenGEPSC, Operands, Flags, DL),
+ : VPRecipeWithIRFlags(VPRecipeBase::VPWidenGEPSC, Operands, Flags, DL),
SourceElementTy(GEP->getSourceElementType()) {
setUnderlyingValue(GEP);
SmallVector<std::pair<unsigned, MDNode *>> Metadata;
@@ -1844,7 +1962,7 @@ class LLVM_ABI_FOR_TEST VPWidenGEPRecipe : public VPRecipeWithIRFlags {
operands(), *this, getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPWidenGEPSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPWidenGEPSC)
/// This recipe generates a GEP instruction.
unsigned getOpcode() const { return Instruction::GetElementPtr; }
@@ -1886,13 +2004,13 @@ class VPVectorEndPointerRecipe : public VPRecipeWithIRFlags,
public:
VPVectorEndPointerRecipe(VPValue *Ptr, VPValue *VF, Type *IndexedTy,
int64_t Stride, GEPNoWrapFlags GEPFlags, DebugLoc DL)
- : VPRecipeWithIRFlags(VPDef::VPVectorEndPointerSC,
+ : VPRecipeWithIRFlags(VPRecipeBase::VPVectorEndPointerSC,
ArrayRef<VPValue *>({Ptr, VF}), GEPFlags, DL),
IndexedTy(IndexedTy), Stride(Stride) {
assert(Stride < 0 && "Stride must be negative");
}
- VP_CLASSOF_IMPL(VPDef::VPVectorEndPointerSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPVectorEndPointerSC)
VPValue *getVFValue() { return getOperand(1); }
const VPValue *getVFValue() const { return getOperand(1); }
@@ -1943,10 +2061,10 @@ class VPVectorPointerRecipe : public VPRecipeWithIRFlags {
public:
VPVectorPointerRecipe(VPValue *Ptr, Type *SourceElementTy,
GEPNoWrapFlags GEPFlags, DebugLoc DL)
- : VPRecipeWithIRFlags(VPDef::VPVectorPointerSC, Ptr, GEPFlags, DL),
+ : VPRecipeWithIRFlags(VPRecipeBase::VPVectorPointerSC, Ptr, GEPFlags, DL),
SourceElementTy(SourceElementTy) {}
- VP_CLASSOF_IMPL(VPDef::VPVectorPointerSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPVectorPointerSC)
VPValue *getOffset() {
return getNumOperands() == 2 ? getOperand(1) : nullptr;
@@ -2019,9 +2137,9 @@ class VPVectorPointerRecipe : public VPRecipeWithIRFlags {
class LLVM_ABI_FOR_TEST VPHeaderPHIRecipe : public VPSingleDefRecipe,
public VPPhiAccessors {
protected:
- VPHeaderPHIRecipe(unsigned char VPDefID, Instruction *UnderlyingInstr,
+ VPHeaderPHIRecipe(unsigned char VPRecipeID, Instruction *UnderlyingInstr,
VPValue *Start, DebugLoc DL = DebugLoc::getUnknown())
- : VPSingleDefRecipe(VPDefID, ArrayRef<VPValue *>({Start}),
+ : VPSingleDefRecipe(VPRecipeID, ArrayRef<VPValue *>({Start}),
UnderlyingInstr, DL) {}
const VPRecipeBase *getAsRecipe() const override { return this; }
@@ -2031,8 +2149,8 @@ class LLVM_ABI_FOR_TEST VPHeaderPHIRecipe : public VPSingleDefRecipe,
/// Method to support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const VPRecipeBase *R) {
- return R->getVPDefID() >= VPDef::VPFirstHeaderPHISC &&
- R->getVPDefID() <= VPDef::VPLastHeaderPHISC;
+ return R->getVPRecipeID() >= VPRecipeBase::VPFirstHeaderPHISC &&
+ R->getVPRecipeID() <= VPRecipeBase::VPLastHeaderPHISC;
}
static inline bool classof(const VPValue *V) {
return isa<VPHeaderPHIRecipe>(V->getDefiningRecipe());
@@ -2096,8 +2214,8 @@ class VPWidenInductionRecipe : public VPHeaderPHIRecipe {
}
static inline bool classof(const VPRecipeBase *R) {
- return R->getVPDefID() == VPDef::VPWidenIntOrFpInductionSC ||
- R->getVPDefID() == VPDef::VPWidenPointerInductionSC;
+ return R->getVPRecipeID() == VPRecipeBase::VPWidenIntOrFpInductionSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPWidenPointerInductionSC;
}
static inline bool classof(const VPValue *V) {
@@ -2173,8 +2291,8 @@ class VPWidenIntOrFpInductionRecipe : public VPWidenInductionRecipe,
VPWidenIntOrFpInductionRecipe(PHINode *IV, VPIRValue *Start, VPValue *Step,
VPValue *VF, const InductionDescriptor &IndDesc,
const VPIRFlags &Flags, DebugLoc DL)
- : VPWidenInductionRecipe(VPDef::VPWidenIntOrFpInductionSC, IV, Start,
- Step, IndDesc, DL),
+ : VPWidenInductionRecipe(VPRecipeBase::VPWidenIntOrFpInductionSC, IV,
+ Start, Step, IndDesc, DL),
VPIRFlags(Flags), Trunc(nullptr) {
addOperand(VF);
}
@@ -2183,8 +2301,8 @@ class VPWidenIntOrFpInductionRecipe : public VPWidenInductionRecipe,
VPValue *VF, const InductionDescriptor &IndDesc,
TruncInst *Trunc, const VPIRFlags &Flags,
DebugLoc DL)
- : VPWidenInductionRecipe(VPDef::VPWidenIntOrFpInductionSC, IV, Start,
- Step, IndDesc, DL),
+ : VPWidenInductionRecipe(VPRecipeBase::VPWidenIntOrFpInductionSC, IV,
+ Start, Step, IndDesc, DL),
VPIRFlags(Flags), Trunc(Trunc) {
addOperand(VF);
SmallVector<std::pair<unsigned, MDNode *>> Metadata;
@@ -2202,7 +2320,7 @@ class VPWidenIntOrFpInductionRecipe : public VPWidenInductionRecipe,
getInductionDescriptor(), Trunc, *this, getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPWidenIntOrFpInductionSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPWidenIntOrFpInductionSC)
void execute(VPTransformState &State) override {
llvm_unreachable("cannot execute this recipe, should be expanded via "
@@ -2261,8 +2379,8 @@ class VPWidenPointerInductionRecipe : public VPWidenInductionRecipe {
VPWidenPointerInductionRecipe(PHINode *Phi, VPValue *Start, VPValue *Step,
VPValue *NumUnrolledElems,
const InductionDescriptor &IndDesc, DebugLoc DL)
- : VPWidenInductionRecipe(VPDef::VPWidenPointerInductionSC, Phi, Start,
- Step, IndDesc, DL) {
+ : VPWidenInductionRecipe(VPRecipeBase::VPWidenPointerInductionSC, Phi,
+ Start, Step, IndDesc, DL) {
addOperand(NumUnrolledElems);
}
@@ -2274,7 +2392,7 @@ class VPWidenPointerInductionRecipe : public VPWidenInductionRecipe {
getOperand(2), getInductionDescriptor(), getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPWidenPointerInductionSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPWidenPointerInductionSC)
/// Generate vector values for the pointer induction.
void execute(VPTransformState &State) override {
@@ -2308,7 +2426,8 @@ class LLVM_ABI_FOR_TEST VPWidenPHIRecipe : public VPSingleDefRecipe,
/// debug location \p DL.
VPWidenPHIRecipe(PHINode *Phi, VPValue *Start = nullptr,
DebugLoc DL = DebugLoc::getUnknown(), const Twine &Name = "")
- : VPSingleDefRecipe(VPDef::VPWidenPHISC, {}, Phi, DL), Name(Name.str()) {
+ : VPSingleDefRecipe(VPRecipeBase::VPWidenPHISC, {}, Phi, DL),
+ Name(Name.str()) {
if (Start)
addOperand(Start);
}
@@ -2323,7 +2442,7 @@ class LLVM_ABI_FOR_TEST VPWidenPHIRecipe : public VPSingleDefRecipe,
~VPWidenPHIRecipe() override = default;
- VP_CLASSOF_IMPL(VPDef::VPWidenPHISC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPWidenPHISC)
/// Generate the phi/select nodes.
void execute(VPTransformState &State) override;
@@ -2344,11 +2463,12 @@ class LLVM_ABI_FOR_TEST VPWidenPHIRecipe : public VPSingleDefRecipe,
struct VPFirstOrderRecurrencePHIRecipe : public VPHeaderPHIRecipe {
VPFirstOrderRecurrencePHIRecipe(PHINode *Phi, VPValue &Start,
VPValue &BackedgeValue)
- : VPHeaderPHIRecipe(VPDef::VPFirstOrderRecurrencePHISC, Phi, &Start) {
+ : VPHeaderPHIRecipe(VPRecipeBase::VPFirstOrderRecurrencePHISC, Phi,
+ &Start) {
addOperand(&BackedgeValue);
}
- VP_CLASSOF_IMPL(VPDef::VPFirstOrderRecurrencePHISC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPFirstOrderRecurrencePHISC)
VPFirstOrderRecurrencePHIRecipe *clone() override {
return new VPFirstOrderRecurrencePHIRecipe(
@@ -2420,8 +2540,8 @@ class VPReductionPHIRecipe : public VPHeaderPHIRecipe,
VPReductionPHIRecipe(PHINode *Phi, RecurKind Kind, VPValue &Start,
VPValue &BackedgeValue, ReductionStyle Style,
bool HasUsesOutsideReductionChain = false)
- : VPHeaderPHIRecipe(VPDef::VPReductionPHISC, Phi, &Start), Kind(Kind),
- Style(Style),
+ : VPHeaderPHIRecipe(VPRecipeBase::VPReductionPHISC, Phi, &Start),
+ Kind(Kind), Style(Style),
HasUsesOutsideReductionChain(HasUsesOutsideReductionChain) {
addOperand(&BackedgeValue);
}
@@ -2435,7 +2555,7 @@ class VPReductionPHIRecipe : public VPHeaderPHIRecipe,
HasUsesOutsideReductionChain);
}
- VP_CLASSOF_IMPL(VPDef::VPReductionPHISC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPReductionPHISC)
/// Generate the phi/select nodes.
void execute(VPTransformState &State) override;
@@ -2503,7 +2623,7 @@ class LLVM_ABI_FOR_TEST VPBlendRecipe : public VPSingleDefRecipe {
/// be omitted (implied by passing an odd number of operands) in which case
/// all other incoming values are merged into it.
VPBlendRecipe(PHINode *Phi, ArrayRef<VPValue *> Operands, DebugLoc DL)
- : VPSingleDefRecipe(VPDef::VPBlendSC, Operands, Phi, DL) {
+ : VPSingleDefRecipe(VPRecipeBase::VPBlendSC, Operands, Phi, DL) {
assert(Operands.size() >= 2 && "Expected at least two operands!");
}
@@ -2512,7 +2632,7 @@ class LLVM_ABI_FOR_TEST VPBlendRecipe : public VPSingleDefRecipe {
operands(), getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPBlendSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPBlendSC)
/// A normalized blend is one that has an odd number of operands, whereby the
/// first operand does not have an associated mask.
@@ -2614,8 +2734,8 @@ class LLVM_ABI_FOR_TEST VPInterleaveBase : public VPRecipeBase,
VPInterleaveBase *clone() override = 0;
static inline bool classof(const VPRecipeBase *R) {
- return R->getVPDefID() == VPRecipeBase::VPInterleaveSC ||
- R->getVPDefID() == VPRecipeBase::VPInterleaveEVLSC;
+ return R->getVPRecipeID() == VPRecipeBase::VPInterleaveSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPInterleaveEVLSC;
}
static inline bool classof(const VPUser *U) {
@@ -2675,8 +2795,8 @@ class LLVM_ABI_FOR_TEST VPInterleaveRecipe final : public VPInterleaveBase {
VPInterleaveRecipe(const InterleaveGroup<Instruction> *IG, VPValue *Addr,
ArrayRef<VPValue *> StoredValues, VPValue *Mask,
bool NeedsMaskForGaps, const VPIRMetadata &MD, DebugLoc DL)
- : VPInterleaveBase(VPDef::VPInterleaveSC, IG, Addr, StoredValues, Mask,
- NeedsMaskForGaps, MD, DL) {}
+ : VPInterleaveBase(VPRecipeBase::VPInterleaveSC, IG, Addr, StoredValues,
+ Mask, NeedsMaskForGaps, MD, DL) {}
~VPInterleaveRecipe() override = default;
@@ -2686,7 +2806,7 @@ class LLVM_ABI_FOR_TEST VPInterleaveRecipe final : public VPInterleaveBase {
needsMaskForGaps(), *this, getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPInterleaveSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPInterleaveSC)
/// Generate the wide load or store, and shuffles.
void execute(VPTransformState &State) override;
@@ -2715,10 +2835,10 @@ class LLVM_ABI_FOR_TEST VPInterleaveRecipe final : public VPInterleaveBase {
class LLVM_ABI_FOR_TEST VPInterleaveEVLRecipe final : public VPInterleaveBase {
public:
VPInterleaveEVLRecipe(VPInterleaveRecipe &R, VPValue &EVL, VPValue *Mask)
- : VPInterleaveBase(VPDef::VPInterleaveEVLSC, R.getInterleaveGroup(),
- ArrayRef<VPValue *>({R.getAddr(), &EVL}),
- R.getStoredValues(), Mask, R.needsMaskForGaps(), R,
- R.getDebugLoc()) {
+ : VPInterleaveBase(
+ VPRecipeBase::VPInterleaveEVLSC, R.getInterleaveGroup(),
+ ArrayRef<VPValue *>({R.getAddr(), &EVL}), R.getStoredValues(), Mask,
+ R.needsMaskForGaps(), R, R.getDebugLoc()) {
assert(!getInterleaveGroup()->isReverse() &&
"Reversed interleave-group with tail folding is not supported.");
assert(!needsMaskForGaps() && "Interleaved access with gap mask is not "
@@ -2731,7 +2851,7 @@ class LLVM_ABI_FOR_TEST VPInterleaveEVLRecipe final : public VPInterleaveBase {
llvm_unreachable("cloning not implemented yet");
}
- VP_CLASSOF_IMPL(VPDef::VPInterleaveEVLSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPInterleaveEVLSC)
/// The VPValue of the explicit vector length.
VPValue *getEVL() const { return getOperand(1); }
@@ -2789,14 +2909,14 @@ class LLVM_ABI_FOR_TEST VPReductionRecipe : public VPRecipeWithIRFlags {
VPReductionRecipe(RecurKind RdxKind, FastMathFlags FMFs, Instruction *I,
VPValue *ChainOp, VPValue *VecOp, VPValue *CondOp,
ReductionStyle Style, DebugLoc DL = DebugLoc::getUnknown())
- : VPReductionRecipe(VPDef::VPReductionSC, RdxKind, FMFs, I,
+ : VPReductionRecipe(VPRecipeBase::VPReductionSC, RdxKind, FMFs, I,
ArrayRef<VPValue *>({ChainOp, VecOp}), CondOp, Style,
DL) {}
VPReductionRecipe(const RecurKind RdxKind, FastMathFlags FMFs,
VPValue *ChainOp, VPValue *VecOp, VPValue *CondOp,
ReductionStyle Style, DebugLoc DL = DebugLoc::getUnknown())
- : VPReductionRecipe(VPDef::VPReductionSC, RdxKind, FMFs, nullptr,
+ : VPReductionRecipe(VPRecipeBase::VPReductionSC, RdxKind, FMFs, nullptr,
ArrayRef<VPValue *>({ChainOp, VecOp}), CondOp, Style,
DL) {}
@@ -2809,8 +2929,8 @@ class LLVM_ABI_FOR_TEST VPReductionRecipe : public VPRecipeWithIRFlags {
}
static inline bool classof(const VPRecipeBase *R) {
- return R->getVPDefID() == VPRecipeBase::VPReductionSC ||
- R->getVPDefID() == VPRecipeBase::VPReductionEVLSC;
+ return R->getVPRecipeID() == VPRecipeBase::VPReductionSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPReductionEVLSC;
}
static inline bool classof(const VPUser *U) {
@@ -2879,7 +2999,7 @@ class LLVM_ABI_FOR_TEST VPReductionEVLRecipe : public VPReductionRecipe {
VPReductionEVLRecipe(VPReductionRecipe &R, VPValue &EVL, VPValue *CondOp,
DebugLoc DL = DebugLoc::getUnknown())
: VPReductionRecipe(
- VPDef::VPReductionEVLSC, R.getRecurrenceKind(),
+ VPRecipeBase::VPReductionEVLSC, R.getRecurrenceKind(),
R.getFastMathFlags(),
cast_or_null<Instruction>(R.getUnderlyingValue()),
ArrayRef<VPValue *>({R.getChainOp(), R.getVecOp(), &EVL}), CondOp,
@@ -2891,7 +3011,7 @@ class LLVM_ABI_FOR_TEST VPReductionEVLRecipe : public VPReductionRecipe {
llvm_unreachable("cloning not implemented yet");
}
- VP_CLASSOF_IMPL(VPDef::VPReductionEVLSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPReductionEVLSC)
/// Generate the reduction in the loop
void execute(VPTransformState &State) override;
@@ -2931,7 +3051,7 @@ class LLVM_ABI_FOR_TEST VPReplicateRecipe : public VPRecipeWithIRFlags,
bool IsSingleScalar, VPValue *Mask = nullptr,
const VPIRFlags &Flags = {}, VPIRMetadata Metadata = {},
DebugLoc DL = DebugLoc::getUnknown())
- : VPRecipeWithIRFlags(VPDef::VPReplicateSC, Operands, Flags, DL),
+ : VPRecipeWithIRFlags(VPRecipeBase::VPReplicateSC, Operands, Flags, DL),
VPIRMetadata(Metadata), IsSingleScalar(IsSingleScalar),
IsPredicated(Mask) {
setUnderlyingValue(I);
@@ -2949,7 +3069,7 @@ class LLVM_ABI_FOR_TEST VPReplicateRecipe : public VPRecipeWithIRFlags,
return Copy;
}
- VP_CLASSOF_IMPL(VPDef::VPReplicateSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPReplicateSC)
/// Generate replicas of the desired Ingredient. Replicas will be generated
/// for all parts and lanes unless a specific part and lane are specified in
@@ -3003,13 +3123,13 @@ class LLVM_ABI_FOR_TEST VPReplicateRecipe : public VPRecipeWithIRFlags,
class LLVM_ABI_FOR_TEST VPBranchOnMaskRecipe : public VPRecipeBase {
public:
VPBranchOnMaskRecipe(VPValue *BlockInMask, DebugLoc DL)
- : VPRecipeBase(VPDef::VPBranchOnMaskSC, {BlockInMask}, DL) {}
+ : VPRecipeBase(VPRecipeBase::VPBranchOnMaskSC, {BlockInMask}, DL) {}
VPBranchOnMaskRecipe *clone() override {
return new VPBranchOnMaskRecipe(getOperand(0), getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPBranchOnMaskSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPBranchOnMaskSC)
/// Generate the extraction of the appropriate bit from the block mask and the
/// conditional branch.
@@ -3118,7 +3238,7 @@ class VPExpressionRecipe : public VPSingleDefRecipe {
delete T;
}
- VP_CLASSOF_IMPL(VPDef::VPExpressionSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPExpressionSC)
VPExpressionRecipe *clone() override {
assert(!ExpressionRecipes.empty() && "empty expressions should be removed");
@@ -3192,14 +3312,14 @@ class LLVM_ABI_FOR_TEST VPPredInstPHIRecipe : public VPSingleDefRecipe {
/// Construct a VPPredInstPHIRecipe given \p PredInst whose value needs a phi
/// nodes after merging back from a Branch-on-Mask.
VPPredInstPHIRecipe(VPValue *PredV, DebugLoc DL)
- : VPSingleDefRecipe(VPDef::VPPredInstPHISC, PredV, DL) {}
+ : VPSingleDefRecipe(VPRecipeBase::VPPredInstPHISC, PredV, DL) {}
~VPPredInstPHIRecipe() override = default;
VPPredInstPHIRecipe *clone() override {
return new VPPredInstPHIRecipe(getOperand(0), getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPPredInstPHISC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPPredInstPHISC)
/// Generates phi nodes for live-outs (from a replicate region) as needed to
/// retain SSA form.
@@ -3272,10 +3392,10 @@ class LLVM_ABI_FOR_TEST VPWidenMemoryRecipe : public VPRecipeBase,
}
static inline bool classof(const VPRecipeBase *R) {
- return R->getVPDefID() == VPRecipeBase::VPWidenLoadSC ||
- R->getVPDefID() == VPRecipeBase::VPWidenStoreSC ||
- R->getVPDefID() == VPRecipeBase::VPWidenLoadEVLSC ||
- R->getVPDefID() == VPRecipeBase::VPWidenStoreEVLSC;
+ return R->getVPRecipeID() == VPRecipeBase::VPWidenLoadSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPWidenStoreSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPWidenLoadEVLSC ||
+ R->getVPRecipeID() == VPRecipeBase::VPWidenStoreEVLSC;
}
static inline bool classof(const VPUser *U) {
@@ -3325,8 +3445,8 @@ struct LLVM_ABI_FOR_TEST VPWidenLoadRecipe final : public VPWidenMemoryRecipe,
VPWidenLoadRecipe(LoadInst &Load, VPValue *Addr, VPValue *Mask,
bool Consecutive, bool Reverse,
const VPIRMetadata &Metadata, DebugLoc DL)
- : VPWidenMemoryRecipe(VPDef::VPWidenLoadSC, Load, {Addr}, Consecutive,
- Reverse, Metadata, DL),
+ : VPWidenMemoryRecipe(VPRecipeBase::VPWidenLoadSC, Load, {Addr},
+ Consecutive, Reverse, Metadata, DL),
VPRecipeValue(this, &Load) {
setMask(Mask);
}
@@ -3337,7 +3457,7 @@ struct LLVM_ABI_FOR_TEST VPWidenLoadRecipe final : public VPWidenMemoryRecipe,
getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPWidenLoadSC);
+ VP_CLASSOF_IMPL(VPRecipeBase::VPWidenLoadSC);
/// Generate a wide load or gather.
void execute(VPTransformState &State) override;
@@ -3366,14 +3486,14 @@ struct VPWidenLoadEVLRecipe final : public VPWidenMemoryRecipe,
public VPRecipeValue {
VPWidenLoadEVLRecipe(VPWidenLoadRecipe &L, VPValue *Addr, VPValue &EVL,
VPValue *Mask)
- : VPWidenMemoryRecipe(VPDef::VPWidenLoadEVLSC, L.getIngredient(),
+ : VPWidenMemoryRecipe(VPRecipeBase::VPWidenLoadEVLSC, L.getIngredient(),
{Addr, &EVL}, L.isConsecutive(), L.isReverse(), L,
L.getDebugLoc()),
VPRecipeValue(this, &getIngredient()) {
setMask(Mask);
}
- VP_CLASSOF_IMPL(VPDef::VPWidenLoadEVLSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPWidenLoadEVLSC)
/// Return the EVL operand.
VPValue *getEVL() const { return getOperand(1); }
@@ -3408,8 +3528,9 @@ struct LLVM_ABI_FOR_TEST VPWidenStoreRecipe final : public VPWidenMemoryRecipe {
VPWidenStoreRecipe(StoreInst &Store, VPValue *Addr, VPValue *StoredVal,
VPValue *Mask, bool Consecutive, bool Reverse,
const VPIRMetadata &Metadata, DebugLoc DL)
- : VPWidenMemoryRecipe(VPDef::VPWidenStoreSC, Store, {Addr, StoredVal},
- Consecutive, Reverse, Metadata, DL) {
+ : VPWidenMemoryRecipe(VPRecipeBase::VPWidenStoreSC, Store,
+ {Addr, StoredVal}, Consecutive, Reverse, Metadata,
+ DL) {
setMask(Mask);
}
@@ -3419,7 +3540,7 @@ struct LLVM_ABI_FOR_TEST VPWidenStoreRecipe final : public VPWidenMemoryRecipe {
Reverse, *this, getDebugLoc());
}
- VP_CLASSOF_IMPL(VPDef::VPWidenStoreSC);
+ VP_CLASSOF_IMPL(VPRecipeBase::VPWidenStoreSC);
/// Return the value stored by this recipe.
VPValue *getStoredValue() const { return getOperand(1); }
@@ -3450,13 +3571,13 @@ struct LLVM_ABI_FOR_TEST VPWidenStoreRecipe final : public VPWidenMemoryRecipe {
struct VPWidenStoreEVLRecipe final : public VPWidenMemoryRecipe {
VPWidenStoreEVLRecipe(VPWidenStoreRecipe &S, VPValue *Addr,
VPValue *StoredVal, VPValue &EVL, VPValue *Mask)
- : VPWidenMemoryRecipe(VPDef::VPWidenStoreEVLSC, S.getIngredient(),
+ : VPWidenMemoryRecipe(VPRecipeBase::VPWidenStoreEVLSC, S.getIngredient(),
{Addr, StoredVal, &EVL}, S.isConsecutive(),
S.isReverse(), S, S.getDebugLoc()) {
setMask(Mask);
}
- VP_CLASSOF_IMPL(VPDef::VPWidenStoreEVLSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPWidenStoreEVLSC)
/// Return the address accessed by this recipe.
VPValue *getStoredValue() const { return getOperand(1); }
@@ -3499,13 +3620,13 @@ class VPExpandSCEVRecipe : public VPSingleDefRecipe {
public:
VPExpandSCEVRecipe(const SCEV *Expr)
- : VPSingleDefRecipe(VPDef::VPExpandSCEVSC, {}), Expr(Expr) {}
+ : VPSingleDefRecipe(VPRecipeBase::VPExpandSCEVSC, {}), Expr(Expr) {}
~VPExpandSCEVRecipe() override = default;
VPExpandSCEVRecipe *clone() override { return new VPExpandSCEVRecipe(Expr); }
- VP_CLASSOF_IMPL(VPDef::VPExpandSCEVSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPExpandSCEVSC)
void execute(VPTransformState &State) override {
llvm_unreachable("SCEV expressions must be expanded before final execute");
@@ -3535,7 +3656,8 @@ class VPExpandSCEVRecipe : public VPSingleDefRecipe {
class VPCanonicalIVPHIRecipe : public VPHeaderPHIRecipe {
public:
VPCanonicalIVPHIRecipe(VPIRValue *StartV, DebugLoc DL)
- : VPHeaderPHIRecipe(VPDef::VPCanonicalIVPHISC, nullptr, StartV, DL) {}
+ : VPHeaderPHIRecipe(VPRecipeBase::VPCanonicalIVPHISC, nullptr, StartV,
+ DL) {}
~VPCanonicalIVPHIRecipe() override = default;
@@ -3545,7 +3667,7 @@ class VPCanonicalIVPHIRecipe : public VPHeaderPHIRecipe {
return R;
}
- VP_CLASSOF_IMPL(VPDef::VPCanonicalIVPHISC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPCanonicalIVPHISC)
void execute(VPTransformState &State) override {
llvm_unreachable("cannot execute this recipe, should be replaced by a "
@@ -3592,8 +3714,8 @@ class VPCanonicalIVPHIRecipe : public VPHeaderPHIRecipe {
class VPActiveLaneMaskPHIRecipe : public VPHeaderPHIRecipe {
public:
VPActiveLaneMaskPHIRecipe(VPValue *StartMask, DebugLoc DL)
- : VPHeaderPHIRecipe(VPDef::VPActiveLaneMaskPHISC, nullptr, StartMask,
- DL) {}
+ : VPHeaderPHIRecipe(VPRecipeBase::VPActiveLaneMaskPHISC, nullptr,
+ StartMask, DL) {}
~VPActiveLaneMaskPHIRecipe() override = default;
@@ -3604,7 +3726,7 @@ class VPActiveLaneMaskPHIRecipe : public VPHeaderPHIRecipe {
return R;
}
- VP_CLASSOF_IMPL(VPDef::VPActiveLaneMaskPHISC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPActiveLaneMaskPHISC)
/// Generate the active lane mask phi of the vector loop.
void execute(VPTransformState &State) override;
@@ -3624,7 +3746,8 @@ class VPActiveLaneMaskPHIRecipe : public VPHeaderPHIRecipe {
class VPEVLBasedIVPHIRecipe : public VPHeaderPHIRecipe {
public:
VPEVLBasedIVPHIRecipe(VPValue *StartIV, DebugLoc DL)
- : VPHeaderPHIRecipe(VPDef::VPEVLBasedIVPHISC, nullptr, StartIV, DL) {}
+ : VPHeaderPHIRecipe(VPRecipeBase::VPEVLBasedIVPHISC, nullptr, StartIV,
+ DL) {}
~VPEVLBasedIVPHIRecipe() override = default;
@@ -3632,7 +3755,7 @@ class VPEVLBasedIVPHIRecipe : public VPHeaderPHIRecipe {
llvm_unreachable("cloning not implemented yet");
}
- VP_CLASSOF_IMPL(VPDef::VPEVLBasedIVPHISC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPEVLBasedIVPHISC)
void execute(VPTransformState &State) override {
llvm_unreachable("cannot execute this recipe, should be replaced by a "
@@ -3666,7 +3789,7 @@ class VPWidenCanonicalIVRecipe : public VPSingleDefRecipe,
public VPUnrollPartAccessor<1> {
public:
VPWidenCanonicalIVRecipe(VPCanonicalIVPHIRecipe *CanonicalIV)
- : VPSingleDefRecipe(VPDef::VPWidenCanonicalIVSC, {CanonicalIV}) {}
+ : VPSingleDefRecipe(VPRecipeBase::VPWidenCanonicalIVSC, {CanonicalIV}) {}
~VPWidenCanonicalIVRecipe() override = default;
@@ -3675,7 +3798,7 @@ class VPWidenCanonicalIVRecipe : public VPSingleDefRecipe,
cast<VPCanonicalIVPHIRecipe>(getOperand(0)));
}
- VP_CLASSOF_IMPL(VPDef::VPWidenCanonicalIVSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPWidenCanonicalIVSC)
/// Generate a canonical vector induction variable of the vector loop, with
/// start = {<Part*VF, Part*VF+1, ..., Part*VF+VF-1> for 0 <= Part < UF}, and
@@ -3722,8 +3845,8 @@ class VPDerivedIVRecipe : public VPSingleDefRecipe {
VPDerivedIVRecipe(InductionDescriptor::InductionKind Kind,
const FPMathOperator *FPBinOp, VPIRValue *Start,
VPValue *IV, VPValue *Step, const Twine &Name = "")
- : VPSingleDefRecipe(VPDef::VPDerivedIVSC, {Start, IV, Step}), Kind(Kind),
- FPBinOp(FPBinOp), Name(Name.str()) {}
+ : VPSingleDefRecipe(VPRecipeBase::VPDerivedIVSC, {Start, IV, Step}),
+ Kind(Kind), FPBinOp(FPBinOp), Name(Name.str()) {}
~VPDerivedIVRecipe() override = default;
@@ -3732,7 +3855,7 @@ class VPDerivedIVRecipe : public VPSingleDefRecipe {
getStepValue());
}
- VP_CLASSOF_IMPL(VPDef::VPDerivedIVSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPDerivedIVSC)
/// Generate the transformed value of the induction at offset StartValue (1.
/// operand) + IV (2. operand) * StepValue (3, operand).
@@ -3775,7 +3898,7 @@ class LLVM_ABI_FOR_TEST VPScalarIVStepsRecipe : public VPRecipeWithIRFlags,
VPScalarIVStepsRecipe(VPValue *IV, VPValue *Step, VPValue *VF,
Instruction::BinaryOps Opcode, FastMathFlags FMFs,
DebugLoc DL)
- : VPRecipeWithIRFlags(VPDef::VPScalarIVStepsSC,
+ : VPRecipeWithIRFlags(VPRecipeBase::VPScalarIVStepsSC,
ArrayRef<VPValue *>({IV, Step, VF}), FMFs, DL),
InductionOpcode(Opcode) {}
@@ -3802,7 +3925,7 @@ class LLVM_ABI_FOR_TEST VPScalarIVStepsRecipe : public VPRecipeWithIRFlags,
/// this is only accurate after the VPlan has been unrolled.
bool isPart0() const { return getUnrollPart(*this) == 0; }
- VP_CLASSOF_IMPL(VPDef::VPScalarIVStepsSC)
+ VP_CLASSOF_IMPL(VPRecipeBase::VPScalarIVStepsSC)
/// Generate the scalarized versions of the phi node as needed by their users.
void execute(VPTransformState &State) override;
@@ -3849,12 +3972,12 @@ struct CastInfoVPPhiAccessors : public CastIsPossible<VPPhiAccessors, SrcTy> {
/// doCast is used by cast<>.
static inline VPPhiAccessors *doCast(SrcTy R) {
return const_cast<VPPhiAccessors *>([R]() -> const VPPhiAccessors * {
- switch (R->getVPDefID()) {
- case VPDef::VPInstructionSC:
+ switch (R->getVPRecipeID()) {
+ case VPRecipeBase::VPInstructionSC:
return cast<VPPhi>(R);
- case VPDef::VPIRInstructionSC:
+ case VPRecipeBase::VPIRInstructionSC:
return cast<VPIRPhi>(R);
- case VPDef::VPWidenPHISC:
+ case VPRecipeBase::VPWidenPHISC:
return cast<VPWidenPHIRecipe>(R);
default:
return cast<VPHeaderPHIRecipe>(R);
@@ -3881,26 +4004,26 @@ struct CastInfo<VPPhiAccessors, const VPRecipeBase *>
namespace detail {
template <typename DstTy, typename RecipeBasePtrTy>
static inline auto castToVPIRMetadata(RecipeBasePtrTy R) -> DstTy {
- switch (R->getVPDefID()) {
- case VPDef::VPInstructionSC:
+ switch (R->getVPRecipeID()) {
+ case VPRecipeBase::VPInstructionSC:
return cast<VPInstruction>(R);
- case VPDef::VPWidenSC:
+ case VPRecipeBase::VPWidenSC:
return cast<VPWidenRecipe>(R);
- case VPDef::VPWidenCastSC:
+ case VPRecipeBase::VPWidenCastSC:
return cast<VPWidenCastRecipe>(R);
- case VPDef::VPWidenIntrinsicSC:
+ case VPRecipeBase::VPWidenIntrinsicSC:
return cast<VPWidenIntrinsicRecipe>(R);
- case VPDef::VPWidenCallSC:
+ case VPRecipeBase::VPWidenCallSC:
return cast<VPWidenCallRecipe>(R);
- case VPDef::VPReplicateSC:
+ case VPRecipeBase::VPReplicateSC:
return cast<VPReplicateRecipe>(R);
- case VPDef::VPInterleaveSC:
- case VPDef::VPInterleaveEVLSC:
+ case VPRecipeBase::VPInterleaveSC:
+ case VPRecipeBase::VPInterleaveEVLSC:
return cast<VPInterleaveBase>(R);
- case VPDef::VPWidenLoadSC:
- case VPDef::VPWidenLoadEVLSC:
- case VPDef::VPWidenStoreSC:
- case VPDef::VPWidenStoreEVLSC:
+ case VPRecipeBase::VPWidenLoadSC:
+ case VPRecipeBase::VPWidenLoadEVLSC:
+ case VPRecipeBase::VPWidenStoreSC:
+ case VPRecipeBase::VPWidenStoreEVLSC:
return cast<VPWidenMemoryRecipe>(R);
default:
llvm_unreachable("invalid recipe for VPIRMetadata cast");
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index b9cd322d9ec69..df8d134f5eabf 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -48,7 +48,7 @@ using VectorParts = SmallVector<Value *, 2>;
#define DEBUG_TYPE LV_NAME
bool VPRecipeBase::mayWriteToMemory() const {
- switch (getVPDefID()) {
+ switch (getVPRecipeID()) {
case VPExpressionSC:
return cast<VPExpressionRecipe>(this)->mayReadOrWriteMemory();
case VPInstructionSC: {
@@ -107,7 +107,7 @@ bool VPRecipeBase::mayWriteToMemory() const {
}
bool VPRecipeBase::mayReadFromMemory() const {
- switch (getVPDefID()) {
+ switch (getVPRecipeID()) {
case VPExpressionSC:
return cast<VPExpressionRecipe>(this)->mayReadOrWriteMemory();
case VPInstructionSC:
@@ -157,7 +157,7 @@ bool VPRecipeBase::mayReadFromMemory() const {
}
bool VPRecipeBase::mayHaveSideEffects() const {
- switch (getVPDefID()) {
+ switch (getVPRecipeID()) {
case VPExpressionSC:
return cast<VPExpressionRecipe>(this)->mayHaveSideEffects();
case VPDerivedIVSC:
@@ -302,7 +302,7 @@ InstructionCost VPRecipeBase::computeCost(ElementCount VF,
}
bool VPRecipeBase::isPhi() const {
- return (getVPDefID() >= VPFirstPHISC && getVPDefID() <= VPLastPHISC) ||
+ return (getVPRecipeID() >= VPFirstPHISC && getVPRecipeID() <= VPLastPHISC) ||
isa<VPPhi, VPIRPhi>(this);
}
@@ -367,7 +367,7 @@ FastMathFlags VPIRFlags::getFastMathFlags() const {
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-void VPSingleDefRecipe::dump() const { VPDef::dump(); }
+void VPSingleDefRecipe::dump() const { VPRecipeBase::dump(); }
void VPRecipeBase::print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
@@ -406,7 +406,7 @@ template class VPUnrollPartAccessor<3>;
VPInstruction::VPInstruction(unsigned Opcode, ArrayRef<VPValue *> Operands,
const VPIRFlags &Flags, const VPIRMetadata &MD,
DebugLoc DL, const Twine &Name)
- : VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, Flags, DL),
+ : VPRecipeWithIRFlags(VPRecipeBase::VPInstructionSC, Operands, Flags, DL),
VPIRMetadata(MD), Opcode(Opcode), Name(Name.str()) {
assert(flagsValidForOpcode(getOpcode()) &&
"Set flags not supported for the provided opcode");
@@ -2788,7 +2788,7 @@ InstructionCost VPReductionRecipe::computeCost(ElementCount VF,
VPExpressionRecipe::VPExpressionRecipe(
ExpressionTypes ExpressionType,
ArrayRef<VPSingleDefRecipe *> ExpressionRecipes)
- : VPSingleDefRecipe(VPDef::VPExpressionSC, {}, {}),
+ : VPSingleDefRecipe(VPRecipeBase::VPExpressionSC, {}, {}),
ExpressionRecipes(ExpressionRecipes), ExpressionType(ExpressionType) {
assert(!ExpressionRecipes.empty() && "Nothing to combine?");
assert(
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 69541c6618568..59320d1a0f0ad 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -1130,9 +1130,9 @@ getOpcodeOrIntrinsicID(const VPSingleDefRecipe *R) {
.Case<VPVectorPointerRecipe, VPPredInstPHIRecipe>([](auto *I) {
// For recipes that do not directly map to LLVM IR instructions,
// assign opcodes after the last VPInstruction opcode (which is also
- // after the last IR Instruction opcode), based on the VPDefID.
+ // after the last IR Instruction opcode), based on the VPRecipeID.
return std::make_pair(false,
- VPInstruction::OpsEnd + 1 + I->getVPDefID());
+ VPInstruction::OpsEnd + 1 + I->getVPRecipeID());
})
.Default([](auto *) { return std::nullopt; });
}
@@ -2441,7 +2441,7 @@ struct VPCSEDenseMapInfo : public DenseMapInfo<VPSingleDefRecipe *> {
const VPlan *Plan = Def->getParent()->getPlan();
VPTypeAnalysis TypeInfo(*Plan);
hash_code Result = hash_combine(
- Def->getVPDefID(), getOpcodeOrIntrinsicID(Def),
+ Def->getVPRecipeID(), getOpcodeOrIntrinsicID(Def),
getGEPSourceElementType(Def), TypeInfo.inferScalarType(Def),
vputils::isSingleScalar(Def), hash_combine_range(Def->operands()));
if (auto *RFlags = dyn_cast<VPRecipeWithIRFlags>(Def))
@@ -2454,7 +2454,7 @@ struct VPCSEDenseMapInfo : public DenseMapInfo<VPSingleDefRecipe *> {
static bool isEqual(const VPSingleDefRecipe *L, const VPSingleDefRecipe *R) {
if (isSentinel(L) || isSentinel(R))
return L == R;
- if (L->getVPDefID() != R->getVPDefID() ||
+ if (L->getVPRecipeID() != R->getVPRecipeID() ||
getOpcodeOrIntrinsicID(L) != getOpcodeOrIntrinsicID(R) ||
getGEPSourceElementType(L) != getGEPSourceElementType(R) ||
vputils::isSingleScalar(L) != vputils::isSingleScalar(R) ||
diff --git a/llvm/lib/Transforms/Vectorize/VPlanValue.h b/llvm/lib/Transforms/Vectorize/VPlanValue.h
index cae0633dbb185..3187984a1d706 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanValue.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanValue.h
@@ -10,9 +10,9 @@
/// This file contains the declarations of the entities induced by Vectorization
/// Plans, e.g. the instructions the VPlan intends to generate if executed.
/// VPlan models the following entities:
-/// VPValue VPUser VPDef
-/// | |
-/// VPInstruction
+/// VPValue VPUser VPRecipeBase
+/// | | |
+/// VPInstruction ------+
/// These are documented in docs/VectorizationPlan.rst.
///
//===----------------------------------------------------------------------===//
@@ -32,8 +32,6 @@ namespace llvm {
class raw_ostream;
class Type;
class Value;
-class VPDef;
-struct VPDoubleValueDef;
class VPSlotTracker;
class VPUser;
class VPRecipeBase;
@@ -43,8 +41,6 @@ class VPPhiAccessors;
/// data flow into, within and out of the VPlan. VPValues can stand for live-ins
/// coming from the input IR, symbolic values and values defined by recipes.
class LLVM_ABI_FOR_TEST VPValue {
- friend class VPDef;
- friend struct VPDoubleValueDef;
friend class VPlan;
friend struct VPIRValue;
friend struct VPSymbolicValue;
@@ -210,12 +206,12 @@ struct VPSymbolicValue : public VPValue {
/// A VPValue defined by a recipe that produces one or more values.
class VPRecipeValue : public VPValue {
friend class VPValue;
- friend class VPDef;
- /// Pointer to the VPDef that defines this VPValue.
- VPDef *Def;
+ friend class VPRecipeBase;
+ /// Pointer to the VPRecipeBase that defines this VPValue.
+ VPRecipeBase *Def;
public:
- VPRecipeValue(VPDef *Def, Value *UV = nullptr);
+ VPRecipeValue(VPRecipeBase *Def, Value *UV = nullptr);
virtual ~VPRecipeValue();
@@ -324,149 +320,6 @@ class VPUser {
}
};
-/// This class augments a recipe with a set of VPValues defined by the recipe.
-/// It allows recipes to define zero, one or multiple VPValues. A VPDef owns
-/// the VPValues it defines and is responsible for deleting its defined values.
-/// Single-value VPDefs that also inherit from VPValue must make sure to inherit
-/// from VPDef before VPValue.
-class VPDef {
- friend class VPValue;
- friend class VPRecipeValue;
-
- /// Subclass identifier (for isa/dyn_cast).
- const unsigned char SubclassID;
-
- /// The VPValues defined by this VPDef.
- TinyPtrVector<VPRecipeValue *> DefinedValues;
-
- /// Add \p V as a defined value by this VPDef.
- void addDefinedValue(VPRecipeValue *V) {
- assert(V->Def == this &&
- "can only add VPValue already linked with this VPDef");
- DefinedValues.push_back(V);
- }
-
- /// Remove \p V from the values defined by this VPDef. \p V must be a defined
- /// value of this VPDef.
- void removeDefinedValue(VPRecipeValue *V) {
- assert(V->Def == this && "can only remove VPValue linked with this VPDef");
- assert(is_contained(DefinedValues, V) &&
- "VPValue to remove must be in DefinedValues");
- llvm::erase(DefinedValues, V);
- V->Def = nullptr;
- }
-
-public:
- /// An enumeration for keeping track of the concrete subclass of VPRecipeBase
- /// that is actually instantiated. Values of this enumeration are kept in the
- /// SubclassID field of the VPRecipeBase objects. They are used for concrete
- /// type identification.
- using VPRecipeTy = enum {
- VPBranchOnMaskSC,
- VPDerivedIVSC,
- VPExpandSCEVSC,
- VPExpressionSC,
- VPIRInstructionSC,
- VPInstructionSC,
- VPInterleaveEVLSC,
- VPInterleaveSC,
- VPReductionEVLSC,
- VPReductionSC,
- VPReplicateSC,
- VPScalarIVStepsSC,
- VPVectorPointerSC,
- VPVectorEndPointerSC,
- VPWidenCallSC,
- VPWidenCanonicalIVSC,
- VPWidenCastSC,
- VPWidenGEPSC,
- VPWidenIntrinsicSC,
- VPWidenLoadEVLSC,
- VPWidenLoadSC,
- VPWidenStoreEVLSC,
- VPWidenStoreSC,
- VPWidenSC,
- VPWidenSelectSC,
- VPBlendSC,
- VPHistogramSC,
- // START: Phi-like recipes. Need to be kept together.
- VPWidenPHISC,
- VPPredInstPHISC,
- // START: SubclassID for recipes that inherit VPHeaderPHIRecipe.
- // VPHeaderPHIRecipe need to be kept together.
- VPCanonicalIVPHISC,
- VPActiveLaneMaskPHISC,
- VPEVLBasedIVPHISC,
- VPFirstOrderRecurrencePHISC,
- VPWidenIntOrFpInductionSC,
- VPWidenPointerInductionSC,
- VPReductionPHISC,
- // END: SubclassID for recipes that inherit VPHeaderPHIRecipe
- // END: Phi-like recipes
- VPFirstPHISC = VPWidenPHISC,
- VPFirstHeaderPHISC = VPCanonicalIVPHISC,
- VPLastHeaderPHISC = VPReductionPHISC,
- VPLastPHISC = VPReductionPHISC,
- };
-
- VPDef(const unsigned char SC) : SubclassID(SC) {}
-
- virtual ~VPDef() {
- for (VPRecipeValue *D : to_vector(DefinedValues)) {
- assert(D->Def == this &&
- "all defined VPValues should point to the containing VPDef");
- assert(D->getNumUsers() == 0 &&
- "all defined VPValues should have no more users");
- delete D;
- }
- }
-
- /// Returns the only VPValue defined by the VPDef. Can only be called for
- /// VPDefs with a single defined value.
- VPValue *getVPSingleValue() {
- assert(DefinedValues.size() == 1 && "must have exactly one defined value");
- assert(DefinedValues[0] && "defined value must be non-null");
- return DefinedValues[0];
- }
- const VPValue *getVPSingleValue() const {
- assert(DefinedValues.size() == 1 && "must have exactly one defined value");
- assert(DefinedValues[0] && "defined value must be non-null");
- return DefinedValues[0];
- }
-
- /// Returns the VPValue with index \p I defined by the VPDef.
- VPValue *getVPValue(unsigned I) {
- assert(DefinedValues[I] && "defined value must be non-null");
- return DefinedValues[I];
- }
- const VPValue *getVPValue(unsigned I) const {
- assert(DefinedValues[I] && "defined value must be non-null");
- return DefinedValues[I];
- }
-
- /// Returns an ArrayRef of the values defined by the VPDef.
- ArrayRef<VPRecipeValue *> definedValues() { return DefinedValues; }
- /// Returns an ArrayRef of the values defined by the VPDef.
- ArrayRef<VPRecipeValue *> definedValues() const { return DefinedValues; }
-
- /// Returns the number of values defined by the VPDef.
- unsigned getNumDefinedValues() const { return DefinedValues.size(); }
-
- /// \return an ID for the concrete type of this object.
- /// This is used to implement the classof checks. This should not be used
- /// for any other purpose, as the values may change as LLVM evolves.
- unsigned getVPDefID() const { return SubclassID; }
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- /// Dump the VPDef to stderr (for debugging).
- LLVM_ABI_FOR_TEST void dump() const;
-
- /// Each concrete VPDef prints itself.
- virtual void print(raw_ostream &O, const Twine &Indent,
- VPSlotTracker &SlotTracker) const = 0;
-#endif
-};
-
} // namespace llvm
#endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H
diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
index b49c57a1332cf..9b1e7c0af7c8c 100644
--- a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
@@ -1015,7 +1015,7 @@ TEST_F(VPRecipeTest, CastVPWidenRecipeToVPUser) {
delete AI;
}
-TEST_F(VPRecipeTest, CastVPWidenCallRecipeToVPUserAndVPDef) {
+TEST_F(VPRecipeTest, CastVPWidenCallRecipeToVPUserAndVPRecipeBase) {
VPlan &Plan = getPlan();
IntegerType *Int32 = IntegerType::get(C, 32);
FunctionType *FTy = FunctionType::get(Int32, false);
@@ -1056,7 +1056,6 @@ TEST_F(VPRecipeTest, CastVPWidenGEPRecipeToVPUserAndVPDef) {
checkVPRecipeCastImpl<VPWidenGEPRecipe, VPUser>(&Recipe);
VPValue *VPV = &Recipe;
- EXPECT_TRUE(isa<VPRecipeBase>(VPV->getDefiningRecipe()));
EXPECT_EQ(&Recipe, VPV->getDefiningRecipe());
delete GEP;
@@ -1141,7 +1140,7 @@ TEST_F(VPRecipeTest, CastVPBranchOnMaskRecipeToVPUser) {
checkVPRecipeCastImpl<VPBranchOnMaskRecipe, VPUser>(&Recipe);
}
-TEST_F(VPRecipeTest, CastVPWidenMemoryRecipeToVPUserAndVPDef) {
+TEST_F(VPRecipeTest, CastVPWidenMemoryRecipeToVPUserAndVPRecipeBase) {
VPlan &Plan = getPlan();
IntegerType *Int32 = IntegerType::get(C, 32);
PointerType *Int32Ptr = PointerType::get(C, 0);
@@ -1154,7 +1153,6 @@ TEST_F(VPRecipeTest, CastVPWidenMemoryRecipeToVPUserAndVPDef) {
checkVPRecipeCastImpl<VPWidenLoadRecipe, VPUser, VPIRMetadata>(&Recipe);
VPValue *VPV = Recipe.getVPSingleValue();
- EXPECT_TRUE(isa<VPRecipeBase>(VPV->getDefiningRecipe()));
EXPECT_EQ(&Recipe, VPV->getDefiningRecipe());
delete Load;
@@ -1432,7 +1430,7 @@ TEST_F(VPRecipeTest, dumpRecipeInPlan) {
},
testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
- VPDef *Def = WidenR;
+ VPRecipeBase *Def = WidenR;
EXPECT_EXIT(
{
Def->dump();
@@ -1455,15 +1453,6 @@ TEST_F(VPRecipeTest, dumpRecipeInPlan) {
exit(0);
},
testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
-
- // Test VPDef::dump().
- VPDef *D = WidenR;
- EXPECT_EXIT(
- {
- D->dump();
- exit(0);
- },
- testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
}
delete AI;
@@ -1511,15 +1500,6 @@ TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesInPlan) {
exit(0);
},
testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>");
-
- // Test VPDef::dump().
- VPDef *D = I1;
- EXPECT_EXIT(
- {
- D->dump();
- exit(0);
- },
- testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>");
}
// Check printing I2.
{
@@ -1542,15 +1522,6 @@ TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesInPlan) {
exit(0);
},
testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>");
-
- // Test VPDef::dump().
- VPDef *D = I2;
- EXPECT_EXIT(
- {
- D->dump();
- exit(0);
- },
- testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>");
}
delete AI;
}
@@ -1587,15 +1558,6 @@ TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesNotInPlanOrBlock) {
exit(0);
},
testing::ExitedWithCode(0), "EMIT <badref> = add ir<1>, ir<%a>");
-
- // Test VPDef::dump().
- VPDef *D = I1;
- EXPECT_EXIT(
- {
- D->dump();
- exit(0);
- },
- testing::ExitedWithCode(0), "EMIT <badref> = add ir<1>, ir<%a>");
}
// Check printing I2.
{
@@ -1618,15 +1580,6 @@ TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesNotInPlanOrBlock) {
exit(0);
},
testing::ExitedWithCode(0), "EMIT <badref> = mul <badref>, <badref>");
-
- // Test VPDef::dump().
- VPDef *D = I2;
- EXPECT_EXIT(
- {
- D->dump();
- exit(0);
- },
- testing::ExitedWithCode(0), "EMIT <badref> = mul <badref>, <badref>");
}
delete I2;
@@ -1683,7 +1636,7 @@ TEST(VPDoubleValueDefTest, traverseUseLists) {
// Check that the def-use chains of a multi-def can be traversed in both
// directions.
- // Create a new VPDef which defines 2 values and has 2 operands.
+ // Create a new VPRecipeBase which defines 2 values and has 2 operands.
VPInstruction Op0(VPInstruction::StepVector, {});
VPInstruction Op1(VPInstruction::VScale, {});
VPDoubleValueDef DoubleValueDef({&Op0, &Op1});
@@ -1694,7 +1647,7 @@ TEST(VPDoubleValueDefTest, traverseUseLists) {
VPInstruction I2(Instruction::Freeze, {DoubleValueDef.getVPValue(0)});
VPInstruction I3(Instruction::Freeze, {DoubleValueDef.getVPValue(1)});
- // Check operands of the VPDef (traversing upwards).
+ // Check operands of the VPRecipeBase (traversing upwards).
SmallVector<VPValue *, 4> DoubleOperands(DoubleValueDef.op_begin(),
DoubleValueDef.op_end());
EXPECT_EQ(2u, DoubleOperands.size());
@@ -1716,7 +1669,7 @@ TEST(VPDoubleValueDefTest, traverseUseLists) {
EXPECT_EQ(&I1, DoubleValueDefV1Users[0]);
EXPECT_EQ(&I3, DoubleValueDefV1Users[1]);
- // Now check that we can get the right VPDef for each defined value.
+ // Now check that we can get the right VPRecipeBase for each defined value.
EXPECT_EQ(&DoubleValueDef, I1.getOperand(0)->getDefiningRecipe());
EXPECT_EQ(&DoubleValueDef, I1.getOperand(1)->getDefiningRecipe());
EXPECT_EQ(&DoubleValueDef, I2.getOperand(0)->getDefiningRecipe());
>From a98f1edca1b30d546d41b0b66e32ebf644692e8e Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Fri, 9 Jan 2026 20:57:10 +0000
Subject: [PATCH 2/3] !fixup address comments, restore VPDef for now
---
llvm/lib/Transforms/Vectorize/VPlan.cpp | 8 +--
llvm/lib/Transforms/Vectorize/VPlan.h | 59 ++++-------------
llvm/lib/Transforms/Vectorize/VPlanValue.h | 74 +++++++++++++++++++++-
3 files changed, 87 insertions(+), 54 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index 5f050627a1fbc..c78e622e50ad0 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -116,16 +116,12 @@ void VPRecipeBase::dump() const {
VPRecipeBase *VPValue::getDefiningRecipe() {
auto *DefValue = dyn_cast<VPRecipeValue>(this);
- if (!DefValue)
- return nullptr;
- return DefValue->Def;
+ return DefValue ? DefValue->Def : nullptr;
}
const VPRecipeBase *VPValue::getDefiningRecipe() const {
auto *DefValue = dyn_cast<VPRecipeValue>(this);
- if (!DefValue)
- return nullptr;
- return DefValue->Def;
+ return DefValue ? DefValue->Def : nullptr;
}
Value *VPValue::getLiveInIRValue() const {
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index c054be345d008..4325f7f205722 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -377,12 +377,13 @@ class LLVM_ABI_FOR_TEST VPBlockBase {
};
/// VPRecipeBase is a base class modeling a sequence of one or more output IR
-/// instructions. VPRecipeBase owns the VPValues it defines and is responsible
-/// for deleting its defined values. Single-value recipes must inherit from
-/// VPSingleDefRecipe instead of inheriting from both VPRecipeBase and VPValue
-/// separately.
+/// instructions. VPRecipeBase owns the VPValues it defines through VPDef
+/// and is responsible for deleting its defined values. Single-value recipes
+/// must inherit from VPSingleDefRecipe instead of inheriting from both
+/// VPRecipeBase and VPValue separately.
class LLVM_ABI_FOR_TEST VPRecipeBase
: public ilist_node_with_parent<VPRecipeBase, VPBasicBlock>,
+ public VPDef,
public VPUser {
friend VPBasicBlock;
friend class VPBlockUtils;
@@ -394,12 +395,6 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
/// The debug location for the recipe.
DebugLoc DL;
- /// Subclass identifier (for isa/dyn_cast).
- const unsigned char SubclassID;
-
- /// The VPValues defined by this VPRecipeBase.
- TinyPtrVector<VPRecipeValue *> DefinedValues;
-
/// Add \p V as a defined value by this VPRecipeBase.
void addDefinedValue(VPRecipeValue *V) {
assert(V->Def == this &&
@@ -473,9 +468,9 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
VPRecipeBase(const unsigned char SC, ArrayRef<VPValue *> Operands,
DebugLoc DL = DebugLoc::getUnknown())
- : VPUser(Operands), DL(DL), SubclassID(SC) {}
+ : VPDef(SC), VPUser(Operands), DL(DL) {}
- virtual ~VPRecipeBase() {
+ ~VPRecipeBase() override {
for (VPRecipeValue *D : to_vector(DefinedValues)) {
assert(
D->Def == this &&
@@ -486,41 +481,10 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
}
}
- /// Returns the only VPValue defined by the VPRecipeBase. Can only be called
- /// for VPRecipeBases with a single defined value.
- VPValue *getVPSingleValue() {
- assert(DefinedValues.size() == 1 && "must have exactly one defined value");
- assert(DefinedValues[0] && "defined value must be non-null");
- return DefinedValues[0];
- }
- const VPValue *getVPSingleValue() const {
- assert(DefinedValues.size() == 1 && "must have exactly one defined value");
- assert(DefinedValues[0] && "defined value must be non-null");
- return DefinedValues[0];
- }
-
- /// Returns the VPValue with index \p I defined by the VPRecipeBase.
- VPValue *getVPValue(unsigned I) {
- assert(DefinedValues[I] && "defined value must be non-null");
- return DefinedValues[I];
- }
- const VPValue *getVPValue(unsigned I) const {
- assert(DefinedValues[I] && "defined value must be non-null");
- return DefinedValues[I];
- }
-
- /// Returns an ArrayRef of the values defined by the VPRecipeBase.
- ArrayRef<VPRecipeValue *> definedValues() { return DefinedValues; }
- /// Returns an ArrayRef of the values defined by the VPRecipeBase.
- ArrayRef<VPRecipeValue *> definedValues() const { return DefinedValues; }
-
- /// Returns the number of values defined by the VPRecipeBase.
- unsigned getNumDefinedValues() const { return DefinedValues.size(); }
-
/// \return an ID for the concrete type of this object.
/// This is used to implement the classof checks. This should not be used
/// for any other purpose, as the values may change as LLVM evolves.
- unsigned getVPRecipeID() const { return SubclassID; }
+ unsigned getVPRecipeID() const { return getVPDefID(); }
/// Clone the current recipe.
virtual VPRecipeBase *clone() = 0;
@@ -572,6 +536,11 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
iplist<VPRecipeBase>::iterator eraseFromParent();
/// Method to support type inquiry through isa, cast, and dyn_cast.
+ static inline bool classof(const VPDef *D) {
+ // All VPDefs are also VPRecipeBases.
+ return true;
+ }
+
static inline bool classof(const VPUser *U) { return true; }
/// Returns true if the recipe may have side-effects.
@@ -606,7 +575,7 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
/// Print the recipe, delegating to printRecipe().
void print(raw_ostream &O, const Twine &Indent,
- VPSlotTracker &SlotTracker) const;
+ VPSlotTracker &SlotTracker) const override final;
#endif
protected:
diff --git a/llvm/lib/Transforms/Vectorize/VPlanValue.h b/llvm/lib/Transforms/Vectorize/VPlanValue.h
index 3187984a1d706..9124864c20962 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanValue.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanValue.h
@@ -10,9 +10,9 @@
/// This file contains the declarations of the entities induced by Vectorization
/// Plans, e.g. the instructions the VPlan intends to generate if executed.
/// VPlan models the following entities:
-/// VPValue VPUser VPRecipeBase
-/// | | |
-/// VPInstruction ------+
+/// VPValue VPUser VPDef
+/// | | |
+/// VPInstruction -----+
/// These are documented in docs/VectorizationPlan.rst.
///
//===----------------------------------------------------------------------===//
@@ -33,6 +33,7 @@ class raw_ostream;
class Type;
class Value;
class VPSlotTracker;
+class VPDef;
class VPUser;
class VPRecipeBase;
class VPPhiAccessors;
@@ -41,6 +42,7 @@ class VPPhiAccessors;
/// data flow into, within and out of the VPlan. VPValues can stand for live-ins
/// coming from the input IR, symbolic values and values defined by recipes.
class LLVM_ABI_FOR_TEST VPValue {
+ friend class VPDef;
friend class VPlan;
friend struct VPIRValue;
friend struct VPSymbolicValue;
@@ -206,6 +208,7 @@ struct VPSymbolicValue : public VPValue {
/// A VPValue defined by a recipe that produces one or more values.
class VPRecipeValue : public VPValue {
friend class VPValue;
+ friend class VPDef;
friend class VPRecipeBase;
/// Pointer to the VPRecipeBase that defines this VPValue.
VPRecipeBase *Def;
@@ -320,6 +323,71 @@ class VPUser {
}
};
+/// This class augments a recipe with a set of VPValues defined by the recipe.
+/// It allows recipes to define zero, one or multiple VPValues. A VPDef owns
+/// the VPValues it defines and is responsible for deleting its defined values.
+/// Single-value VPDefs that also inherit from VPValue must make sure to inherit
+/// from VPDef before VPValue.
+class VPDef {
+ friend class VPRecipeBase;
+
+ /// Subclass identifier (for isa/dyn_cast).
+ const unsigned char SubclassID;
+
+ /// The VPValues defined by this VPDef.
+ TinyPtrVector<VPRecipeValue *> DefinedValues;
+
+public:
+ VPDef(const unsigned char SC) : SubclassID(SC) {}
+
+ virtual ~VPDef() = default;
+
+ /// Returns the only VPValue defined by the VPDef. Can only be called for
+ /// VPDefs with a single defined value.
+ VPValue *getVPSingleValue() {
+ assert(DefinedValues.size() == 1 && "must have exactly one defined value");
+ assert(DefinedValues[0] && "defined value must be non-null");
+ return DefinedValues[0];
+ }
+ const VPValue *getVPSingleValue() const {
+ assert(DefinedValues.size() == 1 && "must have exactly one defined value");
+ assert(DefinedValues[0] && "defined value must be non-null");
+ return DefinedValues[0];
+ }
+
+ /// Returns the VPValue with index \p I defined by the VPDef.
+ VPValue *getVPValue(unsigned I) {
+ assert(DefinedValues[I] && "defined value must be non-null");
+ return DefinedValues[I];
+ }
+ const VPValue *getVPValue(unsigned I) const {
+ assert(DefinedValues[I] && "defined value must be non-null");
+ return DefinedValues[I];
+ }
+
+ /// Returns an ArrayRef of the values defined by the VPDef.
+ ArrayRef<VPRecipeValue *> definedValues() { return DefinedValues; }
+ /// Returns an ArrayRef of the values defined by the VPDef.
+ ArrayRef<VPRecipeValue *> definedValues() const { return DefinedValues; }
+
+ /// Returns the number of values defined by the VPDef.
+ unsigned getNumDefinedValues() const { return DefinedValues.size(); }
+
+ /// \return an ID for the concrete type of this object.
+ /// This is used to implement the classof checks. This should not be used
+ /// for any other purpose, as the values may change as LLVM evolves.
+ unsigned getVPDefID() const { return SubclassID; }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ /// Dump the VPDef to stderr (for debugging).
+ LLVM_ABI_FOR_TEST void dump() const;
+
+ /// Each concrete VPDef prints itself.
+ virtual void print(raw_ostream &O, const Twine &Indent,
+ VPSlotTracker &SlotTracker) const = 0;
+#endif
+};
+
} // namespace llvm
#endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H
>From f4abb0f7eac7c8bfa78fbd3aa93fdf4ffe766c33 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Sun, 11 Jan 2026 16:56:02 +0000
Subject: [PATCH 3/3] !fixup restore VPDef class as much as possible
---
llvm/docs/VectorizationPlan.rst | 8 +++--
llvm/lib/Transforms/Vectorize/VPlan.cpp | 2 ++
llvm/lib/Transforms/Vectorize/VPlan.h | 30 +---------------
llvm/lib/Transforms/Vectorize/VPlanValue.h | 41 ++++++++++++++++++----
4 files changed, 44 insertions(+), 37 deletions(-)
diff --git a/llvm/docs/VectorizationPlan.rst b/llvm/docs/VectorizationPlan.rst
index b8db8cab843cf..73e9e6098175a 100644
--- a/llvm/docs/VectorizationPlan.rst
+++ b/llvm/docs/VectorizationPlan.rst
@@ -186,8 +186,7 @@ The low-level design of VPlan comprises of the following classes.
input IR instructions are referred to as "Ingredients" of the Recipe. A Recipe
may specify how its ingredients are to be transformed to produce the output IR
instructions; e.g., cloned once, replicated multiple times or widened
- according to selected VF. VPRecipeBase also defines zero, one or multiple
- VPValues, modeling the fact that recipes can produce multiple results.
+ according to selected VF.
:VPValue:
The base of VPlan's def-use relations class hierarchy. When instantiated, it
@@ -198,6 +197,11 @@ The low-level design of VPlan comprises of the following classes.
A VPUser represents an entity that uses a number of VPValues as operands.
VPUser is similar in some aspects to LLVM's User class.
+:VPDef:
+ A VPDef represents an entity that defines zero, one or multiple VPValues.
+ It is used to model the fact that recipes in VPlan can define multiple
+ VPValues.
+
:VPInstruction:
A VPInstruction is a recipe characterized by a single opcode and optional
flags, free of ingredients or other meta-data. VPInstructions also extend
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index c78e622e50ad0..6cd828e8c2db8 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -114,6 +114,8 @@ void VPRecipeBase::dump() const {
}
#endif
+bool VPRecipeValue::isDefinedBy(const VPDef *D) const { return Def == D; }
+
VPRecipeBase *VPValue::getDefiningRecipe() {
auto *DefValue = dyn_cast<VPRecipeValue>(this);
return DefValue ? DefValue->Def : nullptr;
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 17aa4f081f5a1..2c0efb71d7d0e 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -387,7 +387,6 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
public VPUser {
friend VPBasicBlock;
friend class VPBlockUtils;
- friend class VPRecipeValue;
/// Each VPRecipe belongs to a single VPBasicBlock.
VPBasicBlock *Parent = nullptr;
@@ -395,24 +394,6 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
/// The debug location for the recipe.
DebugLoc DL;
- /// Add \p V as a defined value by this VPRecipeBase.
- void addDefinedValue(VPRecipeValue *V) {
- assert(V->Def == this &&
- "can only add VPValue already linked with this VPRecipeBase");
- DefinedValues.push_back(V);
- }
-
- /// Remove \p V from the values defined by this VPRecipeBase. \p V must be a
- /// defined value of this VPRecipeBase.
- void removeDefinedValue(VPRecipeValue *V) {
- assert(V->Def == this &&
- "can only remove VPValue linked with this VPRecipeBase");
- assert(is_contained(DefinedValues, V) &&
- "VPValue to remove must be in DefinedValues");
- llvm::erase(DefinedValues, V);
- V->Def = nullptr;
- }
-
public:
/// An enumeration for keeping track of the concrete subclass of VPRecipeBase
/// that is actually instantiated. Values of this enumeration are kept in the
@@ -470,16 +451,7 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
DebugLoc DL = DebugLoc::getUnknown())
: VPDef(SC), VPUser(Operands), DL(DL) {}
- ~VPRecipeBase() override {
- for (VPRecipeValue *D : to_vector(DefinedValues)) {
- assert(
- D->Def == this &&
- "all defined VPValues should point to the containing VPRecipeBase");
- assert(D->getNumUsers() == 0 &&
- "all defined VPValues should have no more users");
- delete D;
- }
- }
+ ~VPRecipeBase() override = default;
/// \return an ID for the concrete type of this object.
/// This is used to implement the classof checks. This should not be used
diff --git a/llvm/lib/Transforms/Vectorize/VPlanValue.h b/llvm/lib/Transforms/Vectorize/VPlanValue.h
index 9124864c20962..aefc94a3c0bea 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanValue.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanValue.h
@@ -11,8 +11,8 @@
/// Plans, e.g. the instructions the VPlan intends to generate if executed.
/// VPlan models the following entities:
/// VPValue VPUser VPDef
-/// | | |
-/// VPInstruction -----+
+/// | |
+/// VPInstruction
/// These are documented in docs/VectorizationPlan.rst.
///
//===----------------------------------------------------------------------===//
@@ -209,10 +209,12 @@ struct VPSymbolicValue : public VPValue {
class VPRecipeValue : public VPValue {
friend class VPValue;
friend class VPDef;
- friend class VPRecipeBase;
- /// Pointer to the VPRecipeBase that defines this VPValue.
+ /// Pointer to the VPDef that defines this VPValue.
VPRecipeBase *Def;
+ /// Returns true if this VPRecipeValue is defined by \p D.
+ bool isDefinedBy(const VPDef *D) const;
+
public:
VPRecipeValue(VPRecipeBase *Def, Value *UV = nullptr);
@@ -329,7 +331,8 @@ class VPUser {
/// Single-value VPDefs that also inherit from VPValue must make sure to inherit
/// from VPDef before VPValue.
class VPDef {
- friend class VPRecipeBase;
+ friend class VPValue;
+ friend class VPRecipeValue;
/// Subclass identifier (for isa/dyn_cast).
const unsigned char SubclassID;
@@ -337,10 +340,36 @@ class VPDef {
/// The VPValues defined by this VPDef.
TinyPtrVector<VPRecipeValue *> DefinedValues;
+ /// Add \p V as a defined value by this VPDef.
+ void addDefinedValue(VPRecipeValue *V) {
+ assert(V->isDefinedBy(this) &&
+ "can only add VPValue already linked with this VPDef");
+ DefinedValues.push_back(V);
+ }
+
+ /// Remove \p V from the values defined by this VPDef. \p V must be a defined
+ /// value of this VPDef.
+ void removeDefinedValue(VPRecipeValue *V) {
+ assert(V->isDefinedBy(this) &&
+ "can only remove VPValue linked with this VPDef");
+ assert(is_contained(DefinedValues, V) &&
+ "VPValue to remove must be in DefinedValues");
+ llvm::erase(DefinedValues, V);
+ V->Def = nullptr;
+ }
+
public:
VPDef(const unsigned char SC) : SubclassID(SC) {}
- virtual ~VPDef() = default;
+ virtual ~VPDef() {
+ for (VPRecipeValue *D : to_vector(DefinedValues)) {
+ assert(D->isDefinedBy(this) &&
+ "all defined VPValues should point to the containing VPDef");
+ assert(D->getNumUsers() == 0 &&
+ "all defined VPValues should have no more users");
+ delete D;
+ }
+ }
/// Returns the only VPValue defined by the VPDef. Can only be called for
/// VPDefs with a single defined value.
More information about the llvm-commits
mailing list