aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Vectorize/VPlan.h
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Vectorize/VPlan.h')
-rw-r--r--llvm/lib/Transforms/Vectorize/VPlan.h247
1 files changed, 194 insertions, 53 deletions
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index f4a1883e35d5..824440f98a8b 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -69,6 +69,9 @@ class VPlanSlp;
/// vectors it is an expression determined at runtime.
Value *getRuntimeVF(IRBuilder<> &B, Type *Ty, ElementCount VF);
+/// Return a value for Step multiplied by VF.
+Value *createStepForVF(IRBuilder<> &B, Type *Ty, ElementCount VF, int64_t Step);
+
/// A range of powers-of-2 vectorization factors with fixed start and
/// adjustable end. The range includes start and excludes end, e.g.,:
/// [1, 9) = {1, 2, 4, 8}
@@ -198,8 +201,8 @@ struct VPTransformState {
VPTransformState(ElementCount VF, unsigned UF, LoopInfo *LI,
DominatorTree *DT, IRBuilder<> &Builder,
InnerLoopVectorizer *ILV, VPlan *Plan)
- : VF(VF), UF(UF), Instance(), LI(LI), DT(DT), Builder(Builder), ILV(ILV),
- Plan(Plan) {}
+ : VF(VF), UF(UF), LI(LI), DT(DT), Builder(Builder), ILV(ILV), Plan(Plan) {
+ }
/// The chosen Vectorization and Unroll Factors of the loop being vectorized.
ElementCount VF;
@@ -341,9 +344,6 @@ struct VPTransformState {
/// Hold the canonical scalar IV of the vector loop (start=0, step=VF*UF).
Value *CanonicalIV = nullptr;
- /// Hold the trip count of the scalar loop.
- Value *TripCount = nullptr;
-
/// Hold a pointer to InnerLoopVectorizer to reuse its IR generation methods.
InnerLoopVectorizer *ILV;
@@ -793,6 +793,9 @@ public:
SLPLoad,
SLPStore,
ActiveLaneMask,
+ CanonicalIVIncrement,
+ CanonicalIVIncrementNUW,
+ BranchOnCount,
};
private:
@@ -833,6 +836,16 @@ public:
return R->getVPDefID() == VPRecipeBase::VPInstructionSC;
}
+ /// Extra classof implementations to allow directly casting from VPUser ->
+ /// VPInstruction.
+ static inline bool classof(const VPUser *U) {
+ auto *R = dyn_cast<VPRecipeBase>(U);
+ return R && R->getVPDefID() == VPRecipeBase::VPInstructionSC;
+ }
+ static inline bool classof(const VPRecipeBase *R) {
+ return R->getVPDefID() == VPRecipeBase::VPInstructionSC;
+ }
+
unsigned getOpcode() const { return Opcode; }
/// Generate the instruction.
@@ -871,6 +884,7 @@ public:
case Instruction::Unreachable:
case Instruction::Fence:
case Instruction::AtomicRMW:
+ case VPInstruction::BranchOnCount:
return false;
default:
return true;
@@ -1045,6 +1059,7 @@ public:
/// Returns the start value of the induction.
VPValue *getStartValue() { return getOperand(0); }
+ const VPValue *getStartValue() const { return getOperand(0); }
/// Returns the first defined value as TruncInst, if it is one or nullptr
/// otherwise.
@@ -1057,66 +1072,65 @@ public:
/// Returns the induction descriptor for the recipe.
const InductionDescriptor &getInductionDescriptor() const { return IndDesc; }
-};
-/// A recipe for handling first order recurrences and pointer inductions. For
-/// first-order recurrences, the start value is the first operand of the recipe
-/// and the incoming value from the backedge is the second operand. It also
-/// serves as base class for VPReductionPHIRecipe. In the VPlan native path, all
-/// incoming VPValues & VPBasicBlock pairs are managed in the recipe directly.
-class VPWidenPHIRecipe : public VPRecipeBase, public VPValue {
- /// List of incoming blocks. Only used in the VPlan native path.
- SmallVector<VPBasicBlock *, 2> IncomingBlocks;
+ /// Returns true if the induction is canonical, i.e. starting at 0 and
+ /// incremented by UF * VF (= the original IV is incremented by 1).
+ bool isCanonical() const;
+
+ /// Returns the scalar type of the induction.
+ const Type *getScalarType() const {
+ const TruncInst *TruncI = getTruncInst();
+ return TruncI ? TruncI->getType() : IV->getType();
+ }
+};
+/// A pure virtual base class for all recipes modeling header phis, including
+/// phis for first order recurrences, pointer inductions and reductions. The
+/// start value is the first operand of the recipe and the incoming value from
+/// the backedge is the second operand.
+class VPHeaderPHIRecipe : public VPRecipeBase, public VPValue {
protected:
- VPWidenPHIRecipe(unsigned char VPVID, unsigned char VPDefID, PHINode *Phi,
- VPValue *Start = nullptr)
+ VPHeaderPHIRecipe(unsigned char VPVID, unsigned char VPDefID, PHINode *Phi,
+ VPValue *Start = nullptr)
: VPRecipeBase(VPDefID, {}), VPValue(VPVID, Phi, this) {
if (Start)
addOperand(Start);
}
public:
- /// Create a VPWidenPHIRecipe for \p Phi
- VPWidenPHIRecipe(PHINode *Phi)
- : VPWidenPHIRecipe(VPVWidenPHISC, VPWidenPHISC, Phi) {}
-
- /// Create a new VPWidenPHIRecipe for \p Phi with start value \p Start.
- VPWidenPHIRecipe(PHINode *Phi, VPValue &Start) : VPWidenPHIRecipe(Phi) {
- addOperand(&Start);
- }
-
- ~VPWidenPHIRecipe() override = default;
+ ~VPHeaderPHIRecipe() override = default;
/// Method to support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const VPRecipeBase *B) {
- return B->getVPDefID() == VPRecipeBase::VPWidenPHISC ||
+ return B->getVPDefID() == VPRecipeBase::VPCanonicalIVPHISC ||
B->getVPDefID() == VPRecipeBase::VPFirstOrderRecurrencePHISC ||
- B->getVPDefID() == VPRecipeBase::VPReductionPHISC;
+ B->getVPDefID() == VPRecipeBase::VPReductionPHISC ||
+ B->getVPDefID() == VPRecipeBase::VPWidenIntOrFpInductionSC ||
+ B->getVPDefID() == VPRecipeBase::VPWidenPHISC;
}
static inline bool classof(const VPValue *V) {
- return V->getVPValueID() == VPValue::VPVWidenPHISC ||
+ return V->getVPValueID() == VPValue::VPVCanonicalIVPHISC ||
V->getVPValueID() == VPValue::VPVFirstOrderRecurrencePHISC ||
- V->getVPValueID() == VPValue::VPVReductionPHISC;
+ V->getVPValueID() == VPValue::VPVReductionPHISC ||
+ V->getVPValueID() == VPValue::VPVWidenIntOrFpInductionSC ||
+ V->getVPValueID() == VPValue::VPVWidenPHISC;
}
- /// Generate the phi/select nodes.
- void execute(VPTransformState &State) override;
+ /// Generate the phi nodes.
+ void execute(VPTransformState &State) override = 0;
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
/// Print the recipe.
void print(raw_ostream &O, const Twine &Indent,
- VPSlotTracker &SlotTracker) const override;
+ VPSlotTracker &SlotTracker) const override = 0;
#endif
- /// Returns the start value of the phi, if it is a reduction or first-order
- /// recurrence.
+ /// Returns the start value of the phi, if one is set.
VPValue *getStartValue() {
return getNumOperands() == 0 ? nullptr : getOperand(0);
}
- /// Returns the incoming value from the loop backedge, if it is a reduction or
- /// first-order recurrence.
+ /// Returns the incoming value from the loop backedge.
VPValue *getBackedgeValue() {
return getOperand(1);
}
@@ -1126,6 +1140,44 @@ public:
VPRecipeBase *getBackedgeRecipe() {
return cast<VPRecipeBase>(getBackedgeValue()->getDef());
}
+};
+
+/// A recipe for handling header phis that are widened in the vector loop.
+/// In the VPlan native path, all incoming VPValues & VPBasicBlock pairs are
+/// managed in the recipe directly.
+class VPWidenPHIRecipe : public VPHeaderPHIRecipe {
+ /// List of incoming blocks. Only used in the VPlan native path.
+ SmallVector<VPBasicBlock *, 2> IncomingBlocks;
+
+public:
+ /// Create a new VPWidenPHIRecipe for \p Phi with start value \p Start.
+ VPWidenPHIRecipe(PHINode *Phi, VPValue *Start = nullptr)
+ : VPHeaderPHIRecipe(VPVWidenPHISC, VPWidenPHISC, Phi) {
+ if (Start)
+ addOperand(Start);
+ }
+
+ ~VPWidenPHIRecipe() override = default;
+
+ /// Method to support type inquiry through isa, cast, and dyn_cast.
+ static inline bool classof(const VPRecipeBase *B) {
+ return B->getVPDefID() == VPRecipeBase::VPWidenPHISC;
+ }
+ static inline bool classof(const VPHeaderPHIRecipe *R) {
+ return R->getVPDefID() == VPRecipeBase::VPWidenPHISC;
+ }
+ static inline bool classof(const VPValue *V) {
+ return V->getVPValueID() == VPValue::VPVWidenPHISC;
+ }
+
+ /// Generate the phi/select nodes.
+ void execute(VPTransformState &State) override;
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ /// Print the recipe.
+ void print(raw_ostream &O, const Twine &Indent,
+ VPSlotTracker &SlotTracker) const override;
+#endif
/// Adds a pair (\p IncomingV, \p IncomingBlock) to the phi.
void addIncoming(VPValue *IncomingV, VPBasicBlock *IncomingBlock) {
@@ -1133,27 +1185,27 @@ public:
IncomingBlocks.push_back(IncomingBlock);
}
- /// Returns the \p I th incoming VPValue.
- VPValue *getIncomingValue(unsigned I) { return getOperand(I); }
-
/// Returns the \p I th incoming VPBasicBlock.
VPBasicBlock *getIncomingBlock(unsigned I) { return IncomingBlocks[I]; }
+
+ /// Returns the \p I th incoming VPValue.
+ VPValue *getIncomingValue(unsigned I) { return getOperand(I); }
};
/// A recipe for handling first-order recurrence phis. The start value is the
/// first operand of the recipe and the incoming value from the backedge is the
/// second operand.
-struct VPFirstOrderRecurrencePHIRecipe : public VPWidenPHIRecipe {
+struct VPFirstOrderRecurrencePHIRecipe : public VPHeaderPHIRecipe {
VPFirstOrderRecurrencePHIRecipe(PHINode *Phi, VPValue &Start)
- : VPWidenPHIRecipe(VPVFirstOrderRecurrencePHISC,
- VPFirstOrderRecurrencePHISC, Phi, &Start) {}
+ : VPHeaderPHIRecipe(VPVFirstOrderRecurrencePHISC,
+ VPFirstOrderRecurrencePHISC, Phi, &Start) {}
/// Method to support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const VPRecipeBase *R) {
return R->getVPDefID() == VPRecipeBase::VPFirstOrderRecurrencePHISC;
}
- static inline bool classof(const VPWidenPHIRecipe *D) {
- return D->getVPDefID() == VPRecipeBase::VPFirstOrderRecurrencePHISC;
+ static inline bool classof(const VPHeaderPHIRecipe *R) {
+ return R->getVPDefID() == VPRecipeBase::VPFirstOrderRecurrencePHISC;
}
static inline bool classof(const VPValue *V) {
return V->getVPValueID() == VPValue::VPVFirstOrderRecurrencePHISC;
@@ -1171,7 +1223,7 @@ struct VPFirstOrderRecurrencePHIRecipe : public VPWidenPHIRecipe {
/// A recipe for handling reduction phis. The start value is the first operand
/// of the recipe and the incoming value from the backedge is the second
/// operand.
-class VPReductionPHIRecipe : public VPWidenPHIRecipe {
+class VPReductionPHIRecipe : public VPHeaderPHIRecipe {
/// Descriptor for the reduction.
const RecurrenceDescriptor &RdxDesc;
@@ -1187,7 +1239,7 @@ public:
VPReductionPHIRecipe(PHINode *Phi, const RecurrenceDescriptor &RdxDesc,
VPValue &Start, bool IsInLoop = false,
bool IsOrdered = false)
- : VPWidenPHIRecipe(VPVReductionPHISC, VPReductionPHISC, Phi, &Start),
+ : VPHeaderPHIRecipe(VPVReductionPHISC, VPReductionPHISC, Phi, &Start),
RdxDesc(RdxDesc), IsInLoop(IsInLoop), IsOrdered(IsOrdered) {
assert((!IsOrdered || IsInLoop) && "IsOrdered requires IsInLoop");
}
@@ -1198,12 +1250,12 @@ public:
static inline bool classof(const VPRecipeBase *R) {
return R->getVPDefID() == VPRecipeBase::VPReductionPHISC;
}
+ static inline bool classof(const VPHeaderPHIRecipe *R) {
+ return R->getVPDefID() == VPRecipeBase::VPReductionPHISC;
+ }
static inline bool classof(const VPValue *V) {
return V->getVPValueID() == VPValue::VPVReductionPHISC;
}
- static inline bool classof(const VPWidenPHIRecipe *R) {
- return R->getVPDefID() == VPRecipeBase::VPReductionPHISC;
- }
/// Generate the phi/select nodes.
void execute(VPTransformState &State) override;
@@ -1601,11 +1653,46 @@ public:
#endif
};
+/// Canonical scalar induction phi of the vector loop. Starting at the specified
+/// start value (either 0 or the resume value when vectorizing the epilogue
+/// loop). VPWidenCanonicalIVRecipe represents the vector version of the
+/// canonical induction variable.
+class VPCanonicalIVPHIRecipe : public VPHeaderPHIRecipe {
+ DebugLoc DL;
+
+public:
+ VPCanonicalIVPHIRecipe(VPValue *StartV, DebugLoc DL)
+ : VPHeaderPHIRecipe(VPValue::VPVCanonicalIVPHISC, VPCanonicalIVPHISC,
+ nullptr, StartV),
+ DL(DL) {}
+
+ ~VPCanonicalIVPHIRecipe() override = default;
+
+ /// Method to support type inquiry through isa, cast, and dyn_cast.
+ static inline bool classof(const VPDef *D) {
+ return D->getVPDefID() == VPCanonicalIVPHISC;
+ }
+
+ /// Generate the canonical scalar induction phi of the vector loop.
+ void execute(VPTransformState &State) override;
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ /// Print the recipe.
+ void print(raw_ostream &O, const Twine &Indent,
+ VPSlotTracker &SlotTracker) const override;
+#endif
+
+ /// Returns the scalar type of the induction.
+ const Type *getScalarType() const {
+ return getOperand(0)->getLiveInIRValue()->getType();
+ }
+};
+
/// A Recipe for widening the canonical induction variable of the vector loop.
class VPWidenCanonicalIVRecipe : public VPRecipeBase, public VPValue {
public:
- VPWidenCanonicalIVRecipe()
- : VPRecipeBase(VPWidenCanonicalIVSC, {}),
+ VPWidenCanonicalIVRecipe(VPCanonicalIVPHIRecipe *CanonicalIV)
+ : VPRecipeBase(VPWidenCanonicalIVSC, {CanonicalIV}),
VPValue(VPValue::VPVWidenCanonicalIVSC, nullptr, this) {}
~VPWidenCanonicalIVRecipe() override = default;
@@ -1615,6 +1702,16 @@ public:
return D->getVPDefID() == VPRecipeBase::VPWidenCanonicalIVSC;
}
+ /// Extra classof implementations to allow directly casting from VPUser ->
+ /// VPWidenCanonicalIVRecipe.
+ static inline bool classof(const VPUser *U) {
+ auto *R = dyn_cast<VPRecipeBase>(U);
+ return R && R->getVPDefID() == VPRecipeBase::VPWidenCanonicalIVSC;
+ }
+ static inline bool classof(const VPRecipeBase *R) {
+ return R->getVPDefID() == 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
/// step = <VF*UF, VF*UF, ..., VF*UF>.
@@ -1625,6 +1722,12 @@ public:
void print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const override;
#endif
+
+ /// Returns the scalar type of the induction.
+ const Type *getScalarType() const {
+ return cast<VPCanonicalIVPHIRecipe>(getOperand(0)->getDef())
+ ->getScalarType();
+ }
};
/// VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph. It
@@ -2112,10 +2215,17 @@ class VPlan {
// (operators '==' and '<').
SetVector<VPValue *> VPExternalDefs;
- /// Represents the backedge taken count of the original loop, for folding
+ /// Represents the trip count of the original loop, for folding
/// the tail.
+ VPValue *TripCount = nullptr;
+
+ /// Represents the backedge taken count of the original loop, for folding
+ /// the tail. It equals TripCount - 1.
VPValue *BackedgeTakenCount = nullptr;
+ /// Represents the vector trip count.
+ VPValue VectorTripCount;
+
/// Holds a mapping between Values and their corresponding VPValue inside
/// VPlan.
Value2VPValueTy Value2VPValue;
@@ -2147,12 +2257,18 @@ public:
}
for (VPValue *VPV : VPValuesToFree)
delete VPV;
+ if (TripCount)
+ delete TripCount;
if (BackedgeTakenCount)
delete BackedgeTakenCount;
for (VPValue *Def : VPExternalDefs)
delete Def;
}
+ /// Prepare the plan for execution, setting up the required live-in values.
+ void prepareToExecute(Value *TripCount, Value *VectorTripCount,
+ Value *CanonicalIVStartValue, VPTransformState &State);
+
/// Generate the IR code for this VPlan.
void execute(struct VPTransformState *State);
@@ -2165,6 +2281,13 @@ public:
return Entry;
}
+ /// The trip count of the original loop.
+ VPValue *getOrCreateTripCount() {
+ if (!TripCount)
+ TripCount = new VPValue();
+ return TripCount;
+ }
+
/// The backedge taken count of the original loop.
VPValue *getOrCreateBackedgeTakenCount() {
if (!BackedgeTakenCount)
@@ -2172,6 +2295,9 @@ public:
return BackedgeTakenCount;
}
+ /// The vector trip count.
+ VPValue &getVectorTripCount() { return VectorTripCount; }
+
/// Mark the plan to indicate that using Value2VPValue is not safe any
/// longer, because it may be stale.
void disableValue2VPValue() { Value2VPValueEnabled = false; }
@@ -2264,6 +2390,21 @@ public:
return !VPV->getDef() || (RepR && RepR->isUniform());
}
+ /// Returns the VPRegionBlock of the vector loop.
+ VPRegionBlock *getVectorLoopRegion() {
+ return cast<VPRegionBlock>(getEntry());
+ }
+
+ /// Returns the canonical induction recipe of the vector loop.
+ VPCanonicalIVPHIRecipe *getCanonicalIV() {
+ VPBasicBlock *EntryVPBB = getVectorLoopRegion()->getEntryBasicBlock();
+ if (EntryVPBB->empty()) {
+ // VPlan native path.
+ EntryVPBB = cast<VPBasicBlock>(EntryVPBB->getSingleSuccessor());
+ }
+ return cast<VPCanonicalIVPHIRecipe>(&*EntryVPBB->begin());
+ }
+
private:
/// Add to the given dominator tree the header block and every new basic block
/// that was created between it and the latch block, inclusive.