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