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