1 //===- VPlanValue.h - Represent Values in Vectorizer Plan -----------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file contains the declarations of the entities induced by Vectorization 11 /// Plans, e.g. the instructions the VPlan intends to generate if executed. 12 /// VPlan models the following entities: 13 /// VPValue VPUser VPDef 14 /// | | 15 /// VPInstruction 16 /// These are documented in docs/VectorizationPlan.rst. 17 /// 18 //===----------------------------------------------------------------------===// 19 20 #ifndef LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H 21 #define LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H 22 23 #include "llvm/ADT/DenseMap.h" 24 #include "llvm/ADT/STLExtras.h" 25 #include "llvm/ADT/SmallVector.h" 26 #include "llvm/ADT/TinyPtrVector.h" 27 #include "llvm/ADT/iterator_range.h" 28 29 namespace llvm { 30 31 // Forward declarations. 32 class raw_ostream; 33 class Value; 34 class VPDef; 35 class VPSlotTracker; 36 class VPUser; 37 class VPRecipeBase; 38 class VPPredInstPHIRecipe; 39 40 // This is the base class of the VPlan Def/Use graph, used for modeling the data 41 // flow into, within and out of the VPlan. VPValues can stand for live-ins 42 // coming from the input IR, instructions which VPlan will generate if executed 43 // and live-outs which the VPlan will need to fix accordingly. 44 class VPValue { 45 friend class VPBuilder; 46 friend class VPDef; 47 friend struct VPlanTransforms; 48 friend class VPBasicBlock; 49 friend class VPInterleavedAccessInfo; 50 friend class VPSlotTracker; 51 friend class VPRecipeBase; 52 friend class VPPredInstPHIRecipe; 53 54 const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast). 55 56 SmallVector<VPUser *, 1> Users; 57 58 protected: 59 // Hold the underlying Value, if any, attached to this VPValue. 60 Value *UnderlyingVal; 61 62 /// Pointer to the VPDef that defines this VPValue. If it is nullptr, the 63 /// VPValue is not defined by any recipe modeled in VPlan. 64 VPDef *Def; 65 66 VPValue(const unsigned char SC, Value *UV = nullptr, VPDef *Def = nullptr); 67 68 // DESIGN PRINCIPLE: Access to the underlying IR must be strictly limited to 69 // the front-end and back-end of VPlan so that the middle-end is as 70 // independent as possible of the underlying IR. We grant access to the 71 // underlying IR using friendship. In that way, we should be able to use VPlan 72 // for multiple underlying IRs (Polly?) by providing a new VPlan front-end, 73 // back-end and analysis information for the new IR. 74 75 /// Return the underlying Value attached to this VPValue. getUnderlyingValue()76 Value *getUnderlyingValue() { return UnderlyingVal; } getUnderlyingValue()77 const Value *getUnderlyingValue() const { return UnderlyingVal; } 78 79 // Set \p Val as the underlying Value of this VPValue. setUnderlyingValue(Value * Val)80 void setUnderlyingValue(Value *Val) { 81 assert(!UnderlyingVal && "Underlying Value is already set."); 82 UnderlyingVal = Val; 83 } 84 85 public: 86 /// An enumeration for keeping track of the concrete subclass of VPValue that 87 /// are actually instantiated. Values of this enumeration are kept in the 88 /// SubclassID field of the VPValue objects. They are used for concrete 89 /// type identification. 90 enum { 91 VPValueSC, 92 VPVInstructionSC, 93 VPVMemoryInstructionSC, 94 VPVReductionSC, 95 VPVReplicateSC, 96 VPVWidenSC, 97 VPVWidenCallSC, 98 VPVWidenGEPSC, 99 VPVWidenSelectSC, 100 }; 101 102 VPValue(Value *UV = nullptr, VPDef *Def = nullptr) VPValue(VPValueSC,UV,Def)103 : VPValue(VPValueSC, UV, Def) {} 104 VPValue(const VPValue &) = delete; 105 VPValue &operator=(const VPValue &) = delete; 106 107 virtual ~VPValue(); 108 109 /// \return an ID for the concrete type of this object. 110 /// This is used to implement the classof checks. This should not be used 111 /// for any other purpose, as the values may change as LLVM evolves. getVPValueID()112 unsigned getVPValueID() const { return SubclassID; } 113 114 void printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const; 115 void print(raw_ostream &OS, VPSlotTracker &Tracker) const; 116 117 /// Dump the value to stderr (for debugging). 118 void dump() const; 119 getNumUsers()120 unsigned getNumUsers() const { return Users.size(); } addUser(VPUser & User)121 void addUser(VPUser &User) { Users.push_back(&User); } 122 123 /// Remove a single \p User from the list of users. removeUser(VPUser & User)124 void removeUser(VPUser &User) { 125 bool Found = false; 126 // The same user can be added multiple times, e.g. because the same VPValue 127 // is used twice by the same VPUser. Remove a single one. 128 erase_if(Users, [&User, &Found](VPUser *Other) { 129 if (Found) 130 return false; 131 if (Other == &User) { 132 Found = true; 133 return true; 134 } 135 return false; 136 }); 137 } 138 139 typedef SmallVectorImpl<VPUser *>::iterator user_iterator; 140 typedef SmallVectorImpl<VPUser *>::const_iterator const_user_iterator; 141 typedef iterator_range<user_iterator> user_range; 142 typedef iterator_range<const_user_iterator> const_user_range; 143 user_begin()144 user_iterator user_begin() { return Users.begin(); } user_begin()145 const_user_iterator user_begin() const { return Users.begin(); } user_end()146 user_iterator user_end() { return Users.end(); } user_end()147 const_user_iterator user_end() const { return Users.end(); } users()148 user_range users() { return user_range(user_begin(), user_end()); } users()149 const_user_range users() const { 150 return const_user_range(user_begin(), user_end()); 151 } 152 153 /// Returns true if the value has more than one unique user. hasMoreThanOneUniqueUser()154 bool hasMoreThanOneUniqueUser() { 155 if (getNumUsers() == 0) 156 return false; 157 158 // Check if all users match the first user. 159 auto Current = std::next(user_begin()); 160 while (Current != user_end() && *user_begin() == *Current) 161 Current++; 162 return Current != user_end(); 163 } 164 165 void replaceAllUsesWith(VPValue *New); 166 getDef()167 VPDef *getDef() { return Def; } 168 }; 169 170 typedef DenseMap<Value *, VPValue *> Value2VPValueTy; 171 typedef DenseMap<VPValue *, Value *> VPValue2ValueTy; 172 173 raw_ostream &operator<<(raw_ostream &OS, const VPValue &V); 174 175 /// This class augments VPValue with operands which provide the inverse def-use 176 /// edges from VPValue's users to their defs. 177 class VPUser { 178 SmallVector<VPValue *, 2> Operands; 179 180 protected: 181 /// Print the operands to \p O. 182 void printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const; 183 184 public: VPUser()185 VPUser() {} VPUser(ArrayRef<VPValue * > Operands)186 VPUser(ArrayRef<VPValue *> Operands) { 187 for (VPValue *Operand : Operands) 188 addOperand(Operand); 189 } 190 VPUser(std::initializer_list<VPValue * > Operands)191 VPUser(std::initializer_list<VPValue *> Operands) 192 : VPUser(ArrayRef<VPValue *>(Operands)) {} VPUser(iterator_range<IterT> Operands)193 template <typename IterT> VPUser(iterator_range<IterT> Operands) { 194 for (VPValue *Operand : Operands) 195 addOperand(Operand); 196 } 197 198 VPUser(const VPUser &) = delete; 199 VPUser &operator=(const VPUser &) = delete; ~VPUser()200 virtual ~VPUser() { 201 for (VPValue *Op : operands()) 202 Op->removeUser(*this); 203 } 204 addOperand(VPValue * Operand)205 void addOperand(VPValue *Operand) { 206 Operands.push_back(Operand); 207 Operand->addUser(*this); 208 } 209 getNumOperands()210 unsigned getNumOperands() const { return Operands.size(); } getOperand(unsigned N)211 inline VPValue *getOperand(unsigned N) const { 212 assert(N < Operands.size() && "Operand index out of bounds"); 213 return Operands[N]; 214 } 215 setOperand(unsigned I,VPValue * New)216 void setOperand(unsigned I, VPValue *New) { 217 Operands[I]->removeUser(*this); 218 Operands[I] = New; 219 New->addUser(*this); 220 } 221 222 typedef SmallVectorImpl<VPValue *>::iterator operand_iterator; 223 typedef SmallVectorImpl<VPValue *>::const_iterator const_operand_iterator; 224 typedef iterator_range<operand_iterator> operand_range; 225 typedef iterator_range<const_operand_iterator> const_operand_range; 226 op_begin()227 operand_iterator op_begin() { return Operands.begin(); } op_begin()228 const_operand_iterator op_begin() const { return Operands.begin(); } op_end()229 operand_iterator op_end() { return Operands.end(); } op_end()230 const_operand_iterator op_end() const { return Operands.end(); } operands()231 operand_range operands() { return operand_range(op_begin(), op_end()); } operands()232 const_operand_range operands() const { 233 return const_operand_range(op_begin(), op_end()); 234 } 235 236 /// Method to support type inquiry through isa, cast, and dyn_cast. 237 static inline bool classof(const VPRecipeBase *Recipe); 238 }; 239 240 /// This class augments a recipe with a set of VPValues defined by the recipe. 241 /// It allows recipes to define zero, one or multiple VPValues. A VPDef owns 242 /// the VPValues it defines and is responsible for deleting its defined values. 243 /// Single-value VPDefs that also inherit from VPValue must make sure to inherit 244 /// from VPDef before VPValue. 245 class VPDef { 246 friend class VPValue; 247 248 /// The VPValues defined by this VPDef. 249 TinyPtrVector<VPValue *> DefinedValues; 250 251 /// Add \p V as a defined value by this VPDef. addDefinedValue(VPValue * V)252 void addDefinedValue(VPValue *V) { 253 assert(V->getDef() == this && 254 "can only add VPValue already linked with this VPDef"); 255 DefinedValues.push_back(V); 256 } 257 258 /// Remove \p V from the values defined by this VPDef. \p V must be a defined 259 /// value of this VPDef. removeDefinedValue(VPValue * V)260 void removeDefinedValue(VPValue *V) { 261 assert(V->getDef() == this && 262 "can only remove VPValue linked with this VPDef"); 263 assert(find(DefinedValues, V) != DefinedValues.end() && 264 "VPValue to remove must be in DefinedValues"); 265 erase_value(DefinedValues, V); 266 V->Def = nullptr; 267 } 268 269 public: ~VPDef()270 virtual ~VPDef() { 271 for (VPValue *D : make_early_inc_range(DefinedValues)) { 272 assert(D->Def == this && 273 "all defined VPValues should point to the containing VPDef"); 274 assert(D->getNumUsers() == 0 && 275 "all defined VPValues should have no more users"); 276 D->Def = nullptr; 277 delete D; 278 } 279 } 280 281 /// Returns the VPValue with index \p I defined by the VPDef. 282 VPValue *getVPValue(unsigned I = 0) { 283 assert(DefinedValues[I] && "defined value must be non-null"); 284 return DefinedValues[I]; 285 } 286 const VPValue *getVPValue(unsigned I = 0) const { 287 assert(DefinedValues[I] && "defined value must be non-null"); 288 return DefinedValues[I]; 289 } 290 291 /// Returns an ArrayRef of the values defined by the VPDef. definedValues()292 ArrayRef<VPValue *> definedValues() { return DefinedValues; } 293 294 /// Returns the number of values defined by the VPDef. getNumDefinedValues()295 unsigned getNumDefinedValues() const { return DefinedValues.size(); } 296 }; 297 298 class VPlan; 299 class VPBasicBlock; 300 class VPRegionBlock; 301 302 /// This class can be used to assign consecutive numbers to all VPValues in a 303 /// VPlan and allows querying the numbering for printing, similar to the 304 /// ModuleSlotTracker for IR values. 305 class VPSlotTracker { 306 DenseMap<const VPValue *, unsigned> Slots; 307 unsigned NextSlot = 0; 308 309 void assignSlots(const VPBlockBase *VPBB); 310 void assignSlots(const VPRegionBlock *Region); 311 void assignSlots(const VPBasicBlock *VPBB); 312 void assignSlot(const VPValue *V); 313 314 void assignSlots(const VPlan &Plan); 315 316 public: VPSlotTracker(const VPlan * Plan)317 VPSlotTracker(const VPlan *Plan) { 318 if (Plan) 319 assignSlots(*Plan); 320 } 321 getSlot(const VPValue * V)322 unsigned getSlot(const VPValue *V) const { 323 auto I = Slots.find(V); 324 if (I == Slots.end()) 325 return -1; 326 return I->second; 327 } 328 }; 329 330 } // namespace llvm 331 332 #endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H 333