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 VPWidenMemoryInstructionRecipe; 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 class VPInstruction; 48 friend struct VPlanTransforms; 49 friend class VPBasicBlock; 50 friend class VPInterleavedAccessInfo; 51 friend class VPSlotTracker; 52 friend class VPRecipeBase; 53 friend class VPWidenMemoryInstructionRecipe; 54 55 const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast). 56 57 SmallVector<VPUser *, 1> Users; 58 59 protected: 60 // Hold the underlying Value, if any, attached to this VPValue. 61 Value *UnderlyingVal; 62 63 /// Pointer to the VPDef that defines this VPValue. If it is nullptr, the 64 /// VPValue is not defined by any recipe modeled in VPlan. 65 VPDef *Def; 66 67 VPValue(const unsigned char SC, Value *UV = nullptr, VPDef *Def = nullptr); 68 69 // DESIGN PRINCIPLE: Access to the underlying IR must be strictly limited to 70 // the front-end and back-end of VPlan so that the middle-end is as 71 // independent as possible of the underlying IR. We grant access to the 72 // underlying IR using friendship. In that way, we should be able to use VPlan 73 // for multiple underlying IRs (Polly?) by providing a new VPlan front-end, 74 // back-end and analysis information for the new IR. 75 76 // Set \p Val as the underlying Value of this VPValue. 77 void setUnderlyingValue(Value *Val) { 78 assert(!UnderlyingVal && "Underlying Value is already set."); 79 UnderlyingVal = Val; 80 } 81 82 public: 83 /// Return the underlying Value attached to this VPValue. 84 Value *getUnderlyingValue() { return UnderlyingVal; } 85 const Value *getUnderlyingValue() const { return UnderlyingVal; } 86 87 /// An enumeration for keeping track of the concrete subclass of VPValue that 88 /// are actually instantiated. 89 enum { 90 VPValueSC, /// A generic VPValue, like live-in values or defined by a recipe 91 /// that defines multiple values. 92 VPVRecipeSC /// A VPValue sub-class that is a VPRecipeBase. 93 }; 94 95 /// Create a live-in VPValue. 96 VPValue(Value *UV = nullptr) : VPValue(VPValueSC, UV, nullptr) {} 97 /// Create a VPValue for a \p Def which is a subclass of VPValue. 98 VPValue(VPDef *Def, Value *UV = nullptr) : VPValue(VPVRecipeSC, UV, Def) {} 99 /// Create a VPValue for a \p Def which defines multiple values. 100 VPValue(Value *UV, VPDef *Def) : VPValue(VPValueSC, UV, Def) {} 101 VPValue(const VPValue &) = delete; 102 VPValue &operator=(const VPValue &) = delete; 103 104 virtual ~VPValue(); 105 106 /// \return an ID for the concrete type of this object. 107 /// This is used to implement the classof checks. This should not be used 108 /// for any other purpose, as the values may change as LLVM evolves. 109 unsigned getVPValueID() const { return SubclassID; } 110 111 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 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 #endif 118 119 unsigned getNumUsers() const { return Users.size(); } 120 void addUser(VPUser &User) { Users.push_back(&User); } 121 122 /// Remove a single \p User from the list of users. 123 void removeUser(VPUser &User) { 124 bool Found = false; 125 // The same user can be added multiple times, e.g. because the same VPValue 126 // is used twice by the same VPUser. Remove a single one. 127 erase_if(Users, [&User, &Found](VPUser *Other) { 128 if (Found) 129 return false; 130 if (Other == &User) { 131 Found = true; 132 return true; 133 } 134 return false; 135 }); 136 } 137 138 typedef SmallVectorImpl<VPUser *>::iterator user_iterator; 139 typedef SmallVectorImpl<VPUser *>::const_iterator const_user_iterator; 140 typedef iterator_range<user_iterator> user_range; 141 typedef iterator_range<const_user_iterator> const_user_range; 142 143 user_iterator user_begin() { return Users.begin(); } 144 const_user_iterator user_begin() const { return Users.begin(); } 145 user_iterator user_end() { return Users.end(); } 146 const_user_iterator user_end() const { return Users.end(); } 147 user_range users() { return user_range(user_begin(), user_end()); } 148 const_user_range users() const { 149 return const_user_range(user_begin(), user_end()); 150 } 151 152 /// Returns true if the value has more than one unique user. 153 bool hasMoreThanOneUniqueUser() { 154 if (getNumUsers() == 0) 155 return false; 156 157 // Check if all users match the first user. 158 auto Current = std::next(user_begin()); 159 while (Current != user_end() && *user_begin() == *Current) 160 Current++; 161 return Current != user_end(); 162 } 163 164 void replaceAllUsesWith(VPValue *New); 165 166 /// Returns the recipe defining this VPValue or nullptr if it is not defined 167 /// by a recipe, i.e. is a live-in. 168 VPRecipeBase *getDefiningRecipe(); 169 const VPRecipeBase *getDefiningRecipe() const; 170 171 /// Returns true if this VPValue is defined by a recipe. 172 bool hasDefiningRecipe() const { return getDefiningRecipe(); } 173 174 /// Returns true if this VPValue is a live-in, i.e. defined outside the VPlan. 175 bool isLiveIn() const { return !hasDefiningRecipe(); } 176 177 /// Returns the underlying IR value, if this VPValue is defined outside the 178 /// scope of VPlan. Returns nullptr if the VPValue is defined by a VPDef 179 /// inside a VPlan. 180 Value *getLiveInIRValue() { 181 assert(isLiveIn() && 182 "VPValue is not a live-in; it is defined by a VPDef inside a VPlan"); 183 return getUnderlyingValue(); 184 } 185 const Value *getLiveInIRValue() const { 186 assert(isLiveIn() && 187 "VPValue is not a live-in; it is defined by a VPDef inside a VPlan"); 188 return getUnderlyingValue(); 189 } 190 191 /// Returns true if the VPValue is defined outside any vector regions, i.e. it 192 /// is a live-in value. 193 /// TODO: Also handle recipes defined in pre-header blocks. 194 bool isDefinedOutsideVectorRegions() const { return !hasDefiningRecipe(); } 195 }; 196 197 typedef DenseMap<Value *, VPValue *> Value2VPValueTy; 198 typedef DenseMap<VPValue *, Value *> VPValue2ValueTy; 199 200 raw_ostream &operator<<(raw_ostream &OS, const VPValue &V); 201 202 /// This class augments VPValue with operands which provide the inverse def-use 203 /// edges from VPValue's users to their defs. 204 class VPUser { 205 public: 206 /// Subclass identifier (for isa/dyn_cast). 207 enum class VPUserID { 208 Recipe, 209 LiveOut, 210 }; 211 212 private: 213 SmallVector<VPValue *, 2> Operands; 214 215 VPUserID ID; 216 217 protected: 218 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 219 /// Print the operands to \p O. 220 void printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const; 221 #endif 222 223 VPUser(ArrayRef<VPValue *> Operands, VPUserID ID) : ID(ID) { 224 for (VPValue *Operand : Operands) 225 addOperand(Operand); 226 } 227 228 VPUser(std::initializer_list<VPValue *> Operands, VPUserID ID) 229 : VPUser(ArrayRef<VPValue *>(Operands), ID) {} 230 231 template <typename IterT> 232 VPUser(iterator_range<IterT> Operands, VPUserID ID) : ID(ID) { 233 for (VPValue *Operand : Operands) 234 addOperand(Operand); 235 } 236 237 public: 238 VPUser() = delete; 239 VPUser(const VPUser &) = delete; 240 VPUser &operator=(const VPUser &) = delete; 241 virtual ~VPUser() { 242 for (VPValue *Op : operands()) 243 Op->removeUser(*this); 244 } 245 246 VPUserID getVPUserID() const { return ID; } 247 248 void addOperand(VPValue *Operand) { 249 Operands.push_back(Operand); 250 Operand->addUser(*this); 251 } 252 253 unsigned getNumOperands() const { return Operands.size(); } 254 inline VPValue *getOperand(unsigned N) const { 255 assert(N < Operands.size() && "Operand index out of bounds"); 256 return Operands[N]; 257 } 258 259 void setOperand(unsigned I, VPValue *New) { 260 Operands[I]->removeUser(*this); 261 Operands[I] = New; 262 New->addUser(*this); 263 } 264 265 void removeLastOperand() { 266 VPValue *Op = Operands.pop_back_val(); 267 Op->removeUser(*this); 268 } 269 270 typedef SmallVectorImpl<VPValue *>::iterator operand_iterator; 271 typedef SmallVectorImpl<VPValue *>::const_iterator const_operand_iterator; 272 typedef iterator_range<operand_iterator> operand_range; 273 typedef iterator_range<const_operand_iterator> const_operand_range; 274 275 operand_iterator op_begin() { return Operands.begin(); } 276 const_operand_iterator op_begin() const { return Operands.begin(); } 277 operand_iterator op_end() { return Operands.end(); } 278 const_operand_iterator op_end() const { return Operands.end(); } 279 operand_range operands() { return operand_range(op_begin(), op_end()); } 280 const_operand_range operands() const { 281 return const_operand_range(op_begin(), op_end()); 282 } 283 284 /// Returns true if the VPUser uses scalars of operand \p Op. Conservatively 285 /// returns if only first (scalar) lane is used, as default. 286 virtual bool usesScalars(const VPValue *Op) const { 287 assert(is_contained(operands(), Op) && 288 "Op must be an operand of the recipe"); 289 return onlyFirstLaneUsed(Op); 290 } 291 292 /// Returns true if the VPUser only uses the first lane of operand \p Op. 293 /// Conservatively returns false. 294 virtual bool onlyFirstLaneUsed(const VPValue *Op) const { 295 assert(is_contained(operands(), Op) && 296 "Op must be an operand of the recipe"); 297 return false; 298 } 299 }; 300 301 /// This class augments a recipe with a set of VPValues defined by the recipe. 302 /// It allows recipes to define zero, one or multiple VPValues. A VPDef owns 303 /// the VPValues it defines and is responsible for deleting its defined values. 304 /// Single-value VPDefs that also inherit from VPValue must make sure to inherit 305 /// from VPDef before VPValue. 306 class VPDef { 307 friend class VPValue; 308 309 /// Subclass identifier (for isa/dyn_cast). 310 const unsigned char SubclassID; 311 312 /// The VPValues defined by this VPDef. 313 TinyPtrVector<VPValue *> DefinedValues; 314 315 /// Add \p V as a defined value by this VPDef. 316 void addDefinedValue(VPValue *V) { 317 assert(V->Def == this && 318 "can only add VPValue already linked with this VPDef"); 319 DefinedValues.push_back(V); 320 } 321 322 /// Remove \p V from the values defined by this VPDef. \p V must be a defined 323 /// value of this VPDef. 324 void removeDefinedValue(VPValue *V) { 325 assert(V->Def == this && "can only remove VPValue linked with this VPDef"); 326 assert(is_contained(DefinedValues, V) && 327 "VPValue to remove must be in DefinedValues"); 328 erase_value(DefinedValues, V); 329 V->Def = nullptr; 330 } 331 332 public: 333 /// An enumeration for keeping track of the concrete subclass of VPRecipeBase 334 /// that is actually instantiated. Values of this enumeration are kept in the 335 /// SubclassID field of the VPRecipeBase objects. They are used for concrete 336 /// type identification. 337 using VPRecipeTy = enum { 338 VPBranchOnMaskSC, 339 VPDerivedIVSC, 340 VPExpandSCEVSC, 341 VPInstructionSC, 342 VPInterleaveSC, 343 VPReductionSC, 344 VPReplicateSC, 345 VPScalarIVStepsSC, 346 VPWidenCallSC, 347 VPWidenCanonicalIVSC, 348 VPWidenGEPSC, 349 VPWidenMemoryInstructionSC, 350 VPWidenSC, 351 VPWidenSelectSC, 352 // START: Phi-like recipes. Need to be kept together. 353 VPBlendSC, 354 VPPredInstPHISC, 355 // START: SubclassID for recipes that inherit VPHeaderPHIRecipe. 356 // VPHeaderPHIRecipe need to be kept together. 357 VPCanonicalIVPHISC, 358 VPActiveLaneMaskPHISC, 359 VPFirstOrderRecurrencePHISC, 360 VPWidenPHISC, 361 VPWidenIntOrFpInductionSC, 362 VPWidenPointerInductionSC, 363 VPReductionPHISC, 364 // END: SubclassID for recipes that inherit VPHeaderPHIRecipe 365 // END: Phi-like recipes 366 VPFirstPHISC = VPBlendSC, 367 VPFirstHeaderPHISC = VPCanonicalIVPHISC, 368 VPLastHeaderPHISC = VPReductionPHISC, 369 VPLastPHISC = VPReductionPHISC, 370 }; 371 372 VPDef(const unsigned char SC) : SubclassID(SC) {} 373 374 virtual ~VPDef() { 375 for (VPValue *D : make_early_inc_range(DefinedValues)) { 376 assert(D->Def == this && 377 "all defined VPValues should point to the containing VPDef"); 378 assert(D->getNumUsers() == 0 && 379 "all defined VPValues should have no more users"); 380 D->Def = nullptr; 381 delete D; 382 } 383 } 384 385 /// Returns the only VPValue defined by the VPDef. Can only be called for 386 /// VPDefs with a single defined value. 387 VPValue *getVPSingleValue() { 388 assert(DefinedValues.size() == 1 && "must have exactly one defined value"); 389 assert(DefinedValues[0] && "defined value must be non-null"); 390 return DefinedValues[0]; 391 } 392 const VPValue *getVPSingleValue() const { 393 assert(DefinedValues.size() == 1 && "must have exactly one defined value"); 394 assert(DefinedValues[0] && "defined value must be non-null"); 395 return DefinedValues[0]; 396 } 397 398 /// Returns the VPValue with index \p I defined by the VPDef. 399 VPValue *getVPValue(unsigned I) { 400 assert(DefinedValues[I] && "defined value must be non-null"); 401 return DefinedValues[I]; 402 } 403 const VPValue *getVPValue(unsigned I) const { 404 assert(DefinedValues[I] && "defined value must be non-null"); 405 return DefinedValues[I]; 406 } 407 408 /// Returns an ArrayRef of the values defined by the VPDef. 409 ArrayRef<VPValue *> definedValues() { return DefinedValues; } 410 /// Returns an ArrayRef of the values defined by the VPDef. 411 ArrayRef<VPValue *> definedValues() const { return DefinedValues; } 412 413 /// Returns the number of values defined by the VPDef. 414 unsigned getNumDefinedValues() const { return DefinedValues.size(); } 415 416 /// \return an ID for the concrete type of this object. 417 /// This is used to implement the classof checks. This should not be used 418 /// for any other purpose, as the values may change as LLVM evolves. 419 unsigned getVPDefID() const { return SubclassID; } 420 421 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 422 /// Dump the VPDef to stderr (for debugging). 423 void dump() const; 424 425 /// Each concrete VPDef prints itself. 426 virtual void print(raw_ostream &O, const Twine &Indent, 427 VPSlotTracker &SlotTracker) const = 0; 428 #endif 429 }; 430 431 class VPlan; 432 class VPBasicBlock; 433 434 /// This class can be used to assign consecutive numbers to all VPValues in a 435 /// VPlan and allows querying the numbering for printing, similar to the 436 /// ModuleSlotTracker for IR values. 437 class VPSlotTracker { 438 DenseMap<const VPValue *, unsigned> Slots; 439 unsigned NextSlot = 0; 440 441 void assignSlot(const VPValue *V); 442 void assignSlots(const VPlan &Plan); 443 void assignSlots(const VPBasicBlock *VPBB); 444 445 public: 446 VPSlotTracker(const VPlan *Plan = nullptr) { 447 if (Plan) 448 assignSlots(*Plan); 449 } 450 451 unsigned getSlot(const VPValue *V) const { 452 auto I = Slots.find(V); 453 if (I == Slots.end()) 454 return -1; 455 return I->second; 456 } 457 }; 458 459 } // namespace llvm 460 461 #endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H 462