diff options
Diffstat (limited to 'llvm/lib/Transforms/Vectorize/VPlanValue.h')
| -rw-r--r-- | llvm/lib/Transforms/Vectorize/VPlanValue.h | 212 |
1 files changed, 186 insertions, 26 deletions
diff --git a/llvm/lib/Transforms/Vectorize/VPlanValue.h b/llvm/lib/Transforms/Vectorize/VPlanValue.h index f73505d0279a..ed572ca36627 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 -/// | |-- VPInstruction +/// VPValue VPUser VPDef +/// | | +/// VPInstruction /// These are documented in docs/VectorizationPlan.rst. /// //===----------------------------------------------------------------------===// @@ -21,7 +21,9 @@ #define LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/iterator_range.h" namespace llvm { @@ -29,8 +31,11 @@ namespace llvm { // Forward declarations. class raw_ostream; class Value; +class VPDef; class VPSlotTracker; class VPUser; +class VPRecipeBase; +class VPWidenMemoryInstructionRecipe; // This is the base class of the VPlan Def/Use graph, used for modeling the data // flow into, within and out of the VPlan. VPValues can stand for live-ins @@ -38,10 +43,14 @@ class VPUser; // and live-outs which the VPlan will need to fix accordingly. class VPValue { friend class VPBuilder; + friend class VPDef; + friend class VPInstruction; friend struct VPlanTransforms; friend class VPBasicBlock; friend class VPInterleavedAccessInfo; friend class VPSlotTracker; + friend class VPRecipeBase; + friend class VPWidenMemoryInstructionRecipe; const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast). @@ -51,8 +60,11 @@ protected: // Hold the underlying Value, if any, attached to this VPValue. Value *UnderlyingVal; - VPValue(const unsigned char SC, Value *UV = nullptr) - : SubclassID(SC), UnderlyingVal(UV) {} + /// Pointer to the VPDef that defines this VPValue. If it is nullptr, the + /// VPValue is not defined by any recipe modeled in VPlan. + VPDef *Def; + + VPValue(const unsigned char SC, Value *UV = nullptr, VPDef *Def = nullptr); // DESIGN PRINCIPLE: Access to the underlying IR must be strictly limited to // the front-end and back-end of VPlan so that the middle-end is as @@ -61,10 +73,6 @@ protected: // for multiple underlying IRs (Polly?) by providing a new VPlan front-end, // back-end and analysis information for the new IR. - /// Return the underlying Value attached to this VPValue. - Value *getUnderlyingValue() { return UnderlyingVal; } - const Value *getUnderlyingValue() const { return UnderlyingVal; } - // Set \p Val as the underlying Value of this VPValue. void setUnderlyingValue(Value *Val) { assert(!UnderlyingVal && "Underlying Value is already set."); @@ -72,16 +80,33 @@ protected: } public: + /// Return the underlying Value attached to this VPValue. + Value *getUnderlyingValue() { return UnderlyingVal; } + const Value *getUnderlyingValue() const { return UnderlyingVal; } + /// An enumeration for keeping track of the concrete subclass of VPValue that /// are actually instantiated. Values of this enumeration are kept in the /// SubclassID field of the VPValue objects. They are used for concrete /// type identification. - enum { VPValueSC, VPUserSC, VPInstructionSC }; + enum { + VPValueSC, + VPVInstructionSC, + VPVMemoryInstructionSC, + VPVReductionSC, + VPVReplicateSC, + VPVWidenSC, + VPVWidenCallSC, + VPVWidenGEPSC, + VPVWidenSelectSC, + }; - VPValue(Value *UV = nullptr) : VPValue(VPValueSC, UV) {} + VPValue(Value *UV = nullptr, VPDef *Def = nullptr) + : VPValue(VPValueSC, UV, Def) {} VPValue(const VPValue &) = delete; VPValue &operator=(const VPValue &) = delete; + virtual ~VPValue(); + /// \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. @@ -90,9 +115,28 @@ public: void printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const; void print(raw_ostream &OS, VPSlotTracker &Tracker) const; + /// Dump the value to stderr (for debugging). + void dump() const; + unsigned getNumUsers() const { return Users.size(); } void addUser(VPUser &User) { Users.push_back(&User); } + /// Remove a single \p User from the list of users. + void removeUser(VPUser &User) { + bool Found = false; + // The same user can be added multiple times, e.g. because the same VPValue + // is used twice by the same VPUser. Remove a single one. + erase_if(Users, [&User, &Found](VPUser *Other) { + if (Found) + return false; + if (Other == &User) { + Found = true; + return true; + } + return false; + }); + } + typedef SmallVectorImpl<VPUser *>::iterator user_iterator; typedef SmallVectorImpl<VPUser *>::const_iterator const_user_iterator; typedef iterator_range<user_iterator> user_range; @@ -120,6 +164,17 @@ public: } void replaceAllUsesWith(VPValue *New); + + VPDef *getDef() { return Def; } + + /// Returns the underlying IR value, if this VPValue is defined outside the + /// scope of VPlan. Returns nullptr if the VPValue is defined by a VPDef + /// inside a VPlan. + Value *getLiveInIRValue() { + assert(!getDef() && + "VPValue is not a live-in; it is defined by a VPDef inside a VPlan"); + return getUnderlyingValue(); + } }; typedef DenseMap<Value *, VPValue *> Value2VPValueTy; @@ -129,34 +184,32 @@ raw_ostream &operator<<(raw_ostream &OS, const VPValue &V); /// This class augments VPValue with operands which provide the inverse def-use /// edges from VPValue's users to their defs. -class VPUser : public VPValue { +class VPUser { SmallVector<VPValue *, 2> Operands; protected: - VPUser(const unsigned char SC) : VPValue(SC) {} - VPUser(const unsigned char SC, ArrayRef<VPValue *> Operands) : VPValue(SC) { + /// Print the operands to \p O. + void printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const; + +public: + VPUser() {} + VPUser(ArrayRef<VPValue *> Operands) { for (VPValue *Operand : Operands) addOperand(Operand); } -public: - VPUser() : VPValue(VPValue::VPUserSC) {} - VPUser(ArrayRef<VPValue *> Operands) : VPUser(VPValue::VPUserSC, Operands) {} VPUser(std::initializer_list<VPValue *> Operands) : VPUser(ArrayRef<VPValue *>(Operands)) {} - template <typename IterT> - VPUser(iterator_range<IterT> Operands) : VPValue(VPValue::VPUserSC) { + template <typename IterT> VPUser(iterator_range<IterT> Operands) { for (VPValue *Operand : Operands) addOperand(Operand); } VPUser(const VPUser &) = delete; VPUser &operator=(const VPUser &) = delete; - - /// Method to support type inquiry through isa, cast, and dyn_cast. - static inline bool classof(const VPValue *V) { - return V->getVPValueID() >= VPUserSC && - V->getVPValueID() <= VPInstructionSC; + virtual ~VPUser() { + for (VPValue *Op : operands()) + Op->removeUser(*this); } void addOperand(VPValue *Operand) { @@ -170,7 +223,11 @@ public: return Operands[N]; } - void setOperand(unsigned I, VPValue *New) { Operands[I] = New; } + void setOperand(unsigned I, VPValue *New) { + Operands[I]->removeUser(*this); + Operands[I] = New; + New->addUser(*this); + } typedef SmallVectorImpl<VPValue *>::iterator operand_iterator; typedef SmallVectorImpl<VPValue *>::const_iterator const_operand_iterator; @@ -185,7 +242,110 @@ public: const_operand_range operands() const { return const_operand_range(op_begin(), op_end()); } + + /// Method to support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const VPDef *Recipe); }; + +/// 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; + + /// Subclass identifier (for isa/dyn_cast). + const unsigned char SubclassID; + + /// The VPValues defined by this VPDef. + TinyPtrVector<VPValue *> DefinedValues; + + /// Add \p V as a defined value by this VPDef. + void addDefinedValue(VPValue *V) { + assert(V->getDef() == 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(VPValue *V) { + assert(V->getDef() == this && + "can only remove VPValue linked with this VPDef"); + assert(is_contained(DefinedValues, V) && + "VPValue to remove must be in DefinedValues"); + erase_value(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 { + VPBlendSC, + VPBranchOnMaskSC, + VPInstructionSC, + VPInterleaveSC, + VPPredInstPHISC, + VPReductionSC, + VPReplicateSC, + VPWidenCallSC, + VPWidenCanonicalIVSC, + VPWidenGEPSC, + VPWidenIntOrFpInductionSC, + VPWidenMemoryInstructionSC, + VPWidenPHISC, + VPWidenSC, + VPWidenSelectSC + }; + + VPDef(const unsigned char SC) : SubclassID(SC) {} + + virtual ~VPDef() { + for (VPValue *D : make_early_inc_range(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"); + D->Def = nullptr; + delete D; + } + } + + /// Returns the VPValue with index \p I defined by the VPDef. + VPValue *getVPValue(unsigned I = 0) { + assert(DefinedValues[I] && "defined value must be non-null"); + return DefinedValues[I]; + } + const VPValue *getVPValue(unsigned I = 0) const { + assert(DefinedValues[I] && "defined value must be non-null"); + return DefinedValues[I]; + } + + /// Returns an ArrayRef of the values defined by the VPDef. + ArrayRef<VPValue *> definedValues() { return DefinedValues; } + /// Returns an ArrayRef of the values defined by the VPDef. + ArrayRef<VPValue *> 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; } + + /// Dump the VPDef to stderr (for debugging). + void dump() const; + + /// Each concrete VPDef prints itself. + virtual void print(raw_ostream &O, const Twine &Indent, + VPSlotTracker &SlotTracker) const = 0; +}; + class VPlan; class VPBasicBlock; class VPRegionBlock; @@ -205,7 +365,7 @@ class VPSlotTracker { void assignSlots(const VPlan &Plan); public: - VPSlotTracker(const VPlan *Plan) { + VPSlotTracker(const VPlan *Plan = nullptr) { if (Plan) assignSlots(*Plan); } |
