10b57cec5SDimitry Andric //===- VPlanValue.h - Represent Values in Vectorizer Plan -----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// This file contains the declarations of the entities induced by Vectorization 110b57cec5SDimitry Andric /// Plans, e.g. the instructions the VPlan intends to generate if executed. 120b57cec5SDimitry Andric /// VPlan models the following entities: 13e8d8bef9SDimitry Andric /// VPValue VPUser VPDef 14e8d8bef9SDimitry Andric /// | | 15e8d8bef9SDimitry Andric /// VPInstruction 160b57cec5SDimitry Andric /// These are documented in docs/VectorizationPlan.rst. 170b57cec5SDimitry Andric /// 180b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #ifndef LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H 210b57cec5SDimitry Andric #define LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 24e8d8bef9SDimitry Andric #include "llvm/ADT/STLExtras.h" 250b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 26*0fca6ea1SDimitry Andric #include "llvm/ADT/StringMap.h" 27e8d8bef9SDimitry Andric #include "llvm/ADT/TinyPtrVector.h" 285ffd83dbSDimitry Andric #include "llvm/ADT/iterator_range.h" 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric namespace llvm { 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric // Forward declarations. 335ffd83dbSDimitry Andric class raw_ostream; 345ffd83dbSDimitry Andric class Value; 35e8d8bef9SDimitry Andric class VPDef; 365ffd83dbSDimitry Andric class VPSlotTracker; 370b57cec5SDimitry Andric class VPUser; 38e8d8bef9SDimitry Andric class VPRecipeBase; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric // This is the base class of the VPlan Def/Use graph, used for modeling the data 410b57cec5SDimitry Andric // flow into, within and out of the VPlan. VPValues can stand for live-ins 420b57cec5SDimitry Andric // coming from the input IR, instructions which VPlan will generate if executed 430b57cec5SDimitry Andric // and live-outs which the VPlan will need to fix accordingly. 440b57cec5SDimitry Andric class VPValue { 450b57cec5SDimitry Andric friend class VPBuilder; 46e8d8bef9SDimitry Andric friend class VPDef; 47e8d8bef9SDimitry Andric friend class VPInstruction; 485ffd83dbSDimitry Andric friend struct VPlanTransforms; 490b57cec5SDimitry Andric friend class VPBasicBlock; 500b57cec5SDimitry Andric friend class VPInterleavedAccessInfo; 515ffd83dbSDimitry Andric friend class VPSlotTracker; 52e8d8bef9SDimitry Andric friend class VPRecipeBase; 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast). 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric SmallVector<VPUser *, 1> Users; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric protected: 590b57cec5SDimitry Andric // Hold the underlying Value, if any, attached to this VPValue. 600b57cec5SDimitry Andric Value *UnderlyingVal; 610b57cec5SDimitry Andric 62e8d8bef9SDimitry Andric /// Pointer to the VPDef that defines this VPValue. If it is nullptr, the 63e8d8bef9SDimitry Andric /// VPValue is not defined by any recipe modeled in VPlan. 64e8d8bef9SDimitry Andric VPDef *Def; 65e8d8bef9SDimitry Andric 66e8d8bef9SDimitry Andric VPValue(const unsigned char SC, Value *UV = nullptr, VPDef *Def = nullptr); 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric // DESIGN PRINCIPLE: Access to the underlying IR must be strictly limited to 690b57cec5SDimitry Andric // the front-end and back-end of VPlan so that the middle-end is as 700b57cec5SDimitry Andric // independent as possible of the underlying IR. We grant access to the 710b57cec5SDimitry Andric // underlying IR using friendship. In that way, we should be able to use VPlan 720b57cec5SDimitry Andric // for multiple underlying IRs (Polly?) by providing a new VPlan front-end, 730b57cec5SDimitry Andric // back-end and analysis information for the new IR. 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric public: 76e8d8bef9SDimitry Andric /// Return the underlying Value attached to this VPValue. getUnderlyingValue()77*0fca6ea1SDimitry Andric Value *getUnderlyingValue() const { return UnderlyingVal; } 78e8d8bef9SDimitry Andric 790b57cec5SDimitry Andric /// An enumeration for keeping track of the concrete subclass of VPValue that 80bdd1243dSDimitry Andric /// are actually instantiated. 81e8d8bef9SDimitry Andric enum { 82bdd1243dSDimitry Andric VPValueSC, /// A generic VPValue, like live-in values or defined by a recipe 83bdd1243dSDimitry Andric /// that defines multiple values. 84bdd1243dSDimitry Andric VPVRecipeSC /// A VPValue sub-class that is a VPRecipeBase. 85e8d8bef9SDimitry Andric }; 860b57cec5SDimitry Andric 87bdd1243dSDimitry Andric /// Create a live-in VPValue. VPValue(VPValueSC,UV,nullptr)88bdd1243dSDimitry Andric VPValue(Value *UV = nullptr) : VPValue(VPValueSC, UV, nullptr) {} 89bdd1243dSDimitry Andric /// Create a VPValue for a \p Def which is a subclass of VPValue. VPValue(VPVRecipeSC,UV,Def)90bdd1243dSDimitry Andric VPValue(VPDef *Def, Value *UV = nullptr) : VPValue(VPVRecipeSC, UV, Def) {} 91bdd1243dSDimitry Andric /// Create a VPValue for a \p Def which defines multiple values. VPValue(Value * UV,VPDef * Def)92bdd1243dSDimitry Andric VPValue(Value *UV, VPDef *Def) : VPValue(VPValueSC, UV, Def) {} 930b57cec5SDimitry Andric VPValue(const VPValue &) = delete; 940b57cec5SDimitry Andric VPValue &operator=(const VPValue &) = delete; 950b57cec5SDimitry Andric 96e8d8bef9SDimitry Andric virtual ~VPValue(); 97e8d8bef9SDimitry Andric 980b57cec5SDimitry Andric /// \return an ID for the concrete type of this object. 990b57cec5SDimitry Andric /// This is used to implement the classof checks. This should not be used 1000b57cec5SDimitry Andric /// for any other purpose, as the values may change as LLVM evolves. getVPValueID()1010b57cec5SDimitry Andric unsigned getVPValueID() const { return SubclassID; } 1020b57cec5SDimitry Andric 103fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1045ffd83dbSDimitry Andric void printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const; 1055ffd83dbSDimitry Andric void print(raw_ostream &OS, VPSlotTracker &Tracker) const; 1060b57cec5SDimitry Andric 107e8d8bef9SDimitry Andric /// Dump the value to stderr (for debugging). 108e8d8bef9SDimitry Andric void dump() const; 109fe6060f1SDimitry Andric #endif 110e8d8bef9SDimitry Andric getNumUsers()1110b57cec5SDimitry Andric unsigned getNumUsers() const { return Users.size(); } addUser(VPUser & User)1120b57cec5SDimitry Andric void addUser(VPUser &User) { Users.push_back(&User); } 1130b57cec5SDimitry Andric 114e8d8bef9SDimitry Andric /// Remove a single \p User from the list of users. removeUser(VPUser & User)115e8d8bef9SDimitry Andric void removeUser(VPUser &User) { 116e8d8bef9SDimitry Andric // The same user can be added multiple times, e.g. because the same VPValue 117e8d8bef9SDimitry Andric // is used twice by the same VPUser. Remove a single one. 1185f757f3fSDimitry Andric auto *I = find(Users, &User); 1195f757f3fSDimitry Andric if (I != Users.end()) 1205f757f3fSDimitry Andric Users.erase(I); 121e8d8bef9SDimitry Andric } 122e8d8bef9SDimitry Andric 1230b57cec5SDimitry Andric typedef SmallVectorImpl<VPUser *>::iterator user_iterator; 1240b57cec5SDimitry Andric typedef SmallVectorImpl<VPUser *>::const_iterator const_user_iterator; 1250b57cec5SDimitry Andric typedef iterator_range<user_iterator> user_range; 1260b57cec5SDimitry Andric typedef iterator_range<const_user_iterator> const_user_range; 1270b57cec5SDimitry Andric user_begin()1280b57cec5SDimitry Andric user_iterator user_begin() { return Users.begin(); } user_begin()1290b57cec5SDimitry Andric const_user_iterator user_begin() const { return Users.begin(); } user_end()1300b57cec5SDimitry Andric user_iterator user_end() { return Users.end(); } user_end()1310b57cec5SDimitry Andric const_user_iterator user_end() const { return Users.end(); } users()1320b57cec5SDimitry Andric user_range users() { return user_range(user_begin(), user_end()); } users()1330b57cec5SDimitry Andric const_user_range users() const { 1340b57cec5SDimitry Andric return const_user_range(user_begin(), user_end()); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric /// Returns true if the value has more than one unique user. hasMoreThanOneUniqueUser()1380b57cec5SDimitry Andric bool hasMoreThanOneUniqueUser() { 1390b57cec5SDimitry Andric if (getNumUsers() == 0) 1400b57cec5SDimitry Andric return false; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric // Check if all users match the first user. 1430b57cec5SDimitry Andric auto Current = std::next(user_begin()); 1440b57cec5SDimitry Andric while (Current != user_end() && *user_begin() == *Current) 1450b57cec5SDimitry Andric Current++; 1460b57cec5SDimitry Andric return Current != user_end(); 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric void replaceAllUsesWith(VPValue *New); 150e8d8bef9SDimitry Andric 1515f757f3fSDimitry Andric /// Go through the uses list for this VPValue and make each use point to \p 1525f757f3fSDimitry Andric /// New if the callback ShouldReplace returns true for the given use specified 1535f757f3fSDimitry Andric /// by a pair of (VPUser, the use index). 1545f757f3fSDimitry Andric void replaceUsesWithIf( 1555f757f3fSDimitry Andric VPValue *New, 1565f757f3fSDimitry Andric llvm::function_ref<bool(VPUser &U, unsigned Idx)> ShouldReplace); 1575f757f3fSDimitry Andric 158bdd1243dSDimitry Andric /// Returns the recipe defining this VPValue or nullptr if it is not defined 159bdd1243dSDimitry Andric /// by a recipe, i.e. is a live-in. 160bdd1243dSDimitry Andric VPRecipeBase *getDefiningRecipe(); 161bdd1243dSDimitry Andric const VPRecipeBase *getDefiningRecipe() const; 162bdd1243dSDimitry Andric 163bdd1243dSDimitry Andric /// Returns true if this VPValue is defined by a recipe. hasDefiningRecipe()164bdd1243dSDimitry Andric bool hasDefiningRecipe() const { return getDefiningRecipe(); } 165e8d8bef9SDimitry Andric 16606c3fb27SDimitry Andric /// Returns true if this VPValue is a live-in, i.e. defined outside the VPlan. isLiveIn()16706c3fb27SDimitry Andric bool isLiveIn() const { return !hasDefiningRecipe(); } 16806c3fb27SDimitry Andric 169e8d8bef9SDimitry Andric /// Returns the underlying IR value, if this VPValue is defined outside the 170e8d8bef9SDimitry Andric /// scope of VPlan. Returns nullptr if the VPValue is defined by a VPDef 171e8d8bef9SDimitry Andric /// inside a VPlan. getLiveInIRValue()172e8d8bef9SDimitry Andric Value *getLiveInIRValue() { 17306c3fb27SDimitry Andric assert(isLiveIn() && 174e8d8bef9SDimitry Andric "VPValue is not a live-in; it is defined by a VPDef inside a VPlan"); 175e8d8bef9SDimitry Andric return getUnderlyingValue(); 176e8d8bef9SDimitry Andric } getLiveInIRValue()17704eeddc0SDimitry Andric const Value *getLiveInIRValue() const { 17806c3fb27SDimitry Andric assert(isLiveIn() && 17904eeddc0SDimitry Andric "VPValue is not a live-in; it is defined by a VPDef inside a VPlan"); 18004eeddc0SDimitry Andric return getUnderlyingValue(); 18104eeddc0SDimitry Andric } 182bdd1243dSDimitry Andric 183bdd1243dSDimitry Andric /// Returns true if the VPValue is defined outside any vector regions, i.e. it 184bdd1243dSDimitry Andric /// is a live-in value. 185bdd1243dSDimitry Andric /// TODO: Also handle recipes defined in pre-header blocks. isDefinedOutsideVectorRegions()186bdd1243dSDimitry Andric bool isDefinedOutsideVectorRegions() const { return !hasDefiningRecipe(); } 187*0fca6ea1SDimitry Andric 188*0fca6ea1SDimitry Andric // Set \p Val as the underlying Value of this VPValue. setUnderlyingValue(Value * Val)189*0fca6ea1SDimitry Andric void setUnderlyingValue(Value *Val) { 190*0fca6ea1SDimitry Andric assert(!UnderlyingVal && "Underlying Value is already set."); 191*0fca6ea1SDimitry Andric UnderlyingVal = Val; 192*0fca6ea1SDimitry Andric } 1930b57cec5SDimitry Andric }; 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric typedef DenseMap<Value *, VPValue *> Value2VPValueTy; 1960b57cec5SDimitry Andric typedef DenseMap<VPValue *, Value *> VPValue2ValueTy; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const VPValue &V); 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric /// This class augments VPValue with operands which provide the inverse def-use 2010b57cec5SDimitry Andric /// edges from VPValue's users to their defs. 202e8d8bef9SDimitry Andric class VPUser { 203fe6060f1SDimitry Andric public: 204fe6060f1SDimitry Andric /// Subclass identifier (for isa/dyn_cast). 205fe6060f1SDimitry Andric enum class VPUserID { 206fe6060f1SDimitry Andric Recipe, 20781ad6265SDimitry Andric LiveOut, 208fe6060f1SDimitry Andric }; 209fe6060f1SDimitry Andric 210fe6060f1SDimitry Andric private: 2110b57cec5SDimitry Andric SmallVector<VPValue *, 2> Operands; 2120b57cec5SDimitry Andric 213fe6060f1SDimitry Andric VPUserID ID; 214fe6060f1SDimitry Andric 2150b57cec5SDimitry Andric protected: 216fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 217e8d8bef9SDimitry Andric /// Print the operands to \p O. 218e8d8bef9SDimitry Andric void printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const; 219fe6060f1SDimitry Andric #endif 220fe6060f1SDimitry Andric VPUser(ArrayRef<VPValue * > Operands,VPUserID ID)221fe6060f1SDimitry Andric VPUser(ArrayRef<VPValue *> Operands, VPUserID ID) : ID(ID) { 222fe6060f1SDimitry Andric for (VPValue *Operand : Operands) 223fe6060f1SDimitry Andric addOperand(Operand); 224fe6060f1SDimitry Andric } 225fe6060f1SDimitry Andric VPUser(std::initializer_list<VPValue * > Operands,VPUserID ID)226fe6060f1SDimitry Andric VPUser(std::initializer_list<VPValue *> Operands, VPUserID ID) 227fe6060f1SDimitry Andric : VPUser(ArrayRef<VPValue *>(Operands), ID) {} 228fe6060f1SDimitry Andric 229fe6060f1SDimitry Andric template <typename IterT> VPUser(iterator_range<IterT> Operands,VPUserID ID)230fe6060f1SDimitry Andric VPUser(iterator_range<IterT> Operands, VPUserID ID) : ID(ID) { 231fe6060f1SDimitry Andric for (VPValue *Operand : Operands) 232fe6060f1SDimitry Andric addOperand(Operand); 233fe6060f1SDimitry Andric } 234e8d8bef9SDimitry Andric 235e8d8bef9SDimitry Andric public: 236fe6060f1SDimitry Andric VPUser() = delete; 2370b57cec5SDimitry Andric VPUser(const VPUser &) = delete; 2380b57cec5SDimitry Andric VPUser &operator=(const VPUser &) = delete; ~VPUser()239e8d8bef9SDimitry Andric virtual ~VPUser() { 240e8d8bef9SDimitry Andric for (VPValue *Op : operands()) 241e8d8bef9SDimitry Andric Op->removeUser(*this); 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric getVPUserID()244fe6060f1SDimitry Andric VPUserID getVPUserID() const { return ID; } 245fe6060f1SDimitry Andric addOperand(VPValue * Operand)2460b57cec5SDimitry Andric void addOperand(VPValue *Operand) { 2470b57cec5SDimitry Andric Operands.push_back(Operand); 2480b57cec5SDimitry Andric Operand->addUser(*this); 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric getNumOperands()2510b57cec5SDimitry Andric unsigned getNumOperands() const { return Operands.size(); } getOperand(unsigned N)2520b57cec5SDimitry Andric inline VPValue *getOperand(unsigned N) const { 2530b57cec5SDimitry Andric assert(N < Operands.size() && "Operand index out of bounds"); 2540b57cec5SDimitry Andric return Operands[N]; 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric setOperand(unsigned I,VPValue * New)257e8d8bef9SDimitry Andric void setOperand(unsigned I, VPValue *New) { 258e8d8bef9SDimitry Andric Operands[I]->removeUser(*this); 259e8d8bef9SDimitry Andric Operands[I] = New; 260e8d8bef9SDimitry Andric New->addUser(*this); 261e8d8bef9SDimitry Andric } 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric typedef SmallVectorImpl<VPValue *>::iterator operand_iterator; 2640b57cec5SDimitry Andric typedef SmallVectorImpl<VPValue *>::const_iterator const_operand_iterator; 2650b57cec5SDimitry Andric typedef iterator_range<operand_iterator> operand_range; 2660b57cec5SDimitry Andric typedef iterator_range<const_operand_iterator> const_operand_range; 2670b57cec5SDimitry Andric op_begin()2680b57cec5SDimitry Andric operand_iterator op_begin() { return Operands.begin(); } op_begin()2690b57cec5SDimitry Andric const_operand_iterator op_begin() const { return Operands.begin(); } op_end()2700b57cec5SDimitry Andric operand_iterator op_end() { return Operands.end(); } op_end()2710b57cec5SDimitry Andric const_operand_iterator op_end() const { return Operands.end(); } operands()2720b57cec5SDimitry Andric operand_range operands() { return operand_range(op_begin(), op_end()); } operands()2730b57cec5SDimitry Andric const_operand_range operands() const { 2740b57cec5SDimitry Andric return const_operand_range(op_begin(), op_end()); 2750b57cec5SDimitry Andric } 276e8d8bef9SDimitry Andric 27781ad6265SDimitry Andric /// Returns true if the VPUser uses scalars of operand \p Op. Conservatively 27881ad6265SDimitry Andric /// returns if only first (scalar) lane is used, as default. usesScalars(const VPValue * Op)27981ad6265SDimitry Andric virtual bool usesScalars(const VPValue *Op) const { 28081ad6265SDimitry Andric assert(is_contained(operands(), Op) && 28181ad6265SDimitry Andric "Op must be an operand of the recipe"); 28281ad6265SDimitry Andric return onlyFirstLaneUsed(Op); 28381ad6265SDimitry Andric } 28481ad6265SDimitry Andric 28581ad6265SDimitry Andric /// Returns true if the VPUser only uses the first lane of operand \p Op. 28681ad6265SDimitry Andric /// Conservatively returns false. onlyFirstLaneUsed(const VPValue * Op)28781ad6265SDimitry Andric virtual bool onlyFirstLaneUsed(const VPValue *Op) const { 28881ad6265SDimitry Andric assert(is_contained(operands(), Op) && 28981ad6265SDimitry Andric "Op must be an operand of the recipe"); 29081ad6265SDimitry Andric return false; 29181ad6265SDimitry Andric } 2925f757f3fSDimitry Andric 2935f757f3fSDimitry Andric /// Returns true if the VPUser only uses the first part of operand \p Op. 2945f757f3fSDimitry Andric /// Conservatively returns false. onlyFirstPartUsed(const VPValue * Op)2955f757f3fSDimitry Andric virtual bool onlyFirstPartUsed(const VPValue *Op) const { 2965f757f3fSDimitry Andric assert(is_contained(operands(), Op) && 2975f757f3fSDimitry Andric "Op must be an operand of the recipe"); 2985f757f3fSDimitry Andric return false; 2995f757f3fSDimitry Andric } 3000b57cec5SDimitry Andric }; 301e8d8bef9SDimitry Andric 302e8d8bef9SDimitry Andric /// This class augments a recipe with a set of VPValues defined by the recipe. 303e8d8bef9SDimitry Andric /// It allows recipes to define zero, one or multiple VPValues. A VPDef owns 304e8d8bef9SDimitry Andric /// the VPValues it defines and is responsible for deleting its defined values. 305e8d8bef9SDimitry Andric /// Single-value VPDefs that also inherit from VPValue must make sure to inherit 306e8d8bef9SDimitry Andric /// from VPDef before VPValue. 307e8d8bef9SDimitry Andric class VPDef { 308e8d8bef9SDimitry Andric friend class VPValue; 309e8d8bef9SDimitry Andric 310e8d8bef9SDimitry Andric /// Subclass identifier (for isa/dyn_cast). 311e8d8bef9SDimitry Andric const unsigned char SubclassID; 312e8d8bef9SDimitry Andric 313e8d8bef9SDimitry Andric /// The VPValues defined by this VPDef. 314e8d8bef9SDimitry Andric TinyPtrVector<VPValue *> DefinedValues; 315e8d8bef9SDimitry Andric 316e8d8bef9SDimitry Andric /// Add \p V as a defined value by this VPDef. addDefinedValue(VPValue * V)317e8d8bef9SDimitry Andric void addDefinedValue(VPValue *V) { 318bdd1243dSDimitry Andric assert(V->Def == this && 319e8d8bef9SDimitry Andric "can only add VPValue already linked with this VPDef"); 320e8d8bef9SDimitry Andric DefinedValues.push_back(V); 321e8d8bef9SDimitry Andric } 322e8d8bef9SDimitry Andric 323e8d8bef9SDimitry Andric /// Remove \p V from the values defined by this VPDef. \p V must be a defined 324e8d8bef9SDimitry Andric /// value of this VPDef. removeDefinedValue(VPValue * V)325e8d8bef9SDimitry Andric void removeDefinedValue(VPValue *V) { 326bdd1243dSDimitry Andric assert(V->Def == this && "can only remove VPValue linked with this VPDef"); 327e8d8bef9SDimitry Andric assert(is_contained(DefinedValues, V) && 328e8d8bef9SDimitry Andric "VPValue to remove must be in DefinedValues"); 3295f757f3fSDimitry Andric llvm::erase(DefinedValues, V); 330e8d8bef9SDimitry Andric V->Def = nullptr; 331e8d8bef9SDimitry Andric } 332e8d8bef9SDimitry Andric 333e8d8bef9SDimitry Andric public: 334e8d8bef9SDimitry Andric /// An enumeration for keeping track of the concrete subclass of VPRecipeBase 335e8d8bef9SDimitry Andric /// that is actually instantiated. Values of this enumeration are kept in the 336e8d8bef9SDimitry Andric /// SubclassID field of the VPRecipeBase objects. They are used for concrete 337e8d8bef9SDimitry Andric /// type identification. 338e8d8bef9SDimitry Andric using VPRecipeTy = enum { 339e8d8bef9SDimitry Andric VPBranchOnMaskSC, 340bdd1243dSDimitry Andric VPDerivedIVSC, 34181ad6265SDimitry Andric VPExpandSCEVSC, 342e8d8bef9SDimitry Andric VPInstructionSC, 343e8d8bef9SDimitry Andric VPInterleaveSC, 344*0fca6ea1SDimitry Andric VPReductionEVLSC, 345e8d8bef9SDimitry Andric VPReductionSC, 346e8d8bef9SDimitry Andric VPReplicateSC, 347*0fca6ea1SDimitry Andric VPScalarCastSC, 34881ad6265SDimitry Andric VPScalarIVStepsSC, 349647cbc5dSDimitry Andric VPVectorPointerSC, 350e8d8bef9SDimitry Andric VPWidenCallSC, 35104eeddc0SDimitry Andric VPWidenCanonicalIVSC, 35206c3fb27SDimitry Andric VPWidenCastSC, 353e8d8bef9SDimitry Andric VPWidenGEPSC, 354*0fca6ea1SDimitry Andric VPWidenLoadEVLSC, 355*0fca6ea1SDimitry Andric VPWidenLoadSC, 356*0fca6ea1SDimitry Andric VPWidenStoreEVLSC, 357*0fca6ea1SDimitry Andric VPWidenStoreSC, 358e8d8bef9SDimitry Andric VPWidenSC, 359fe6060f1SDimitry Andric VPWidenSelectSC, 360fe6060f1SDimitry Andric VPBlendSC, 361*0fca6ea1SDimitry Andric // START: Phi-like recipes. Need to be kept together. 362*0fca6ea1SDimitry Andric VPWidenPHISC, 363bdd1243dSDimitry Andric VPPredInstPHISC, 36406c3fb27SDimitry Andric // START: SubclassID for recipes that inherit VPHeaderPHIRecipe. 36506c3fb27SDimitry Andric // VPHeaderPHIRecipe need to be kept together. 36604eeddc0SDimitry Andric VPCanonicalIVPHISC, 367753f127fSDimitry Andric VPActiveLaneMaskPHISC, 368*0fca6ea1SDimitry Andric VPEVLBasedIVPHISC, 369fe6060f1SDimitry Andric VPFirstOrderRecurrencePHISC, 370fe6060f1SDimitry Andric VPWidenIntOrFpInductionSC, 37181ad6265SDimitry Andric VPWidenPointerInductionSC, 372fe6060f1SDimitry Andric VPReductionPHISC, 37306c3fb27SDimitry Andric // END: SubclassID for recipes that inherit VPHeaderPHIRecipe 37406c3fb27SDimitry Andric // END: Phi-like recipes 375*0fca6ea1SDimitry Andric VPFirstPHISC = VPWidenPHISC, 376bdd1243dSDimitry Andric VPFirstHeaderPHISC = VPCanonicalIVPHISC, 37706c3fb27SDimitry Andric VPLastHeaderPHISC = VPReductionPHISC, 378fe6060f1SDimitry Andric VPLastPHISC = VPReductionPHISC, 379e8d8bef9SDimitry Andric }; 380e8d8bef9SDimitry Andric VPDef(const unsigned char SC)381e8d8bef9SDimitry Andric VPDef(const unsigned char SC) : SubclassID(SC) {} 382e8d8bef9SDimitry Andric ~VPDef()383e8d8bef9SDimitry Andric virtual ~VPDef() { 384e8d8bef9SDimitry Andric for (VPValue *D : make_early_inc_range(DefinedValues)) { 385e8d8bef9SDimitry Andric assert(D->Def == this && 386e8d8bef9SDimitry Andric "all defined VPValues should point to the containing VPDef"); 387e8d8bef9SDimitry Andric assert(D->getNumUsers() == 0 && 388e8d8bef9SDimitry Andric "all defined VPValues should have no more users"); 389e8d8bef9SDimitry Andric D->Def = nullptr; 390e8d8bef9SDimitry Andric delete D; 391e8d8bef9SDimitry Andric } 392e8d8bef9SDimitry Andric } 393e8d8bef9SDimitry Andric 394fe6060f1SDimitry Andric /// Returns the only VPValue defined by the VPDef. Can only be called for 395fe6060f1SDimitry Andric /// VPDefs with a single defined value. getVPSingleValue()396fe6060f1SDimitry Andric VPValue *getVPSingleValue() { 397fe6060f1SDimitry Andric assert(DefinedValues.size() == 1 && "must have exactly one defined value"); 398fe6060f1SDimitry Andric assert(DefinedValues[0] && "defined value must be non-null"); 399fe6060f1SDimitry Andric return DefinedValues[0]; 400fe6060f1SDimitry Andric } getVPSingleValue()401fe6060f1SDimitry Andric const VPValue *getVPSingleValue() const { 402fe6060f1SDimitry Andric assert(DefinedValues.size() == 1 && "must have exactly one defined value"); 403fe6060f1SDimitry Andric assert(DefinedValues[0] && "defined value must be non-null"); 404fe6060f1SDimitry Andric return DefinedValues[0]; 405fe6060f1SDimitry Andric } 406fe6060f1SDimitry Andric 407e8d8bef9SDimitry Andric /// Returns the VPValue with index \p I defined by the VPDef. getVPValue(unsigned I)408fe6060f1SDimitry Andric VPValue *getVPValue(unsigned I) { 409e8d8bef9SDimitry Andric assert(DefinedValues[I] && "defined value must be non-null"); 410e8d8bef9SDimitry Andric return DefinedValues[I]; 411e8d8bef9SDimitry Andric } getVPValue(unsigned I)412fe6060f1SDimitry Andric const VPValue *getVPValue(unsigned I) const { 413e8d8bef9SDimitry Andric assert(DefinedValues[I] && "defined value must be non-null"); 414e8d8bef9SDimitry Andric return DefinedValues[I]; 415e8d8bef9SDimitry Andric } 416e8d8bef9SDimitry Andric 417e8d8bef9SDimitry Andric /// Returns an ArrayRef of the values defined by the VPDef. definedValues()418e8d8bef9SDimitry Andric ArrayRef<VPValue *> definedValues() { return DefinedValues; } 419e8d8bef9SDimitry Andric /// Returns an ArrayRef of the values defined by the VPDef. definedValues()420e8d8bef9SDimitry Andric ArrayRef<VPValue *> definedValues() const { return DefinedValues; } 421e8d8bef9SDimitry Andric 422e8d8bef9SDimitry Andric /// Returns the number of values defined by the VPDef. getNumDefinedValues()423e8d8bef9SDimitry Andric unsigned getNumDefinedValues() const { return DefinedValues.size(); } 424e8d8bef9SDimitry Andric 425e8d8bef9SDimitry Andric /// \return an ID for the concrete type of this object. 426e8d8bef9SDimitry Andric /// This is used to implement the classof checks. This should not be used 427e8d8bef9SDimitry Andric /// for any other purpose, as the values may change as LLVM evolves. getVPDefID()428e8d8bef9SDimitry Andric unsigned getVPDefID() const { return SubclassID; } 429e8d8bef9SDimitry Andric 430fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 431e8d8bef9SDimitry Andric /// Dump the VPDef to stderr (for debugging). 432e8d8bef9SDimitry Andric void dump() const; 433e8d8bef9SDimitry Andric 434e8d8bef9SDimitry Andric /// Each concrete VPDef prints itself. 435e8d8bef9SDimitry Andric virtual void print(raw_ostream &O, const Twine &Indent, 436e8d8bef9SDimitry Andric VPSlotTracker &SlotTracker) const = 0; 437fe6060f1SDimitry Andric #endif 438e8d8bef9SDimitry Andric }; 439e8d8bef9SDimitry Andric 4405ffd83dbSDimitry Andric class VPlan; 4415ffd83dbSDimitry Andric class VPBasicBlock; 4425ffd83dbSDimitry Andric 443*0fca6ea1SDimitry Andric /// This class can be used to assign names to VPValues. For VPValues without 444*0fca6ea1SDimitry Andric /// underlying value, assign consecutive numbers and use those as names (wrapped 445*0fca6ea1SDimitry Andric /// in vp<>). Otherwise, use the name from the underlying value (wrapped in 446*0fca6ea1SDimitry Andric /// ir<>), appending a .V version number if there are multiple uses of the same 447*0fca6ea1SDimitry Andric /// name. Allows querying names for VPValues for printing, similar to the 4485ffd83dbSDimitry Andric /// ModuleSlotTracker for IR values. 4495ffd83dbSDimitry Andric class VPSlotTracker { 450*0fca6ea1SDimitry Andric /// Keep track of versioned names assigned to VPValues with underlying IR 451*0fca6ea1SDimitry Andric /// values. 452*0fca6ea1SDimitry Andric DenseMap<const VPValue *, std::string> VPValue2Name; 453*0fca6ea1SDimitry Andric /// Keep track of the next number to use to version the base name. 454*0fca6ea1SDimitry Andric StringMap<unsigned> BaseName2Version; 455*0fca6ea1SDimitry Andric 456*0fca6ea1SDimitry Andric /// Number to assign to the next VPValue without underlying value. 4575ffd83dbSDimitry Andric unsigned NextSlot = 0; 4585ffd83dbSDimitry Andric 459*0fca6ea1SDimitry Andric void assignName(const VPValue *V); 460*0fca6ea1SDimitry Andric void assignNames(const VPlan &Plan); 461*0fca6ea1SDimitry Andric void assignNames(const VPBasicBlock *VPBB); 4625ffd83dbSDimitry Andric 4635ffd83dbSDimitry Andric public: 464e8d8bef9SDimitry Andric VPSlotTracker(const VPlan *Plan = nullptr) { 4655ffd83dbSDimitry Andric if (Plan) 466*0fca6ea1SDimitry Andric assignNames(*Plan); 4675ffd83dbSDimitry Andric } 4685ffd83dbSDimitry Andric 469*0fca6ea1SDimitry Andric /// Returns the name assigned to \p V, if there is one, otherwise try to 470*0fca6ea1SDimitry Andric /// construct one from the underlying value, if there's one; else return 471*0fca6ea1SDimitry Andric /// <badref>. 472*0fca6ea1SDimitry Andric std::string getOrCreateName(const VPValue *V) const; 4735ffd83dbSDimitry Andric }; 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric } // namespace llvm 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric #endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H 478