[llvm] abdb61f - [VPlan] Introduce VPSingleDefRecipe. (#77023)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 19 02:27:58 PST 2024
Author: Florian Hahn
Date: 2024-01-19T10:27:53Z
New Revision: abdb61f5fd0fa6f184aa2c7f3b676879a71df8a8
URL: https://github.com/llvm/llvm-project/commit/abdb61f5fd0fa6f184aa2c7f3b676879a71df8a8
DIFF: https://github.com/llvm/llvm-project/commit/abdb61f5fd0fa6f184aa2c7f3b676879a71df8a8.diff
LOG: [VPlan] Introduce VPSingleDefRecipe. (#77023)
This patch introduces a new common base class for recipes defining a
single result VPValue. This has been discussed/mentioned at various
previous reviews as potential follow-up and helps to replace various
getVPSingleValue calls.
PR: https://github.com/llvm/llvm-project/pull/77023
Added:
Modified:
llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
llvm/lib/Transforms/Vectorize/VPlan.h
llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 77d54c9d08f4e6..fa1aa15fa822d9 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -8963,16 +8963,17 @@ void LoopVectorizationPlanner::adjustRecipesForReductions(
"AnyOf reductions are not allowed for in-loop reductions");
// Collect the chain of "link" recipes for the reduction starting at PhiR.
- SetVector<VPRecipeBase *> Worklist;
+ SetVector<VPSingleDefRecipe *> Worklist;
Worklist.insert(PhiR);
for (unsigned I = 0; I != Worklist.size(); ++I) {
- VPRecipeBase *Cur = Worklist[I];
- for (VPUser *U : Cur->getVPSingleValue()->users()) {
- auto *UserRecipe = dyn_cast<VPRecipeBase>(U);
- if (!UserRecipe)
+ VPSingleDefRecipe *Cur = Worklist[I];
+ for (VPUser *U : Cur->users()) {
+ auto *UserRecipe = dyn_cast<VPSingleDefRecipe>(U);
+ if (!UserRecipe) {
+ assert(isa<VPLiveOut>(U) &&
+ "U must either be a VPSingleDef or VPLiveOut");
continue;
- assert(UserRecipe->getNumDefinedValues() == 1 &&
- "recipes must define exactly one result value");
+ }
Worklist.insert(UserRecipe);
}
}
@@ -8982,10 +8983,8 @@ void LoopVectorizationPlanner::adjustRecipesForReductions(
// (PreviousLink) to tell which of the two operands of a Link will remain
// scalar and which will be reduced. For minmax by select(cmp), Link will be
// the select instructions.
- VPRecipeBase *PreviousLink = PhiR; // Aka Worklist[0].
- for (VPRecipeBase *CurrentLink : Worklist.getArrayRef().drop_front()) {
- VPValue *PreviousLinkV = PreviousLink->getVPSingleValue();
-
+ VPSingleDefRecipe *PreviousLink = PhiR; // Aka Worklist[0].
+ for (VPSingleDefRecipe *CurrentLink : Worklist.getArrayRef().drop_front()) {
Instruction *CurrentLinkI = CurrentLink->getUnderlyingInstr();
// Index of the first operand which holds a non-mask vector operand.
@@ -9000,7 +8999,7 @@ void LoopVectorizationPlanner::adjustRecipesForReductions(
"Expected instruction to be a call to the llvm.fmuladd intrinsic");
assert(((MinVF.isScalar() && isa<VPReplicateRecipe>(CurrentLink)) ||
isa<VPWidenCallRecipe>(CurrentLink)) &&
- CurrentLink->getOperand(2) == PreviousLinkV &&
+ CurrentLink->getOperand(2) == PreviousLink &&
"expected a call where the previous link is the added operand");
// If the instruction is a call to the llvm.fmuladd intrinsic then we
@@ -9031,15 +9030,15 @@ void LoopVectorizationPlanner::adjustRecipesForReductions(
// Note that for non-commutable operands (cmp-selects), the semantics of
// the cmp-select are captured in the recurrence kind.
unsigned VecOpId =
- CurrentLink->getOperand(IndexOfFirstOperand) == PreviousLinkV
+ CurrentLink->getOperand(IndexOfFirstOperand) == PreviousLink
? IndexOfFirstOperand + 1
: IndexOfFirstOperand;
VecOp = CurrentLink->getOperand(VecOpId);
- assert(VecOp != PreviousLinkV &&
+ assert(VecOp != PreviousLink &&
CurrentLink->getOperand(CurrentLink->getNumOperands() - 1 -
(VecOpId - IndexOfFirstOperand)) ==
- PreviousLinkV &&
- "PreviousLinkV must be the operand other than VecOp");
+ PreviousLink &&
+ "PreviousLink must be the operand other than VecOp");
}
BasicBlock *BB = CurrentLinkI->getParent();
@@ -9051,13 +9050,13 @@ void LoopVectorizationPlanner::adjustRecipesForReductions(
}
VPReductionRecipe *RedRecipe = new VPReductionRecipe(
- RdxDesc, CurrentLinkI, PreviousLinkV, VecOp, CondOp);
+ RdxDesc, CurrentLinkI, PreviousLink, VecOp, CondOp);
// Append the recipe to the end of the VPBasicBlock because we need to
// ensure that it comes after all of it's inputs, including CondOp.
// Note that this transformation may leave over dead recipes (including
// CurrentLink), which will be cleaned by a later VPlan transform.
LinkVPBB->appendRecipe(RedRecipe);
- CurrentLink->getVPSingleValue()->replaceAllUsesWith(RedRecipe);
+ CurrentLink->replaceAllUsesWith(RedRecipe);
PreviousLink = RedRecipe;
}
}
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 4b4f4911eb6415..bdbb61b88ecb23 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -12,10 +12,12 @@
/// VPBlockBase, together implementing a Hierarchical CFG;
/// 2. Pure virtual VPRecipeBase serving as the base class for recipes contained
/// within VPBasicBlocks;
-/// 3. VPInstruction, a concrete Recipe and VPUser modeling a single planned
+/// 3. Pure virtual VPSingleDefRecipe serving as a base class for recipes that
+/// also inherit from VPValue.
+/// 4. VPInstruction, a concrete Recipe and VPUser modeling a single planned
/// instruction;
-/// 4. The VPlan class holding a candidate for vectorization;
-/// 5. The VPlanPrinter class providing a way to print a plan in dot format;
+/// 5. The VPlan class holding a candidate for vectorization;
+/// 6. The VPlanPrinter class providing a way to print a plan in dot format;
/// These are documented in docs/VectorizationPlan.rst.
//
//===----------------------------------------------------------------------===//
@@ -700,8 +702,8 @@ class VPLiveOut : public VPUser {
/// 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
-/// VPRecipeBases that also inherit from VPValue must make sure to inherit from
-/// VPRecipeBase before VPValue.
+/// recipes must inherit from VPSingleDef instead of inheriting from both
+/// VPRecipeBase and VPValue separately.
class VPRecipeBase : public ilist_node_with_parent<VPRecipeBase, VPBasicBlock>,
public VPDef,
public VPUser {
@@ -762,15 +764,6 @@ class VPRecipeBase : public ilist_node_with_parent<VPRecipeBase, VPBasicBlock>,
/// \returns an iterator pointing to the element after the erased one
iplist<VPRecipeBase>::iterator eraseFromParent();
- /// Returns the underlying instruction, if the recipe is a VPValue or nullptr
- /// otherwise.
- Instruction *getUnderlyingInstr() {
- return cast<Instruction>(getVPSingleValue()->getUnderlyingValue());
- }
- const Instruction *getUnderlyingInstr() const {
- return cast<Instruction>(getVPSingleValue()->getUnderlyingValue());
- }
-
/// Method to support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const VPDef *D) {
// All VPDefs are also VPRecipeBases.
@@ -819,10 +812,80 @@ class VPRecipeBase : public ilist_node_with_parent<VPRecipeBase, VPBasicBlock>,
} \
static inline bool classof(const VPRecipeBase *R) { \
return R->getVPDefID() == VPDefID; \
+ } \
+ static inline bool classof(const VPSingleDefRecipe *R) { \
+ return R->getVPDefID() == VPDefID; \
}
+/// VPSingleDef is a base class for recipes for modeling a sequence of one or
+/// more output IR that define a single result VPValue.
+/// Note that VPRecipeBase must be inherited from before VPValue.
+class VPSingleDefRecipe : public VPRecipeBase, public VPValue {
+public:
+ template <typename IterT>
+ VPSingleDefRecipe(const unsigned char SC, IterT Operands, DebugLoc DL = {})
+ : VPRecipeBase(SC, Operands, DL), VPValue(this) {}
+
+ VPSingleDefRecipe(const unsigned char SC, ArrayRef<VPValue *> Operands,
+ DebugLoc DL = {})
+ : VPRecipeBase(SC, Operands, DL), VPValue(this) {}
+
+ template <typename IterT>
+ VPSingleDefRecipe(const unsigned char SC, IterT Operands, Value *UV,
+ DebugLoc DL = {})
+ : VPRecipeBase(SC, Operands, DL), VPValue(this, UV) {}
+
+ static inline bool classof(const VPRecipeBase *R) {
+ switch (R->getVPDefID()) {
+ case VPRecipeBase::VPDerivedIVSC:
+ case VPRecipeBase::VPExpandSCEVSC:
+ case VPRecipeBase::VPInstructionSC:
+ case VPRecipeBase::VPReductionSC:
+ case VPRecipeBase::VPReplicateSC:
+ case VPRecipeBase::VPScalarIVStepsSC:
+ case VPRecipeBase::VPVectorPointerSC:
+ case VPRecipeBase::VPWidenCallSC:
+ case VPRecipeBase::VPWidenCanonicalIVSC:
+ case VPRecipeBase::VPWidenCastSC:
+ case VPRecipeBase::VPWidenGEPSC:
+ case VPRecipeBase::VPWidenSC:
+ case VPRecipeBase::VPWidenSelectSC:
+ case VPRecipeBase::VPBlendSC:
+ case VPRecipeBase::VPPredInstPHISC:
+ case VPRecipeBase::VPCanonicalIVPHISC:
+ case VPRecipeBase::VPActiveLaneMaskPHISC:
+ case VPRecipeBase::VPFirstOrderRecurrencePHISC:
+ case VPRecipeBase::VPWidenPHISC:
+ case VPRecipeBase::VPWidenIntOrFpInductionSC:
+ case VPRecipeBase::VPWidenPointerInductionSC:
+ case VPRecipeBase::VPReductionPHISC:
+ return true;
+ case VPRecipeBase::VPInterleaveSC:
+ case VPRecipeBase::VPBranchOnMaskSC:
+ case VPRecipeBase::VPWidenMemoryInstructionSC:
+ // TODO: Widened stores don't define a value, but widened loads do. Split
+ // the recipes to be able to make widened loads VPSingleDefRecipes.
+ return false;
+ }
+ llvm_unreachable("Unhandled VPDefID");
+ }
+
+ static inline bool classof(const VPUser *U) {
+ auto *R = dyn_cast<VPRecipeBase>(U);
+ return R && classof(R);
+ }
+
+ /// Returns the underlying instruction.
+ Instruction *getUnderlyingInstr() {
+ return cast<Instruction>(getUnderlyingValue());
+ }
+ const Instruction *getUnderlyingInstr() const {
+ return cast<Instruction>(getUnderlyingValue());
+ }
+};
+
/// Class to record LLVM IR flag for a recipe along with it.
-class VPRecipeWithIRFlags : public VPRecipeBase {
+class VPRecipeWithIRFlags : public VPSingleDefRecipe {
enum class OperationType : unsigned char {
Cmp,
OverflowingBinOp,
@@ -886,14 +949,14 @@ class VPRecipeWithIRFlags : public VPRecipeBase {
public:
template <typename IterT>
VPRecipeWithIRFlags(const unsigned char SC, IterT Operands, DebugLoc DL = {})
- : VPRecipeBase(SC, Operands, DL) {
+ : VPSingleDefRecipe(SC, Operands, DL) {
OpType = OperationType::Other;
AllFlags = 0;
}
template <typename IterT>
VPRecipeWithIRFlags(const unsigned char SC, IterT Operands, Instruction &I)
- : VPRecipeWithIRFlags(SC, Operands, I.getDebugLoc()) {
+ : VPSingleDefRecipe(SC, Operands, &I, I.getDebugLoc()) {
if (auto *Op = dyn_cast<CmpInst>(&I)) {
OpType = OperationType::Cmp;
CmpPredicate = Op->getPredicate();
@@ -915,32 +978,35 @@ class VPRecipeWithIRFlags : public VPRecipeBase {
} else if (auto *Op = dyn_cast<FPMathOperator>(&I)) {
OpType = OperationType::FPMathOp;
FMFs = Op->getFastMathFlags();
+ } else {
+ OpType = OperationType::Other;
+ AllFlags = 0;
}
}
template <typename IterT>
VPRecipeWithIRFlags(const unsigned char SC, IterT Operands,
CmpInst::Predicate Pred, DebugLoc DL = {})
- : VPRecipeBase(SC, Operands, DL), OpType(OperationType::Cmp),
+ : VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::Cmp),
CmpPredicate(Pred) {}
template <typename IterT>
VPRecipeWithIRFlags(const unsigned char SC, IterT Operands,
WrapFlagsTy WrapFlags, DebugLoc DL = {})
- : VPRecipeBase(SC, Operands, DL), OpType(OperationType::OverflowingBinOp),
- WrapFlags(WrapFlags) {}
+ : VPSingleDefRecipe(SC, Operands, DL),
+ OpType(OperationType::OverflowingBinOp), WrapFlags(WrapFlags) {}
template <typename IterT>
VPRecipeWithIRFlags(const unsigned char SC, IterT Operands,
FastMathFlags FMFs, DebugLoc DL = {})
- : VPRecipeBase(SC, Operands, DL), OpType(OperationType::FPMathOp),
+ : VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::FPMathOp),
FMFs(FMFs) {}
protected:
template <typename IterT>
VPRecipeWithIRFlags(const unsigned char SC, IterT Operands,
GEPFlagsTy GEPFlags, DebugLoc DL = {})
- : VPRecipeBase(SC, Operands, DL), OpType(OperationType::GEPOp),
+ : VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::GEPOp),
GEPFlags(GEPFlags) {}
public:
@@ -1056,7 +1122,7 @@ class VPRecipeWithIRFlags : public VPRecipeBase {
/// While as any Recipe it may generate a sequence of IR instructions when
/// executed, these instructions would always form a single-def expression as
/// the VPInstruction is also a single def-use vertex.
-class VPInstruction : public VPRecipeWithIRFlags, public VPValue {
+class VPInstruction : public VPRecipeWithIRFlags {
friend class VPlanSlp;
public:
@@ -1103,7 +1169,7 @@ class VPInstruction : public VPRecipeWithIRFlags, public VPValue {
VPInstruction(unsigned Opcode, ArrayRef<VPValue *> Operands, DebugLoc DL,
const Twine &Name = "")
: VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, DL),
- VPValue(this), Opcode(Opcode), Name(Name.str()) {}
+ Opcode(Opcode), Name(Name.str()) {}
VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands,
DebugLoc DL = {}, const Twine &Name = "")
@@ -1115,7 +1181,7 @@ class VPInstruction : public VPRecipeWithIRFlags, public VPValue {
VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands,
WrapFlagsTy WrapFlags, DebugLoc DL = {}, const Twine &Name = "")
: VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, WrapFlags, DL),
- VPValue(this), Opcode(Opcode), Name(Name.str()) {}
+ Opcode(Opcode), Name(Name.str()) {}
VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands,
FastMathFlags FMFs, DebugLoc DL = {}, const Twine &Name = "");
@@ -1205,13 +1271,13 @@ class VPInstruction : public VPRecipeWithIRFlags, public VPValue {
/// VPWidenRecipe is a recipe for producing a copy of vector type its
/// ingredient. This recipe covers most of the traditional vectorization cases
/// where each ingredient transforms into a vectorized version of itself.
-class VPWidenRecipe : public VPRecipeWithIRFlags, public VPValue {
+class VPWidenRecipe : public VPRecipeWithIRFlags {
unsigned Opcode;
public:
template <typename IterT>
VPWidenRecipe(Instruction &I, iterator_range<IterT> Operands)
- : VPRecipeWithIRFlags(VPDef::VPWidenSC, Operands, I), VPValue(this, &I),
+ : VPRecipeWithIRFlags(VPDef::VPWidenSC, Operands, I),
Opcode(I.getOpcode()) {}
~VPWidenRecipe() override = default;
@@ -1231,7 +1297,7 @@ class VPWidenRecipe : public VPRecipeWithIRFlags, public VPValue {
};
/// VPWidenCastRecipe is a recipe to create vector cast instructions.
-class VPWidenCastRecipe : public VPRecipeWithIRFlags, public VPValue {
+class VPWidenCastRecipe : public VPRecipeWithIRFlags {
/// Cast instruction opcode.
Instruction::CastOps Opcode;
@@ -1241,8 +1307,8 @@ class VPWidenCastRecipe : public VPRecipeWithIRFlags, public VPValue {
public:
VPWidenCastRecipe(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy,
CastInst &UI)
- : VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op, UI), VPValue(this, &UI),
- Opcode(Opcode), ResultTy(ResultTy) {
+ : VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op, UI), Opcode(Opcode),
+ ResultTy(ResultTy) {
assert(UI.getOpcode() == Opcode &&
"opcode of underlying cast doesn't match");
assert(UI.getType() == ResultTy &&
@@ -1250,8 +1316,8 @@ class VPWidenCastRecipe : public VPRecipeWithIRFlags, public VPValue {
}
VPWidenCastRecipe(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy)
- : VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op), VPValue(this, nullptr),
- Opcode(Opcode), ResultTy(ResultTy) {}
+ : VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op), Opcode(Opcode),
+ ResultTy(ResultTy) {}
~VPWidenCastRecipe() override = default;
@@ -1273,7 +1339,7 @@ class VPWidenCastRecipe : public VPRecipeWithIRFlags, public VPValue {
};
/// A recipe for widening Call instructions.
-class VPWidenCallRecipe : public VPRecipeBase, public VPValue {
+class VPWidenCallRecipe : public VPSingleDefRecipe {
/// ID of the vector intrinsic to call when widening the call. If set the
/// Intrinsic::not_intrinsic, a library call will be used instead.
Intrinsic::ID VectorIntrinsicID;
@@ -1288,7 +1354,7 @@ class VPWidenCallRecipe : public VPRecipeBase, public VPValue {
VPWidenCallRecipe(CallInst &I, iterator_range<IterT> CallArguments,
Intrinsic::ID VectorIntrinsicID,
Function *Variant = nullptr)
- : VPRecipeBase(VPDef::VPWidenCallSC, CallArguments), VPValue(this, &I),
+ : VPSingleDefRecipe(VPDef::VPWidenCallSC, CallArguments, &I),
VectorIntrinsicID(VectorIntrinsicID), Variant(Variant) {}
~VPWidenCallRecipe() override = default;
@@ -1306,11 +1372,11 @@ class VPWidenCallRecipe : public VPRecipeBase, public VPValue {
};
/// A recipe for widening select instructions.
-struct VPWidenSelectRecipe : public VPRecipeBase, public VPValue {
+struct VPWidenSelectRecipe : public VPSingleDefRecipe {
template <typename IterT>
VPWidenSelectRecipe(SelectInst &I, iterator_range<IterT> Operands)
- : VPRecipeBase(VPDef::VPWidenSelectSC, Operands, I.getDebugLoc()),
- VPValue(this, &I) {}
+ : VPSingleDefRecipe(VPDef::VPWidenSelectSC, Operands, &I,
+ I.getDebugLoc()) {}
~VPWidenSelectRecipe() override = default;
@@ -1335,7 +1401,7 @@ struct VPWidenSelectRecipe : public VPRecipeBase, public VPValue {
};
/// A recipe for handling GEP instructions.
-class VPWidenGEPRecipe : public VPRecipeWithIRFlags, public VPValue {
+class VPWidenGEPRecipe : public VPRecipeWithIRFlags {
bool isPointerLoopInvariant() const {
return getOperand(0)->isDefinedOutsideVectorRegions();
}
@@ -1353,8 +1419,7 @@ class VPWidenGEPRecipe : public VPRecipeWithIRFlags, public VPValue {
public:
template <typename IterT>
VPWidenGEPRecipe(GetElementPtrInst *GEP, iterator_range<IterT> Operands)
- : VPRecipeWithIRFlags(VPDef::VPWidenGEPSC, Operands, *GEP),
- VPValue(this, GEP) {}
+ : VPRecipeWithIRFlags(VPDef::VPWidenGEPSC, Operands, *GEP) {}
~VPWidenGEPRecipe() override = default;
@@ -1373,7 +1438,7 @@ class VPWidenGEPRecipe : public VPRecipeWithIRFlags, public VPValue {
/// A recipe to compute the pointers for widened memory accesses of IndexTy for
/// all parts. If IsReverse is true, compute pointers for accessing the input in
/// reverse order per part.
-class VPVectorPointerRecipe : public VPRecipeWithIRFlags, public VPValue {
+class VPVectorPointerRecipe : public VPRecipeWithIRFlags {
Type *IndexedTy;
bool IsReverse;
@@ -1382,7 +1447,7 @@ class VPVectorPointerRecipe : public VPRecipeWithIRFlags, public VPValue {
bool IsInBounds, DebugLoc DL)
: VPRecipeWithIRFlags(VPDef::VPVectorPointerSC, ArrayRef<VPValue *>(Ptr),
GEPFlagsTy(IsInBounds), DL),
- VPValue(this), IndexedTy(IndexedTy), IsReverse(IsReverse) {}
+ IndexedTy(IndexedTy), IsReverse(IsReverse) {}
VP_CLASSOF_IMPL(VPDef::VPVectorPointerSC)
@@ -1424,11 +1489,11 @@ class VPVectorPointerRecipe : public VPRecipeWithIRFlags, public VPValue {
/// * VPWidenPointerInductionRecipe: Generate vector and scalar values for a
/// pointer induction. Produces either a vector PHI per-part or scalar values
/// per-lane based on the canonical induction.
-class VPHeaderPHIRecipe : public VPRecipeBase, public VPValue {
+class VPHeaderPHIRecipe : public VPSingleDefRecipe {
protected:
VPHeaderPHIRecipe(unsigned char VPDefID, Instruction *UnderlyingInstr,
VPValue *Start = nullptr, DebugLoc DL = {})
- : VPRecipeBase(VPDefID, {}, DL), VPValue(this, UnderlyingInstr) {
+ : VPSingleDefRecipe(VPDefID, ArrayRef<VPValue *>(), UnderlyingInstr, DL) {
if (Start)
addOperand(Start);
}
@@ -1709,14 +1774,13 @@ class VPReductionPHIRecipe : public VPHeaderPHIRecipe {
/// A recipe for vectorizing a phi-node as a sequence of mask-based select
/// instructions.
-class VPBlendRecipe : public VPRecipeBase, public VPValue {
+class VPBlendRecipe : public VPSingleDefRecipe {
public:
/// The blend operation is a User of the incoming values and of their
/// respective masks, ordered [I0, M0, I1, M1, ...]. Note that a single value
/// might be incoming with a full mask for which there is no VPValue.
VPBlendRecipe(PHINode *Phi, ArrayRef<VPValue *> Operands)
- : VPRecipeBase(VPDef::VPBlendSC, Operands, Phi->getDebugLoc()),
- VPValue(this, Phi) {
+ : VPSingleDefRecipe(VPDef::VPBlendSC, Operands, Phi, Phi->getDebugLoc()) {
assert(Operands.size() > 0 &&
((Operands.size() == 1) || (Operands.size() % 2 == 0)) &&
"Expected either a single incoming value or a positive even number "
@@ -1843,14 +1907,15 @@ class VPInterleaveRecipe : public VPRecipeBase {
/// A recipe to represent inloop reduction operations, performing a reduction on
/// a vector operand into a scalar value, and adding the result to a chain.
/// The Operands are {ChainOp, VecOp, [Condition]}.
-class VPReductionRecipe : public VPRecipeBase, public VPValue {
+class VPReductionRecipe : public VPSingleDefRecipe {
/// The recurrence decriptor for the reduction in question.
const RecurrenceDescriptor &RdxDesc;
public:
VPReductionRecipe(const RecurrenceDescriptor &R, Instruction *I,
VPValue *ChainOp, VPValue *VecOp, VPValue *CondOp)
- : VPRecipeBase(VPDef::VPReductionSC, {ChainOp, VecOp}), VPValue(this, I),
+ : VPSingleDefRecipe(VPDef::VPReductionSC,
+ ArrayRef<VPValue *>({ChainOp, VecOp}), I),
RdxDesc(R) {
if (CondOp)
addOperand(CondOp);
@@ -1883,7 +1948,7 @@ class VPReductionRecipe : public VPRecipeBase, public VPValue {
/// copies of the original scalar type, one per lane, instead of producing a
/// single copy of widened type for all lanes. If the instruction is known to be
/// uniform only one copy, per lane zero, will be generated.
-class VPReplicateRecipe : public VPRecipeWithIRFlags, public VPValue {
+class VPReplicateRecipe : public VPRecipeWithIRFlags {
/// Indicator if only a single replica per lane is needed.
bool IsUniform;
@@ -1895,7 +1960,7 @@ class VPReplicateRecipe : public VPRecipeWithIRFlags, public VPValue {
VPReplicateRecipe(Instruction *I, iterator_range<IterT> Operands,
bool IsUniform, VPValue *Mask = nullptr)
: VPRecipeWithIRFlags(VPDef::VPReplicateSC, Operands, *I),
- VPValue(this, I), IsUniform(IsUniform), IsPredicated(Mask) {
+ IsUniform(IsUniform), IsPredicated(Mask) {
if (Mask)
addOperand(Mask);
}
@@ -1993,12 +2058,12 @@ class VPBranchOnMaskRecipe : public VPRecipeBase {
/// order to merge values that are set under such a branch and feed their uses.
/// The phi nodes can be scalar or vector depending on the users of the value.
/// This recipe works in concert with VPBranchOnMaskRecipe.
-class VPPredInstPHIRecipe : public VPRecipeBase, public VPValue {
+class VPPredInstPHIRecipe : public VPSingleDefRecipe {
public:
/// Construct a VPPredInstPHIRecipe given \p PredInst whose value needs a phi
/// nodes after merging back from a Branch-on-Mask.
VPPredInstPHIRecipe(VPValue *PredV)
- : VPRecipeBase(VPDef::VPPredInstPHISC, PredV), VPValue(this) {}
+ : VPSingleDefRecipe(VPDef::VPPredInstPHISC, PredV) {}
~VPPredInstPHIRecipe() override = default;
VP_CLASSOF_IMPL(VPDef::VPPredInstPHISC)
@@ -2119,14 +2184,13 @@ class VPWidenMemoryInstructionRecipe : public VPRecipeBase {
};
/// Recipe to expand a SCEV expression.
-class VPExpandSCEVRecipe : public VPRecipeBase, public VPValue {
+class VPExpandSCEVRecipe : public VPSingleDefRecipe {
const SCEV *Expr;
ScalarEvolution &SE;
public:
VPExpandSCEVRecipe(const SCEV *Expr, ScalarEvolution &SE)
- : VPRecipeBase(VPDef::VPExpandSCEVSC, {}), VPValue(this), Expr(Expr),
- SE(SE) {}
+ : VPSingleDefRecipe(VPDef::VPExpandSCEVSC, {}), Expr(Expr), SE(SE) {}
~VPExpandSCEVRecipe() override = default;
@@ -2225,11 +2289,10 @@ class VPActiveLaneMaskPHIRecipe : public VPHeaderPHIRecipe {
};
/// A Recipe for widening the canonical induction variable of the vector loop.
-class VPWidenCanonicalIVRecipe : public VPRecipeBase, public VPValue {
+class VPWidenCanonicalIVRecipe : public VPSingleDefRecipe {
public:
VPWidenCanonicalIVRecipe(VPCanonicalIVPHIRecipe *CanonicalIV)
- : VPRecipeBase(VPDef::VPWidenCanonicalIVSC, {CanonicalIV}),
- VPValue(this) {}
+ : VPSingleDefRecipe(VPDef::VPWidenCanonicalIVSC, {CanonicalIV}) {}
~VPWidenCanonicalIVRecipe() override = default;
@@ -2256,7 +2319,7 @@ class VPWidenCanonicalIVRecipe : public VPRecipeBase, public VPValue {
/// A recipe for converting the canonical IV value to the corresponding value of
/// an IV with
diff erent start and step values, using Start + CanonicalIV *
/// Step.
-class VPDerivedIVRecipe : public VPRecipeBase, public VPValue {
+class VPDerivedIVRecipe : public VPSingleDefRecipe {
/// If not nullptr, the result of the induction will get truncated to
/// TruncResultTy.
Type *TruncResultTy;
@@ -2271,8 +2334,8 @@ class VPDerivedIVRecipe : public VPRecipeBase, public VPValue {
VPDerivedIVRecipe(const InductionDescriptor &IndDesc, VPValue *Start,
VPCanonicalIVPHIRecipe *CanonicalIV, VPValue *Step,
Type *TruncResultTy)
- : VPRecipeBase(VPDef::VPDerivedIVSC, {Start, CanonicalIV, Step}),
- VPValue(this), TruncResultTy(TruncResultTy), Kind(IndDesc.getKind()),
+ : VPSingleDefRecipe(VPDef::VPDerivedIVSC, {Start, CanonicalIV, Step}),
+ TruncResultTy(TruncResultTy), Kind(IndDesc.getKind()),
FPBinOp(dyn_cast_or_null<FPMathOperator>(IndDesc.getInductionBinOp())) {
}
@@ -2309,7 +2372,7 @@ class VPDerivedIVRecipe : public VPRecipeBase, public VPValue {
/// A recipe for handling phi nodes of integer and floating-point inductions,
/// producing their scalar values.
-class VPScalarIVStepsRecipe : public VPRecipeWithIRFlags, public VPValue {
+class VPScalarIVStepsRecipe : public VPRecipeWithIRFlags {
Instruction::BinaryOps InductionOpcode;
public:
@@ -2317,7 +2380,7 @@ class VPScalarIVStepsRecipe : public VPRecipeWithIRFlags, public VPValue {
Instruction::BinaryOps Opcode, FastMathFlags FMFs)
: VPRecipeWithIRFlags(VPDef::VPScalarIVStepsSC,
ArrayRef<VPValue *>({IV, Step}), FMFs),
- VPValue(this), InductionOpcode(Opcode) {}
+ InductionOpcode(Opcode) {}
VPScalarIVStepsRecipe(const InductionDescriptor &IndDesc, VPValue *IV,
VPValue *Step)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index c553e2c9e76839..78e64e7ffb1261 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -258,7 +258,7 @@ VPInstruction::VPInstruction(unsigned Opcode, CmpInst::Predicate Pred,
const Twine &Name)
: VPRecipeWithIRFlags(VPDef::VPInstructionSC, ArrayRef<VPValue *>({A, B}),
Pred, DL),
- VPValue(this), Opcode(Opcode), Name(Name.str()) {
+ Opcode(Opcode), Name(Name.str()) {
assert(Opcode == Instruction::ICmp &&
"only ICmp predicates supported at the moment");
}
@@ -267,7 +267,7 @@ VPInstruction::VPInstruction(unsigned Opcode,
std::initializer_list<VPValue *> Operands,
FastMathFlags FMFs, DebugLoc DL, const Twine &Name)
: VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, FMFs, DL),
- VPValue(this), Opcode(Opcode), Name(Name.str()) {
+ Opcode(Opcode), Name(Name.str()) {
// Make sure the VPInstruction is a floating-point operation.
assert(isFPMathOp() && "this op can't take fast-math flags");
}
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index b3694e74a38509..38671bafb42776 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -103,7 +103,7 @@ static bool sinkScalarOperands(VPlan &Plan) {
bool Changed = false;
// First, collect the operands of all recipes in replicate blocks as seeds for
// sinking.
- SetVector<std::pair<VPBasicBlock *, VPRecipeBase *>> WorkList;
+ SetVector<std::pair<VPBasicBlock *, VPSingleDefRecipe *>> WorkList;
for (VPRegionBlock *VPR : VPBlockUtils::blocksOnly<VPRegionBlock>(Iter)) {
VPBasicBlock *EntryVPBB = VPR->getEntryBasicBlock();
if (!VPR->isReplicator() || EntryVPBB->getSuccessors().size() != 2)
@@ -113,7 +113,8 @@ static bool sinkScalarOperands(VPlan &Plan) {
continue;
for (auto &Recipe : *VPBB) {
for (VPValue *Op : Recipe.operands())
- if (auto *Def = Op->getDefiningRecipe())
+ if (auto *Def =
+ dyn_cast_or_null<VPSingleDefRecipe>(Op->getDefiningRecipe()))
WorkList.insert(std::make_pair(VPBB, Def));
}
}
@@ -122,7 +123,7 @@ static bool sinkScalarOperands(VPlan &Plan) {
// Try to sink each replicate or scalar IV steps recipe in the worklist.
for (unsigned I = 0; I != WorkList.size(); ++I) {
VPBasicBlock *SinkTo;
- VPRecipeBase *SinkCandidate;
+ VPSingleDefRecipe *SinkCandidate;
std::tie(SinkTo, SinkCandidate) = WorkList[I];
if (SinkCandidate->getParent() == SinkTo ||
SinkCandidate->mayHaveSideEffects() ||
@@ -146,12 +147,11 @@ static bool sinkScalarOperands(VPlan &Plan) {
return false;
if (UI->getParent() == SinkTo)
return true;
- NeedsDuplicating =
- UI->onlyFirstLaneUsed(SinkCandidate->getVPSingleValue());
+ NeedsDuplicating = UI->onlyFirstLaneUsed(SinkCandidate);
// We only know how to duplicate VPRecipeRecipes for now.
return NeedsDuplicating && isa<VPReplicateRecipe>(SinkCandidate);
};
- if (!all_of(SinkCandidate->getVPSingleValue()->users(), CanSinkWithUser))
+ if (!all_of(SinkCandidate->users(), CanSinkWithUser))
continue;
if (NeedsDuplicating) {
@@ -163,14 +163,14 @@ static bool sinkScalarOperands(VPlan &Plan) {
// TODO: add ".cloned" suffix to name of Clone's VPValue.
Clone->insertBefore(SinkCandidate);
- SinkCandidate->getVPSingleValue()->replaceUsesWithIf(
- Clone, [SinkTo](VPUser &U, unsigned) {
- return cast<VPRecipeBase>(&U)->getParent() != SinkTo;
- });
+ SinkCandidate->replaceUsesWithIf(Clone, [SinkTo](VPUser &U, unsigned) {
+ return cast<VPRecipeBase>(&U)->getParent() != SinkTo;
+ });
}
SinkCandidate->moveBefore(*SinkTo, SinkTo->getFirstNonPhi());
for (VPValue *Op : SinkCandidate->operands())
- if (auto *Def = Op->getDefiningRecipe())
+ if (auto *Def =
+ dyn_cast_or_null<VPSingleDefRecipe>(Op->getDefiningRecipe()))
WorkList.insert(std::make_pair(SinkTo, Def));
Changed = true;
}
@@ -412,16 +412,15 @@ void VPlanTransforms::removeRedundantInductionCasts(VPlan &Plan) {
auto &Casts = IV->getInductionDescriptor().getCastInsts();
VPValue *FindMyCast = IV;
for (Instruction *IRCast : reverse(Casts)) {
- VPRecipeBase *FoundUserCast = nullptr;
+ VPSingleDefRecipe *FoundUserCast = nullptr;
for (auto *U : FindMyCast->users()) {
- auto *UserCast = cast<VPRecipeBase>(U);
- if (UserCast->getNumDefinedValues() == 1 &&
- UserCast->getVPSingleValue()->getUnderlyingValue() == IRCast) {
+ auto *UserCast = dyn_cast<VPSingleDefRecipe>(U);
+ if (UserCast && UserCast->getUnderlyingValue() == IRCast) {
FoundUserCast = UserCast;
break;
}
}
- FindMyCast = FoundUserCast->getVPSingleValue();
+ FindMyCast = FoundUserCast;
}
FindMyCast->replaceAllUsesWith(IV);
}
@@ -1139,7 +1138,7 @@ void VPlanTransforms::addActiveLaneMask(
"Must have widened canonical IV when tail folding!");
auto *WideCanonicalIV =
cast<VPWidenCanonicalIVRecipe>(*FoundWidenCanonicalIVUser);
- VPRecipeBase *LaneMask;
+ VPSingleDefRecipe *LaneMask;
if (UseActiveLaneMaskForControlFlow) {
LaneMask = addVPLaneMaskPhiAndUpdateExitBranch(
Plan, DataAndControlFlowWithoutRuntimeCheck);
@@ -1164,7 +1163,7 @@ void VPlanTransforms::addActiveLaneMask(
assert(CompareToReplace->getOperand(0) == WideCanonicalIV &&
"WidenCanonicalIV must be the first operand of the compare");
- CompareToReplace->replaceAllUsesWith(LaneMask->getVPSingleValue());
+ CompareToReplace->replaceAllUsesWith(LaneMask);
CompareToReplace->eraseFromParent();
}
}
More information about the llvm-commits
mailing list