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