1227825Stheraven//===- VPlanValue.h - Represent Values in Vectorizer Plan -----------------===// 2227825Stheraven// 3227825Stheraven// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4227825Stheraven// See https://llvm.org/LICENSE.txt for license information. 5227825Stheraven// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6227825Stheraven// 7227825Stheraven//===----------------------------------------------------------------------===// 8227825Stheraven/// 9227825Stheraven/// \file 10262801Sdim/// This file contains the declarations of the entities induced by Vectorization 11227825Stheraven/// Plans, e.g. the instructions the VPlan intends to generate if executed. 12227825Stheraven/// VPlan models the following entities: 13227825Stheraven/// VPValue VPUser VPDef 14227825Stheraven/// | | 15227825Stheraven/// VPInstruction 16227825Stheraven/// These are documented in docs/VectorizationPlan.rst. 17227825Stheraven/// 18227825Stheraven//===----------------------------------------------------------------------===// 19227825Stheraven 20249998Sdim#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H 21227825Stheraven#define LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H 22227825Stheraven 23227825Stheraven#include "llvm/ADT/DenseMap.h" 24227825Stheraven#include "llvm/ADT/STLExtras.h" 25227825Stheraven#include "llvm/ADT/SmallVector.h" 26246487Stheraven#include "llvm/ADT/TinyPtrVector.h" 27227825Stheraven#include "llvm/ADT/iterator_range.h" 28249998Sdim 29227825Stheravennamespace llvm { 30227825Stheraven 31227825Stheraven// Forward declarations. 32227825Stheravenclass raw_ostream; 33227825Stheravenclass Value; 34227825Stheravenclass VPDef; 35227825Stheravenclass VPSlotTracker; 36227825Stheravenclass VPUser; 37227825Stheravenclass VPRecipeBase; 38227825Stheravenclass VPWidenMemoryInstructionRecipe; 39227825Stheraven 40227825Stheraven// This is the base class of the VPlan Def/Use graph, used for modeling the data 41227825Stheraven// flow into, within and out of the VPlan. VPValues can stand for live-ins 42227825Stheraven// coming from the input IR, instructions which VPlan will generate if executed 43227825Stheraven// and live-outs which the VPlan will need to fix accordingly. 44227825Stheravenclass VPValue { 45227825Stheraven friend class VPBuilder; 46227825Stheraven friend class VPDef; 47227825Stheraven friend class VPInstruction; 48227825Stheraven friend struct VPlanTransforms; 49227825Stheraven friend class VPBasicBlock; 50227825Stheraven friend class VPInterleavedAccessInfo; 51227825Stheraven friend class VPSlotTracker; 52227825Stheraven friend class VPRecipeBase; 53227825Stheraven friend class VPWidenMemoryInstructionRecipe; 54227825Stheraven 55227825Stheraven const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast). 56227825Stheraven 57227825Stheraven SmallVector<VPUser *, 1> Users; 58227825Stheraven 59227825Stheravenprotected: 60227825Stheraven // Hold the underlying Value, if any, attached to this VPValue. 61227825Stheraven Value *UnderlyingVal; 62227825Stheraven 63227825Stheraven /// Pointer to the VPDef that defines this VPValue. If it is nullptr, the 64227825Stheraven /// VPValue is not defined by any recipe modeled in VPlan. 65227825Stheraven VPDef *Def; 66227825Stheraven 67227825Stheraven VPValue(const unsigned char SC, Value *UV = nullptr, VPDef *Def = nullptr); 68227825Stheraven 69227825Stheraven // DESIGN PRINCIPLE: Access to the underlying IR must be strictly limited to 70227825Stheraven // the front-end and back-end of VPlan so that the middle-end is as 71227825Stheraven // independent as possible of the underlying IR. We grant access to the 72227825Stheraven // underlying IR using friendship. In that way, we should be able to use VPlan 73227825Stheraven // for multiple underlying IRs (Polly?) by providing a new VPlan front-end, 74227825Stheraven // back-end and analysis information for the new IR. 75227825Stheraven 76227825Stheraven // Set \p Val as the underlying Value of this VPValue. 77227825Stheraven void setUnderlyingValue(Value *Val) { 78227825Stheraven assert(!UnderlyingVal && "Underlying Value is already set."); 79227825Stheraven UnderlyingVal = Val; 80227825Stheraven } 81227825Stheraven 82227825Stheravenpublic: 83227825Stheraven /// Return the underlying Value attached to this VPValue. 84227825Stheraven Value *getUnderlyingValue() { return UnderlyingVal; } 85227825Stheraven const Value *getUnderlyingValue() const { return UnderlyingVal; } 86227825Stheraven 87227825Stheraven /// An enumeration for keeping track of the concrete subclass of VPValue that 88227825Stheraven /// are actually instantiated. 89227825Stheraven enum { 90227825Stheraven VPValueSC, /// A generic VPValue, like live-in values or defined by a recipe 91227825Stheraven /// that defines multiple values. 92227825Stheraven VPVRecipeSC /// A VPValue sub-class that is a VPRecipeBase. 93227825Stheraven }; 94227825Stheraven 95227825Stheraven /// Create a live-in VPValue. 96227825Stheraven VPValue(Value *UV = nullptr) : VPValue(VPValueSC, UV, nullptr) {} 97227825Stheraven /// Create a VPValue for a \p Def which is a subclass of VPValue. 98227825Stheraven VPValue(VPDef *Def, Value *UV = nullptr) : VPValue(VPVRecipeSC, UV, Def) {} 99227825Stheraven /// Create a VPValue for a \p Def which defines multiple values. 100227825Stheraven VPValue(Value *UV, VPDef *Def) : VPValue(VPValueSC, UV, Def) {} 101227825Stheraven VPValue(const VPValue &) = delete; 102227825Stheraven VPValue &operator=(const VPValue &) = delete; 103227825Stheraven 104227825Stheraven virtual ~VPValue(); 105227825Stheraven 106227825Stheraven /// \return an ID for the concrete type of this object. 107227825Stheraven /// This is used to implement the classof checks. This should not be used 108227825Stheraven /// for any other purpose, as the values may change as LLVM evolves. 109227825Stheraven unsigned getVPValueID() const { return SubclassID; } 110227825Stheraven 111227825Stheraven#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 112227825Stheraven void printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const; 113249998Sdim void print(raw_ostream &OS, VPSlotTracker &Tracker) const; 114227825Stheraven 115227825Stheraven /// Dump the value to stderr (for debugging). 116227825Stheraven void dump() const; 117227825Stheraven#endif 118227825Stheraven 119227825Stheraven unsigned getNumUsers() const { return Users.size(); } 120227825Stheraven void addUser(VPUser &User) { Users.push_back(&User); } 121262801Sdim 122262801Sdim /// Remove a single \p User from the list of users. 123232950Stheraven void removeUser(VPUser &User) { 124227825Stheraven // The same user can be added multiple times, e.g. because the same VPValue 125262801Sdim // is used twice by the same VPUser. Remove a single one. 126262801Sdim auto *I = find(Users, &User); 127227825Stheraven if (I != Users.end()) 128227825Stheraven Users.erase(I); 129227825Stheraven } 130262801Sdim 131262801Sdim typedef SmallVectorImpl<VPUser *>::iterator user_iterator; 132227825Stheraven typedef SmallVectorImpl<VPUser *>::const_iterator const_user_iterator; 133262801Sdim typedef iterator_range<user_iterator> user_range; 134227825Stheraven typedef iterator_range<const_user_iterator> const_user_range; 135227825Stheraven 136227825Stheraven user_iterator user_begin() { return Users.begin(); } 137227825Stheraven const_user_iterator user_begin() const { return Users.begin(); } 138227825Stheraven user_iterator user_end() { return Users.end(); } 139227825Stheraven const_user_iterator user_end() const { return Users.end(); } 140227825Stheraven user_range users() { return user_range(user_begin(), user_end()); } 141227825Stheraven const_user_range users() const { 142232950Stheraven return const_user_range(user_begin(), user_end()); 143227825Stheraven } 144232950Stheraven 145253159Stheraven /// Returns true if the value has more than one unique user. 146227825Stheraven bool hasMoreThanOneUniqueUser() { 147241903Sdim if (getNumUsers() == 0) 148227825Stheraven return false; 149241903Sdim 150241903Sdim // Check if all users match the first user. 151241903Sdim auto Current = std::next(user_begin()); 152227825Stheraven while (Current != user_end() && *user_begin() == *Current) 153227825Stheraven Current++; 154227825Stheraven return Current != user_end(); 155227825Stheraven } 156227825Stheraven 157227825Stheraven void replaceAllUsesWith(VPValue *New); 158227825Stheraven 159227825Stheraven /// Go through the uses list for this VPValue and make each use point to \p 160227825Stheraven /// New if the callback ShouldReplace returns true for the given use specified 161227825Stheraven /// by a pair of (VPUser, the use index). 162227825Stheraven void replaceUsesWithIf( 163227825Stheraven VPValue *New, 164227825Stheraven llvm::function_ref<bool(VPUser &U, unsigned Idx)> ShouldReplace); 165227825Stheraven 166227825Stheraven /// Returns the recipe defining this VPValue or nullptr if it is not defined 167227825Stheraven /// by a recipe, i.e. is a live-in. 168232950Stheraven VPRecipeBase *getDefiningRecipe(); 169227825Stheraven const VPRecipeBase *getDefiningRecipe() const; 170253159Stheraven 171253159Stheraven /// Returns true if this VPValue is defined by a recipe. 172227825Stheraven bool hasDefiningRecipe() const { return getDefiningRecipe(); } 173241903Sdim 174227825Stheraven /// Returns true if this VPValue is a live-in, i.e. defined outside the VPlan. 175241903Sdim bool isLiveIn() const { return !hasDefiningRecipe(); } 176241903Sdim 177241903Sdim /// Returns the underlying IR value, if this VPValue is defined outside the 178227825Stheraven /// scope of VPlan. Returns nullptr if the VPValue is defined by a VPDef 179227825Stheraven /// inside a VPlan. 180227825Stheraven Value *getLiveInIRValue() { 181227825Stheraven assert(isLiveIn() && 182227825Stheraven "VPValue is not a live-in; it is defined by a VPDef inside a VPlan"); 183227825Stheraven return getUnderlyingValue(); 184227825Stheraven } 185227825Stheraven const Value *getLiveInIRValue() const { 186227825Stheraven assert(isLiveIn() && 187227825Stheraven "VPValue is not a live-in; it is defined by a VPDef inside a VPlan"); 188227825Stheraven return getUnderlyingValue(); 189227825Stheraven } 190232950Stheraven 191227825Stheraven /// Returns true if the VPValue is defined outside any vector regions, i.e. it 192227825Stheraven /// is a live-in value. 193227825Stheraven /// TODO: Also handle recipes defined in pre-header blocks. 194227825Stheraven bool isDefinedOutsideVectorRegions() const { return !hasDefiningRecipe(); } 195227825Stheraven}; 196227825Stheraven 197227825Stheraventypedef DenseMap<Value *, VPValue *> Value2VPValueTy; 198227825Stheraventypedef DenseMap<VPValue *, Value *> VPValue2ValueTy; 199227825Stheraven 200227825Stheravenraw_ostream &operator<<(raw_ostream &OS, const VPValue &V); 201227825Stheraven 202227825Stheraven/// This class augments VPValue with operands which provide the inverse def-use 203227825Stheraven/// edges from VPValue's users to their defs. 204227825Stheravenclass VPUser { 205227825Stheravenpublic: 206227825Stheraven /// Subclass identifier (for isa/dyn_cast). 207227825Stheraven enum class VPUserID { 208227825Stheraven Recipe, 209227825Stheraven LiveOut, 210227825Stheraven }; 211227825Stheraven 212227825Stheravenprivate: 213227825Stheraven SmallVector<VPValue *, 2> Operands; 214227825Stheraven 215227825Stheraven VPUserID ID; 216227825Stheraven 217227825Stheravenprotected: 218227825Stheraven#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 219262801Sdim /// Print the operands to \p O. 220227825Stheraven void printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const; 221262801Sdim#endif 222262801Sdim 223262801Sdim VPUser(ArrayRef<VPValue *> Operands, VPUserID ID) : ID(ID) { 224262801Sdim for (VPValue *Operand : Operands) 225262801Sdim addOperand(Operand); 226262801Sdim } 227262801Sdim 228262801Sdim VPUser(std::initializer_list<VPValue *> Operands, VPUserID ID) 229262801Sdim : VPUser(ArrayRef<VPValue *>(Operands), ID) {} 230262801Sdim 231262801Sdim template <typename IterT> 232262801Sdim VPUser(iterator_range<IterT> Operands, VPUserID ID) : ID(ID) { 233262801Sdim for (VPValue *Operand : Operands) 234262801Sdim addOperand(Operand); 235262801Sdim } 236227825Stheraven 237227825Stheravenpublic: 238227825Stheraven VPUser() = delete; 239227825Stheraven VPUser(const VPUser &) = delete; 240227825Stheraven VPUser &operator=(const VPUser &) = delete; 241227825Stheraven virtual ~VPUser() { 242227825Stheraven for (VPValue *Op : operands()) 243262801Sdim Op->removeUser(*this); 244262801Sdim } 245262801Sdim 246262801Sdim VPUserID getVPUserID() const { return ID; } 247262801Sdim 248232950Stheraven void addOperand(VPValue *Operand) { 249227825Stheraven Operands.push_back(Operand); 250262801Sdim Operand->addUser(*this); 251262801Sdim } 252262801Sdim 253262801Sdim unsigned getNumOperands() const { return Operands.size(); } 254262801Sdim inline VPValue *getOperand(unsigned N) const { 255227825Stheraven assert(N < Operands.size() && "Operand index out of bounds"); 256227825Stheraven return Operands[N]; 257227825Stheraven } 258262801Sdim 259262801Sdim void setOperand(unsigned I, VPValue *New) { 260262801Sdim Operands[I]->removeUser(*this); 261262801Sdim Operands[I] = New; 262262801Sdim New->addUser(*this); 263227825Stheraven } 264227825Stheraven 265227825Stheraven void removeLastOperand() { 266227825Stheraven VPValue *Op = Operands.pop_back_val(); 267227825Stheraven Op->removeUser(*this); 268227825Stheraven } 269227825Stheraven 270232950Stheraven typedef SmallVectorImpl<VPValue *>::iterator operand_iterator; 271227825Stheraven typedef SmallVectorImpl<VPValue *>::const_iterator const_operand_iterator; 272227825Stheraven typedef iterator_range<operand_iterator> operand_range; 273227825Stheraven typedef iterator_range<const_operand_iterator> const_operand_range; 274227825Stheraven 275227825Stheraven operand_iterator op_begin() { return Operands.begin(); } 276227825Stheraven const_operand_iterator op_begin() const { return Operands.begin(); } 277227825Stheraven operand_iterator op_end() { return Operands.end(); } 278227825Stheraven const_operand_iterator op_end() const { return Operands.end(); } 279227825Stheraven operand_range operands() { return operand_range(op_begin(), op_end()); } 280227825Stheraven const_operand_range operands() const { 281227825Stheraven return const_operand_range(op_begin(), op_end()); 282227825Stheraven } 283227825Stheraven 284227825Stheraven /// Returns true if the VPUser uses scalars of operand \p Op. Conservatively 285227825Stheraven /// returns if only first (scalar) lane is used, as default. 286227825Stheraven virtual bool usesScalars(const VPValue *Op) const { 287227825Stheraven assert(is_contained(operands(), Op) && 288227825Stheraven "Op must be an operand of the recipe"); 289227825Stheraven return onlyFirstLaneUsed(Op); 290227825Stheraven } 291262801Sdim 292227825Stheraven /// Returns true if the VPUser only uses the first lane of operand \p Op. 293262801Sdim /// Conservatively returns false. 294262801Sdim virtual bool onlyFirstLaneUsed(const VPValue *Op) const { 295262801Sdim assert(is_contained(operands(), Op) && 296262801Sdim "Op must be an operand of the recipe"); 297262801Sdim return false; 298262801Sdim } 299262801Sdim 300262801Sdim /// Returns true if the VPUser only uses the first part of operand \p Op. 301262801Sdim /// Conservatively returns false. 302262801Sdim virtual bool onlyFirstPartUsed(const VPValue *Op) const { 303262801Sdim assert(is_contained(operands(), Op) && 304262801Sdim "Op must be an operand of the recipe"); 305262801Sdim return false; 306262801Sdim } 307262801Sdim}; 308262801Sdim 309262801Sdim/// This class augments a recipe with a set of VPValues defined by the recipe. 310262801Sdim/// It allows recipes to define zero, one or multiple VPValues. A VPDef owns 311262801Sdim/// the VPValues it defines and is responsible for deleting its defined values. 312262801Sdim/// Single-value VPDefs that also inherit from VPValue must make sure to inherit 313262801Sdim/// from VPDef before VPValue. 314262801Sdimclass VPDef { 315262801Sdim friend class VPValue; 316262801Sdim 317262801Sdim /// Subclass identifier (for isa/dyn_cast). 318262801Sdim const unsigned char SubclassID; 319227825Stheraven 320227825Stheraven /// The VPValues defined by this VPDef. 321227825Stheraven TinyPtrVector<VPValue *> DefinedValues; 322227825Stheraven 323227825Stheraven /// Add \p V as a defined value by this VPDef. 324227825Stheraven void addDefinedValue(VPValue *V) { 325227825Stheraven assert(V->Def == this && 326227825Stheraven "can only add VPValue already linked with this VPDef"); 327227825Stheraven DefinedValues.push_back(V); 328227825Stheraven } 329249998Sdim 330227825Stheraven /// Remove \p V from the values defined by this VPDef. \p V must be a defined 331227825Stheraven /// value of this VPDef. 332227825Stheraven void removeDefinedValue(VPValue *V) { 333227825Stheraven assert(V->Def == this && "can only remove VPValue linked with this VPDef"); 334227825Stheraven assert(is_contained(DefinedValues, V) && 335227825Stheraven "VPValue to remove must be in DefinedValues"); 336227825Stheraven llvm::erase(DefinedValues, V); 337227825Stheraven V->Def = nullptr; 338227825Stheraven } 339227825Stheraven 340227825Stheravenpublic: 341227825Stheraven /// An enumeration for keeping track of the concrete subclass of VPRecipeBase 342227825Stheraven /// that is actually instantiated. Values of this enumeration are kept in the 343227825Stheraven /// SubclassID field of the VPRecipeBase objects. They are used for concrete 344227825Stheraven /// type identification. 345227825Stheraven using VPRecipeTy = enum { 346227825Stheraven VPBranchOnMaskSC, 347227825Stheraven VPDerivedIVSC, 348227825Stheraven VPExpandSCEVSC, 349227825Stheraven VPInstructionSC, 350227825Stheraven VPInterleaveSC, 351227825Stheraven VPReductionSC, 352227825Stheraven VPReplicateSC, 353227825Stheraven VPScalarIVStepsSC, 354227825Stheraven VPVectorPointerSC, 355227825Stheraven VPWidenCallSC, 356227825Stheraven VPWidenCanonicalIVSC, 357227825Stheraven VPWidenCastSC, 358227825Stheraven VPWidenGEPSC, 359227825Stheraven VPWidenMemoryInstructionSC, 360227825Stheraven VPWidenSC, 361227825Stheraven VPWidenSelectSC, 362227825Stheraven // START: Phi-like recipes. Need to be kept together. 363227825Stheraven VPBlendSC, 364227825Stheraven VPPredInstPHISC, 365227825Stheraven // START: SubclassID for recipes that inherit VPHeaderPHIRecipe. 366227825Stheraven // VPHeaderPHIRecipe need to be kept together. 367227825Stheraven VPCanonicalIVPHISC, 368227825Stheraven VPActiveLaneMaskPHISC, 369227825Stheraven VPFirstOrderRecurrencePHISC, 370227825Stheraven VPWidenPHISC, 371227825Stheraven VPWidenIntOrFpInductionSC, 372227825Stheraven VPWidenPointerInductionSC, 373227825Stheraven VPReductionPHISC, 374227825Stheraven // END: SubclassID for recipes that inherit VPHeaderPHIRecipe 375227825Stheraven // END: Phi-like recipes 376227825Stheraven VPFirstPHISC = VPBlendSC, 377227825Stheraven VPFirstHeaderPHISC = VPCanonicalIVPHISC, 378227825Stheraven VPLastHeaderPHISC = VPReductionPHISC, 379227825Stheraven VPLastPHISC = VPReductionPHISC, 380227825Stheraven }; 381262801Sdim 382227825Stheraven VPDef(const unsigned char SC) : SubclassID(SC) {} 383227825Stheraven 384227825Stheraven virtual ~VPDef() { 385227825Stheraven for (VPValue *D : make_early_inc_range(DefinedValues)) { 386227825Stheraven assert(D->Def == this && 387227825Stheraven "all defined VPValues should point to the containing VPDef"); 388227825Stheraven assert(D->getNumUsers() == 0 && 389227825Stheraven "all defined VPValues should have no more users"); 390227825Stheraven D->Def = nullptr; 391227825Stheraven delete D; 392227825Stheraven } 393227825Stheraven } 394227825Stheraven 395232950Stheraven /// Returns the only VPValue defined by the VPDef. Can only be called for 396227825Stheraven /// VPDefs with a single defined value. 397227825Stheraven VPValue *getVPSingleValue() { 398227825Stheraven assert(DefinedValues.size() == 1 && "must have exactly one defined value"); 399227825Stheraven assert(DefinedValues[0] && "defined value must be non-null"); 400227825Stheraven return DefinedValues[0]; 401227825Stheraven } 402227825Stheraven const VPValue *getVPSingleValue() const { 403232950Stheraven assert(DefinedValues.size() == 1 && "must have exactly one defined value"); 404227825Stheraven assert(DefinedValues[0] && "defined value must be non-null"); 405227825Stheraven return DefinedValues[0]; 406227825Stheraven } 407227825Stheraven 408227825Stheraven /// Returns the VPValue with index \p I defined by the VPDef. 409227825Stheraven VPValue *getVPValue(unsigned I) { 410227825Stheraven assert(DefinedValues[I] && "defined value must be non-null"); 411227825Stheraven return DefinedValues[I]; 412227825Stheraven } 413227825Stheraven const VPValue *getVPValue(unsigned I) const { 414227825Stheraven assert(DefinedValues[I] && "defined value must be non-null"); 415227825Stheraven return DefinedValues[I]; 416227825Stheraven } 417227825Stheraven 418227825Stheraven /// Returns an ArrayRef of the values defined by the VPDef. 419227825Stheraven ArrayRef<VPValue *> definedValues() { return DefinedValues; } 420227825Stheraven /// Returns an ArrayRef of the values defined by the VPDef. 421227825Stheraven ArrayRef<VPValue *> definedValues() const { return DefinedValues; } 422227825Stheraven 423227825Stheraven /// Returns the number of values defined by the VPDef. 424227825Stheraven unsigned getNumDefinedValues() const { return DefinedValues.size(); } 425227825Stheraven 426227825Stheraven /// \return an ID for the concrete type of this object. 427227825Stheraven /// This is used to implement the classof checks. This should not be used 428227825Stheraven /// for any other purpose, as the values may change as LLVM evolves. 429227825Stheraven unsigned getVPDefID() const { return SubclassID; } 430227825Stheraven 431227825Stheraven#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 432232950Stheraven /// Dump the VPDef to stderr (for debugging). 433227825Stheraven void dump() const; 434227825Stheraven 435253159Stheraven /// Each concrete VPDef prints itself. 436253159Stheraven virtual void print(raw_ostream &O, const Twine &Indent, 437227825Stheraven VPSlotTracker &SlotTracker) const = 0; 438241903Sdim#endif 439227825Stheraven}; 440241903Sdim 441241903Sdimclass VPlan; 442241903Sdimclass VPBasicBlock; 443227825Stheraven 444227825Stheraven/// This class can be used to assign consecutive numbers to all VPValues in a 445227825Stheraven/// VPlan and allows querying the numbering for printing, similar to the 446227825Stheraven/// ModuleSlotTracker for IR values. 447227825Stheravenclass VPSlotTracker { 448227825Stheraven DenseMap<const VPValue *, unsigned> Slots; 449227825Stheraven unsigned NextSlot = 0; 450227825Stheraven 451227825Stheraven void assignSlot(const VPValue *V); 452227825Stheraven void assignSlots(const VPlan &Plan); 453227825Stheraven void assignSlots(const VPBasicBlock *VPBB); 454227825Stheraven 455227825Stheravenpublic: 456227825Stheraven VPSlotTracker(const VPlan *Plan = nullptr) { 457227825Stheraven if (Plan) 458227825Stheraven assignSlots(*Plan); 459232950Stheraven } 460227825Stheraven 461232950Stheraven unsigned getSlot(const VPValue *V) const { 462253159Stheraven auto I = Slots.find(V); 463227825Stheraven if (I == Slots.end()) 464241903Sdim return -1; 465227825Stheraven return I->second; 466241903Sdim } 467241903Sdim}; 468241903Sdim 469227825Stheraven} // namespace llvm 470227825Stheraven 471227825Stheraven#endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H 472227825Stheraven