1*0fca6ea1SDimitry Andric //===- CodeGenSchedule.h - Scheduling Machine Models ------------*- C++ -*-===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // This file defines structures to encapsulate the machine model as described in 10*0fca6ea1SDimitry Andric // the target description. 11*0fca6ea1SDimitry Andric // 12*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 13*0fca6ea1SDimitry Andric 14*0fca6ea1SDimitry Andric #ifndef LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H 15*0fca6ea1SDimitry Andric #define LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H 16*0fca6ea1SDimitry Andric 17*0fca6ea1SDimitry Andric #include "llvm/ADT/APInt.h" 18*0fca6ea1SDimitry Andric #include "llvm/ADT/ArrayRef.h" 19*0fca6ea1SDimitry Andric #include "llvm/ADT/DenseMap.h" 20*0fca6ea1SDimitry Andric #include "llvm/ADT/DenseSet.h" 21*0fca6ea1SDimitry Andric #include "llvm/ADT/STLExtras.h" 22*0fca6ea1SDimitry Andric #include "llvm/ADT/StringRef.h" 23*0fca6ea1SDimitry Andric #include "llvm/TableGen/Record.h" 24*0fca6ea1SDimitry Andric #include "llvm/TableGen/SetTheory.h" 25*0fca6ea1SDimitry Andric #include <cassert> 26*0fca6ea1SDimitry Andric #include <string> 27*0fca6ea1SDimitry Andric #include <utility> 28*0fca6ea1SDimitry Andric #include <vector> 29*0fca6ea1SDimitry Andric 30*0fca6ea1SDimitry Andric namespace llvm { 31*0fca6ea1SDimitry Andric 32*0fca6ea1SDimitry Andric class CodeGenTarget; 33*0fca6ea1SDimitry Andric class CodeGenSchedModels; 34*0fca6ea1SDimitry Andric class CodeGenInstruction; 35*0fca6ea1SDimitry Andric 36*0fca6ea1SDimitry Andric using RecVec = std::vector<Record *>; 37*0fca6ea1SDimitry Andric using RecIter = std::vector<Record *>::const_iterator; 38*0fca6ea1SDimitry Andric 39*0fca6ea1SDimitry Andric using IdxVec = std::vector<unsigned>; 40*0fca6ea1SDimitry Andric using IdxIter = std::vector<unsigned>::const_iterator; 41*0fca6ea1SDimitry Andric 42*0fca6ea1SDimitry Andric /// We have two kinds of SchedReadWrites. Explicitly defined and inferred 43*0fca6ea1SDimitry Andric /// sequences. TheDef is nonnull for explicit SchedWrites, but Sequence may or 44*0fca6ea1SDimitry Andric /// may not be empty. TheDef is null for inferred sequences, and Sequence must 45*0fca6ea1SDimitry Andric /// be nonempty. 46*0fca6ea1SDimitry Andric /// 47*0fca6ea1SDimitry Andric /// IsVariadic controls whether the variants are expanded into multiple operands 48*0fca6ea1SDimitry Andric /// or a sequence of writes on one operand. 49*0fca6ea1SDimitry Andric struct CodeGenSchedRW { 50*0fca6ea1SDimitry Andric unsigned Index; 51*0fca6ea1SDimitry Andric std::string Name; 52*0fca6ea1SDimitry Andric Record *TheDef; 53*0fca6ea1SDimitry Andric bool IsRead; 54*0fca6ea1SDimitry Andric bool IsAlias; 55*0fca6ea1SDimitry Andric bool HasVariants; 56*0fca6ea1SDimitry Andric bool IsVariadic; 57*0fca6ea1SDimitry Andric bool IsSequence; 58*0fca6ea1SDimitry Andric IdxVec Sequence; 59*0fca6ea1SDimitry Andric RecVec Aliases; 60*0fca6ea1SDimitry Andric 61*0fca6ea1SDimitry Andric CodeGenSchedRW() 62*0fca6ea1SDimitry Andric : Index(0), TheDef(nullptr), IsRead(false), IsAlias(false), 63*0fca6ea1SDimitry Andric HasVariants(false), IsVariadic(false), IsSequence(false) {} 64*0fca6ea1SDimitry Andric CodeGenSchedRW(unsigned Idx, Record *Def) 65*0fca6ea1SDimitry Andric : Index(Idx), TheDef(Def), IsAlias(false), IsVariadic(false) { 66*0fca6ea1SDimitry Andric Name = std::string(Def->getName()); 67*0fca6ea1SDimitry Andric IsRead = Def->isSubClassOf("SchedRead"); 68*0fca6ea1SDimitry Andric HasVariants = Def->isSubClassOf("SchedVariant"); 69*0fca6ea1SDimitry Andric if (HasVariants) 70*0fca6ea1SDimitry Andric IsVariadic = Def->getValueAsBit("Variadic"); 71*0fca6ea1SDimitry Andric 72*0fca6ea1SDimitry Andric // Read records don't currently have sequences, but it can be easily 73*0fca6ea1SDimitry Andric // added. Note that implicit Reads (from ReadVariant) may have a Sequence 74*0fca6ea1SDimitry Andric // (but no record). 75*0fca6ea1SDimitry Andric IsSequence = Def->isSubClassOf("WriteSequence"); 76*0fca6ea1SDimitry Andric } 77*0fca6ea1SDimitry Andric 78*0fca6ea1SDimitry Andric CodeGenSchedRW(unsigned Idx, bool Read, ArrayRef<unsigned> Seq, 79*0fca6ea1SDimitry Andric const std::string &Name) 80*0fca6ea1SDimitry Andric : Index(Idx), Name(Name), TheDef(nullptr), IsRead(Read), IsAlias(false), 81*0fca6ea1SDimitry Andric HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) { 82*0fca6ea1SDimitry Andric assert(Sequence.size() > 1 && "implied sequence needs >1 RWs"); 83*0fca6ea1SDimitry Andric } 84*0fca6ea1SDimitry Andric 85*0fca6ea1SDimitry Andric bool isValid() const { 86*0fca6ea1SDimitry Andric assert((!HasVariants || TheDef) && "Variant write needs record def"); 87*0fca6ea1SDimitry Andric assert((!IsVariadic || HasVariants) && "Variadic write needs variants"); 88*0fca6ea1SDimitry Andric assert((!IsSequence || !HasVariants) && "Sequence can't have variant"); 89*0fca6ea1SDimitry Andric assert((!IsSequence || !Sequence.empty()) && "Sequence should be nonempty"); 90*0fca6ea1SDimitry Andric assert((!IsAlias || Aliases.empty()) && "Alias cannot have aliases"); 91*0fca6ea1SDimitry Andric return TheDef || !Sequence.empty(); 92*0fca6ea1SDimitry Andric } 93*0fca6ea1SDimitry Andric 94*0fca6ea1SDimitry Andric #ifndef NDEBUG 95*0fca6ea1SDimitry Andric void dump() const; 96*0fca6ea1SDimitry Andric #endif 97*0fca6ea1SDimitry Andric }; 98*0fca6ea1SDimitry Andric 99*0fca6ea1SDimitry Andric /// Represent a transition between SchedClasses induced by SchedVariant. 100*0fca6ea1SDimitry Andric struct CodeGenSchedTransition { 101*0fca6ea1SDimitry Andric unsigned ToClassIdx; 102*0fca6ea1SDimitry Andric unsigned ProcIndex; 103*0fca6ea1SDimitry Andric RecVec PredTerm; 104*0fca6ea1SDimitry Andric }; 105*0fca6ea1SDimitry Andric 106*0fca6ea1SDimitry Andric /// Scheduling class. 107*0fca6ea1SDimitry Andric /// 108*0fca6ea1SDimitry Andric /// Each instruction description will be mapped to a scheduling class. There are 109*0fca6ea1SDimitry Andric /// four types of classes: 110*0fca6ea1SDimitry Andric /// 111*0fca6ea1SDimitry Andric /// 1) An explicitly defined itinerary class with ItinClassDef set. 112*0fca6ea1SDimitry Andric /// Writes and ReadDefs are empty. ProcIndices contains 0 for any processor. 113*0fca6ea1SDimitry Andric /// 114*0fca6ea1SDimitry Andric /// 2) An implied class with a list of SchedWrites and SchedReads that are 115*0fca6ea1SDimitry Andric /// defined in an instruction definition and which are common across all 116*0fca6ea1SDimitry Andric /// subtargets. ProcIndices contains 0 for any processor. 117*0fca6ea1SDimitry Andric /// 118*0fca6ea1SDimitry Andric /// 3) An implied class with a list of InstRW records that map instructions to 119*0fca6ea1SDimitry Andric /// SchedWrites and SchedReads per-processor. InstrClassMap should map the same 120*0fca6ea1SDimitry Andric /// instructions to this class. ProcIndices contains all the processors that 121*0fca6ea1SDimitry Andric /// provided InstrRW records for this class. ItinClassDef or Writes/Reads may 122*0fca6ea1SDimitry Andric /// still be defined for processors with no InstRW entry. 123*0fca6ea1SDimitry Andric /// 124*0fca6ea1SDimitry Andric /// 4) An inferred class represents a variant of another class that may be 125*0fca6ea1SDimitry Andric /// resolved at runtime. ProcIndices contains the set of processors that may 126*0fca6ea1SDimitry Andric /// require the class. ProcIndices are propagated through SchedClasses as 127*0fca6ea1SDimitry Andric /// variants are expanded. Multiple SchedClasses may be inferred from an 128*0fca6ea1SDimitry Andric /// itinerary class. Each inherits the processor index from the ItinRW record 129*0fca6ea1SDimitry Andric /// that mapped the itinerary class to the variant Writes or Reads. 130*0fca6ea1SDimitry Andric struct CodeGenSchedClass { 131*0fca6ea1SDimitry Andric unsigned Index; 132*0fca6ea1SDimitry Andric std::string Name; 133*0fca6ea1SDimitry Andric Record *ItinClassDef; 134*0fca6ea1SDimitry Andric 135*0fca6ea1SDimitry Andric IdxVec Writes; 136*0fca6ea1SDimitry Andric IdxVec Reads; 137*0fca6ea1SDimitry Andric // Sorted list of ProcIdx, where ProcIdx==0 implies any processor. 138*0fca6ea1SDimitry Andric IdxVec ProcIndices; 139*0fca6ea1SDimitry Andric 140*0fca6ea1SDimitry Andric std::vector<CodeGenSchedTransition> Transitions; 141*0fca6ea1SDimitry Andric 142*0fca6ea1SDimitry Andric // InstRW records associated with this class. These records may refer to an 143*0fca6ea1SDimitry Andric // Instruction no longer mapped to this class by InstrClassMap. These 144*0fca6ea1SDimitry Andric // Instructions should be ignored by this class because they have been split 145*0fca6ea1SDimitry Andric // off to join another inferred class. 146*0fca6ea1SDimitry Andric RecVec InstRWs; 147*0fca6ea1SDimitry Andric // InstRWs processor indices. Filled in inferFromInstRWs 148*0fca6ea1SDimitry Andric DenseSet<unsigned> InstRWProcIndices; 149*0fca6ea1SDimitry Andric 150*0fca6ea1SDimitry Andric CodeGenSchedClass(unsigned Index, std::string Name, Record *ItinClassDef) 151*0fca6ea1SDimitry Andric : Index(Index), Name(std::move(Name)), ItinClassDef(ItinClassDef) {} 152*0fca6ea1SDimitry Andric 153*0fca6ea1SDimitry Andric bool isKeyEqual(Record *IC, ArrayRef<unsigned> W, 154*0fca6ea1SDimitry Andric ArrayRef<unsigned> R) const { 155*0fca6ea1SDimitry Andric return ItinClassDef == IC && ArrayRef(Writes) == W && ArrayRef(Reads) == R; 156*0fca6ea1SDimitry Andric } 157*0fca6ea1SDimitry Andric 158*0fca6ea1SDimitry Andric // Is this class generated from a variants if existing classes? Instructions 159*0fca6ea1SDimitry Andric // are never mapped directly to inferred scheduling classes. 160*0fca6ea1SDimitry Andric bool isInferred() const { return !ItinClassDef; } 161*0fca6ea1SDimitry Andric 162*0fca6ea1SDimitry Andric #ifndef NDEBUG 163*0fca6ea1SDimitry Andric void dump(const CodeGenSchedModels *SchedModels) const; 164*0fca6ea1SDimitry Andric #endif 165*0fca6ea1SDimitry Andric }; 166*0fca6ea1SDimitry Andric 167*0fca6ea1SDimitry Andric /// Represent the cost of allocating a register of register class RCDef. 168*0fca6ea1SDimitry Andric /// 169*0fca6ea1SDimitry Andric /// The cost of allocating a register is equivalent to the number of physical 170*0fca6ea1SDimitry Andric /// registers used by the register renamer. Register costs are defined at 171*0fca6ea1SDimitry Andric /// register class granularity. 172*0fca6ea1SDimitry Andric struct CodeGenRegisterCost { 173*0fca6ea1SDimitry Andric Record *RCDef; 174*0fca6ea1SDimitry Andric unsigned Cost; 175*0fca6ea1SDimitry Andric bool AllowMoveElimination; 176*0fca6ea1SDimitry Andric CodeGenRegisterCost(Record *RC, unsigned RegisterCost, 177*0fca6ea1SDimitry Andric bool AllowMoveElim = false) 178*0fca6ea1SDimitry Andric : RCDef(RC), Cost(RegisterCost), AllowMoveElimination(AllowMoveElim) {} 179*0fca6ea1SDimitry Andric CodeGenRegisterCost(const CodeGenRegisterCost &) = default; 180*0fca6ea1SDimitry Andric CodeGenRegisterCost &operator=(const CodeGenRegisterCost &) = delete; 181*0fca6ea1SDimitry Andric }; 182*0fca6ea1SDimitry Andric 183*0fca6ea1SDimitry Andric /// A processor register file. 184*0fca6ea1SDimitry Andric /// 185*0fca6ea1SDimitry Andric /// This class describes a processor register file. Register file information is 186*0fca6ea1SDimitry Andric /// currently consumed by external tools like llvm-mca to predict dispatch 187*0fca6ea1SDimitry Andric /// stalls due to register pressure. 188*0fca6ea1SDimitry Andric struct CodeGenRegisterFile { 189*0fca6ea1SDimitry Andric std::string Name; 190*0fca6ea1SDimitry Andric Record *RegisterFileDef; 191*0fca6ea1SDimitry Andric unsigned MaxMovesEliminatedPerCycle; 192*0fca6ea1SDimitry Andric bool AllowZeroMoveEliminationOnly; 193*0fca6ea1SDimitry Andric 194*0fca6ea1SDimitry Andric unsigned NumPhysRegs; 195*0fca6ea1SDimitry Andric std::vector<CodeGenRegisterCost> Costs; 196*0fca6ea1SDimitry Andric 197*0fca6ea1SDimitry Andric CodeGenRegisterFile(StringRef name, Record *def, 198*0fca6ea1SDimitry Andric unsigned MaxMoveElimPerCy = 0, 199*0fca6ea1SDimitry Andric bool AllowZeroMoveElimOnly = false) 200*0fca6ea1SDimitry Andric : Name(name), RegisterFileDef(def), 201*0fca6ea1SDimitry Andric MaxMovesEliminatedPerCycle(MaxMoveElimPerCy), 202*0fca6ea1SDimitry Andric AllowZeroMoveEliminationOnly(AllowZeroMoveElimOnly), NumPhysRegs(0) {} 203*0fca6ea1SDimitry Andric 204*0fca6ea1SDimitry Andric bool hasDefaultCosts() const { return Costs.empty(); } 205*0fca6ea1SDimitry Andric }; 206*0fca6ea1SDimitry Andric 207*0fca6ea1SDimitry Andric // Processor model. 208*0fca6ea1SDimitry Andric // 209*0fca6ea1SDimitry Andric // ModelName is a unique name used to name an instantiation of MCSchedModel. 210*0fca6ea1SDimitry Andric // 211*0fca6ea1SDimitry Andric // ModelDef is NULL for inferred Models. This happens when a processor defines 212*0fca6ea1SDimitry Andric // an itinerary but no machine model. If the processor defines neither a machine 213*0fca6ea1SDimitry Andric // model nor itinerary, then ModelDef remains pointing to NoModel. NoModel has 214*0fca6ea1SDimitry Andric // the special "NoModel" field set to true. 215*0fca6ea1SDimitry Andric // 216*0fca6ea1SDimitry Andric // ItinsDef always points to a valid record definition, but may point to the 217*0fca6ea1SDimitry Andric // default NoItineraries. NoItineraries has an empty list of InstrItinData 218*0fca6ea1SDimitry Andric // records. 219*0fca6ea1SDimitry Andric // 220*0fca6ea1SDimitry Andric // ItinDefList orders this processor's InstrItinData records by SchedClass idx. 221*0fca6ea1SDimitry Andric struct CodeGenProcModel { 222*0fca6ea1SDimitry Andric unsigned Index; 223*0fca6ea1SDimitry Andric std::string ModelName; 224*0fca6ea1SDimitry Andric Record *ModelDef; 225*0fca6ea1SDimitry Andric Record *ItinsDef; 226*0fca6ea1SDimitry Andric 227*0fca6ea1SDimitry Andric // Derived members... 228*0fca6ea1SDimitry Andric 229*0fca6ea1SDimitry Andric // Array of InstrItinData records indexed by a CodeGenSchedClass index. 230*0fca6ea1SDimitry Andric // This list is empty if the Processor has no value for Itineraries. 231*0fca6ea1SDimitry Andric // Initialized by collectProcItins(). 232*0fca6ea1SDimitry Andric RecVec ItinDefList; 233*0fca6ea1SDimitry Andric 234*0fca6ea1SDimitry Andric // Map itinerary classes to per-operand resources. 235*0fca6ea1SDimitry Andric // This list is empty if no ItinRW refers to this Processor. 236*0fca6ea1SDimitry Andric RecVec ItinRWDefs; 237*0fca6ea1SDimitry Andric 238*0fca6ea1SDimitry Andric // List of unsupported feature. 239*0fca6ea1SDimitry Andric // This list is empty if the Processor has no UnsupportedFeatures. 240*0fca6ea1SDimitry Andric RecVec UnsupportedFeaturesDefs; 241*0fca6ea1SDimitry Andric 242*0fca6ea1SDimitry Andric // All read/write resources associated with this processor. 243*0fca6ea1SDimitry Andric RecVec WriteResDefs; 244*0fca6ea1SDimitry Andric RecVec ReadAdvanceDefs; 245*0fca6ea1SDimitry Andric 246*0fca6ea1SDimitry Andric // Per-operand machine model resources associated with this processor. 247*0fca6ea1SDimitry Andric RecVec ProcResourceDefs; 248*0fca6ea1SDimitry Andric 249*0fca6ea1SDimitry Andric // List of Register Files. 250*0fca6ea1SDimitry Andric std::vector<CodeGenRegisterFile> RegisterFiles; 251*0fca6ea1SDimitry Andric 252*0fca6ea1SDimitry Andric // Optional Retire Control Unit definition. 253*0fca6ea1SDimitry Andric Record *RetireControlUnit; 254*0fca6ea1SDimitry Andric 255*0fca6ea1SDimitry Andric // Load/Store queue descriptors. 256*0fca6ea1SDimitry Andric Record *LoadQueue; 257*0fca6ea1SDimitry Andric Record *StoreQueue; 258*0fca6ea1SDimitry Andric 259*0fca6ea1SDimitry Andric CodeGenProcModel(unsigned Idx, std::string Name, Record *MDef, Record *IDef) 260*0fca6ea1SDimitry Andric : Index(Idx), ModelName(std::move(Name)), ModelDef(MDef), ItinsDef(IDef), 261*0fca6ea1SDimitry Andric RetireControlUnit(nullptr), LoadQueue(nullptr), StoreQueue(nullptr) {} 262*0fca6ea1SDimitry Andric 263*0fca6ea1SDimitry Andric bool hasItineraries() const { 264*0fca6ea1SDimitry Andric return !ItinsDef->getValueAsListOfDefs("IID").empty(); 265*0fca6ea1SDimitry Andric } 266*0fca6ea1SDimitry Andric 267*0fca6ea1SDimitry Andric bool hasInstrSchedModel() const { 268*0fca6ea1SDimitry Andric return !WriteResDefs.empty() || !ItinRWDefs.empty(); 269*0fca6ea1SDimitry Andric } 270*0fca6ea1SDimitry Andric 271*0fca6ea1SDimitry Andric bool hasExtraProcessorInfo() const { 272*0fca6ea1SDimitry Andric return RetireControlUnit || LoadQueue || StoreQueue || 273*0fca6ea1SDimitry Andric !RegisterFiles.empty(); 274*0fca6ea1SDimitry Andric } 275*0fca6ea1SDimitry Andric 276*0fca6ea1SDimitry Andric unsigned getProcResourceIdx(Record *PRDef) const; 277*0fca6ea1SDimitry Andric 278*0fca6ea1SDimitry Andric bool isUnsupported(const CodeGenInstruction &Inst) const; 279*0fca6ea1SDimitry Andric 280*0fca6ea1SDimitry Andric // Return true if the given write record is referenced by a ReadAdvance. 281*0fca6ea1SDimitry Andric bool hasReadOfWrite(Record *WriteDef) const; 282*0fca6ea1SDimitry Andric 283*0fca6ea1SDimitry Andric #ifndef NDEBUG 284*0fca6ea1SDimitry Andric void dump() const; 285*0fca6ea1SDimitry Andric #endif 286*0fca6ea1SDimitry Andric }; 287*0fca6ea1SDimitry Andric 288*0fca6ea1SDimitry Andric /// Used to correlate instructions to MCInstPredicates specified by 289*0fca6ea1SDimitry Andric /// InstructionEquivalentClass tablegen definitions. 290*0fca6ea1SDimitry Andric /// 291*0fca6ea1SDimitry Andric /// Example: a XOR of a register with self, is a known zero-idiom for most 292*0fca6ea1SDimitry Andric /// X86 processors. 293*0fca6ea1SDimitry Andric /// 294*0fca6ea1SDimitry Andric /// Each processor can use a (potentially different) InstructionEquivalenceClass 295*0fca6ea1SDimitry Andric /// definition to classify zero-idioms. That means, XORrr is likely to appear 296*0fca6ea1SDimitry Andric /// in more than one equivalence class (where each class definition is 297*0fca6ea1SDimitry Andric /// contributed by a different processor). 298*0fca6ea1SDimitry Andric /// 299*0fca6ea1SDimitry Andric /// There is no guarantee that the same MCInstPredicate will be used to describe 300*0fca6ea1SDimitry Andric /// equivalence classes that identify XORrr as a zero-idiom. 301*0fca6ea1SDimitry Andric /// 302*0fca6ea1SDimitry Andric /// To be more specific, the requirements for being a zero-idiom XORrr may be 303*0fca6ea1SDimitry Andric /// different for different processors. 304*0fca6ea1SDimitry Andric /// 305*0fca6ea1SDimitry Andric /// Class PredicateInfo identifies a subset of processors that specify the same 306*0fca6ea1SDimitry Andric /// requirements (i.e. same MCInstPredicate and OperandMask) for an instruction 307*0fca6ea1SDimitry Andric /// opcode. 308*0fca6ea1SDimitry Andric /// 309*0fca6ea1SDimitry Andric /// Back to the example. Field `ProcModelMask` will have one bit set for every 310*0fca6ea1SDimitry Andric /// processor model that sees XORrr as a zero-idiom, and that specifies the same 311*0fca6ea1SDimitry Andric /// set of constraints. 312*0fca6ea1SDimitry Andric /// 313*0fca6ea1SDimitry Andric /// By construction, there can be multiple instances of PredicateInfo associated 314*0fca6ea1SDimitry Andric /// with a same instruction opcode. For example, different processors may define 315*0fca6ea1SDimitry Andric /// different constraints on the same opcode. 316*0fca6ea1SDimitry Andric /// 317*0fca6ea1SDimitry Andric /// Field OperandMask can be used as an extra constraint. 318*0fca6ea1SDimitry Andric /// It may be used to describe conditions that appy only to a subset of the 319*0fca6ea1SDimitry Andric /// operands of a machine instruction, and the operands subset may not be the 320*0fca6ea1SDimitry Andric /// same for all processor models. 321*0fca6ea1SDimitry Andric struct PredicateInfo { 322*0fca6ea1SDimitry Andric llvm::APInt ProcModelMask; // A set of processor model indices. 323*0fca6ea1SDimitry Andric llvm::APInt OperandMask; // An operand mask. 324*0fca6ea1SDimitry Andric const Record *Predicate; // MCInstrPredicate definition. 325*0fca6ea1SDimitry Andric PredicateInfo(llvm::APInt CpuMask, llvm::APInt Operands, const Record *Pred) 326*0fca6ea1SDimitry Andric : ProcModelMask(CpuMask), OperandMask(Operands), Predicate(Pred) {} 327*0fca6ea1SDimitry Andric 328*0fca6ea1SDimitry Andric bool operator==(const PredicateInfo &Other) const { 329*0fca6ea1SDimitry Andric return ProcModelMask == Other.ProcModelMask && 330*0fca6ea1SDimitry Andric OperandMask == Other.OperandMask && Predicate == Other.Predicate; 331*0fca6ea1SDimitry Andric } 332*0fca6ea1SDimitry Andric }; 333*0fca6ea1SDimitry Andric 334*0fca6ea1SDimitry Andric /// A collection of PredicateInfo objects. 335*0fca6ea1SDimitry Andric /// 336*0fca6ea1SDimitry Andric /// There is at least one OpcodeInfo object for every opcode specified by a 337*0fca6ea1SDimitry Andric /// TIPredicate definition. 338*0fca6ea1SDimitry Andric class OpcodeInfo { 339*0fca6ea1SDimitry Andric std::vector<PredicateInfo> Predicates; 340*0fca6ea1SDimitry Andric 341*0fca6ea1SDimitry Andric OpcodeInfo(const OpcodeInfo &Other) = delete; 342*0fca6ea1SDimitry Andric OpcodeInfo &operator=(const OpcodeInfo &Other) = delete; 343*0fca6ea1SDimitry Andric 344*0fca6ea1SDimitry Andric public: 345*0fca6ea1SDimitry Andric OpcodeInfo() = default; 346*0fca6ea1SDimitry Andric OpcodeInfo &operator=(OpcodeInfo &&Other) = default; 347*0fca6ea1SDimitry Andric OpcodeInfo(OpcodeInfo &&Other) = default; 348*0fca6ea1SDimitry Andric 349*0fca6ea1SDimitry Andric ArrayRef<PredicateInfo> getPredicates() const { return Predicates; } 350*0fca6ea1SDimitry Andric 351*0fca6ea1SDimitry Andric void addPredicateForProcModel(const llvm::APInt &CpuMask, 352*0fca6ea1SDimitry Andric const llvm::APInt &OperandMask, 353*0fca6ea1SDimitry Andric const Record *Predicate); 354*0fca6ea1SDimitry Andric }; 355*0fca6ea1SDimitry Andric 356*0fca6ea1SDimitry Andric /// Used to group together tablegen instruction definitions that are subject 357*0fca6ea1SDimitry Andric /// to a same set of constraints (identified by an instance of OpcodeInfo). 358*0fca6ea1SDimitry Andric class OpcodeGroup { 359*0fca6ea1SDimitry Andric OpcodeInfo Info; 360*0fca6ea1SDimitry Andric std::vector<const Record *> Opcodes; 361*0fca6ea1SDimitry Andric 362*0fca6ea1SDimitry Andric OpcodeGroup(const OpcodeGroup &Other) = delete; 363*0fca6ea1SDimitry Andric OpcodeGroup &operator=(const OpcodeGroup &Other) = delete; 364*0fca6ea1SDimitry Andric 365*0fca6ea1SDimitry Andric public: 366*0fca6ea1SDimitry Andric OpcodeGroup(OpcodeInfo &&OpInfo) : Info(std::move(OpInfo)) {} 367*0fca6ea1SDimitry Andric OpcodeGroup(OpcodeGroup &&Other) = default; 368*0fca6ea1SDimitry Andric 369*0fca6ea1SDimitry Andric void addOpcode(const Record *Opcode) { 370*0fca6ea1SDimitry Andric assert(!llvm::is_contained(Opcodes, Opcode) && "Opcode already in set!"); 371*0fca6ea1SDimitry Andric Opcodes.push_back(Opcode); 372*0fca6ea1SDimitry Andric } 373*0fca6ea1SDimitry Andric 374*0fca6ea1SDimitry Andric ArrayRef<const Record *> getOpcodes() const { return Opcodes; } 375*0fca6ea1SDimitry Andric const OpcodeInfo &getOpcodeInfo() const { return Info; } 376*0fca6ea1SDimitry Andric }; 377*0fca6ea1SDimitry Andric 378*0fca6ea1SDimitry Andric /// An STIPredicateFunction descriptor used by tablegen backends to 379*0fca6ea1SDimitry Andric /// auto-generate the body of a predicate function as a member of tablegen'd 380*0fca6ea1SDimitry Andric /// class XXXGenSubtargetInfo. 381*0fca6ea1SDimitry Andric class STIPredicateFunction { 382*0fca6ea1SDimitry Andric const Record *FunctionDeclaration; 383*0fca6ea1SDimitry Andric 384*0fca6ea1SDimitry Andric std::vector<const Record *> Definitions; 385*0fca6ea1SDimitry Andric std::vector<OpcodeGroup> Groups; 386*0fca6ea1SDimitry Andric 387*0fca6ea1SDimitry Andric STIPredicateFunction(const STIPredicateFunction &Other) = delete; 388*0fca6ea1SDimitry Andric STIPredicateFunction &operator=(const STIPredicateFunction &Other) = delete; 389*0fca6ea1SDimitry Andric 390*0fca6ea1SDimitry Andric public: 391*0fca6ea1SDimitry Andric STIPredicateFunction(const Record *Rec) : FunctionDeclaration(Rec) {} 392*0fca6ea1SDimitry Andric STIPredicateFunction(STIPredicateFunction &&Other) = default; 393*0fca6ea1SDimitry Andric 394*0fca6ea1SDimitry Andric bool isCompatibleWith(const STIPredicateFunction &Other) const { 395*0fca6ea1SDimitry Andric return FunctionDeclaration == Other.FunctionDeclaration; 396*0fca6ea1SDimitry Andric } 397*0fca6ea1SDimitry Andric 398*0fca6ea1SDimitry Andric void addDefinition(const Record *Def) { Definitions.push_back(Def); } 399*0fca6ea1SDimitry Andric void addOpcode(const Record *OpcodeRec, OpcodeInfo &&Info) { 400*0fca6ea1SDimitry Andric if (Groups.empty() || 401*0fca6ea1SDimitry Andric Groups.back().getOpcodeInfo().getPredicates() != Info.getPredicates()) 402*0fca6ea1SDimitry Andric Groups.emplace_back(std::move(Info)); 403*0fca6ea1SDimitry Andric Groups.back().addOpcode(OpcodeRec); 404*0fca6ea1SDimitry Andric } 405*0fca6ea1SDimitry Andric 406*0fca6ea1SDimitry Andric StringRef getName() const { 407*0fca6ea1SDimitry Andric return FunctionDeclaration->getValueAsString("Name"); 408*0fca6ea1SDimitry Andric } 409*0fca6ea1SDimitry Andric const Record *getDefaultReturnPredicate() const { 410*0fca6ea1SDimitry Andric return FunctionDeclaration->getValueAsDef("DefaultReturnValue"); 411*0fca6ea1SDimitry Andric } 412*0fca6ea1SDimitry Andric 413*0fca6ea1SDimitry Andric const Record *getDeclaration() const { return FunctionDeclaration; } 414*0fca6ea1SDimitry Andric ArrayRef<const Record *> getDefinitions() const { return Definitions; } 415*0fca6ea1SDimitry Andric ArrayRef<OpcodeGroup> getGroups() const { return Groups; } 416*0fca6ea1SDimitry Andric }; 417*0fca6ea1SDimitry Andric 418*0fca6ea1SDimitry Andric using ProcModelMapTy = DenseMap<const Record *, unsigned>; 419*0fca6ea1SDimitry Andric 420*0fca6ea1SDimitry Andric /// Top level container for machine model data. 421*0fca6ea1SDimitry Andric class CodeGenSchedModels { 422*0fca6ea1SDimitry Andric RecordKeeper &Records; 423*0fca6ea1SDimitry Andric const CodeGenTarget &Target; 424*0fca6ea1SDimitry Andric 425*0fca6ea1SDimitry Andric // Map dag expressions to Instruction lists. 426*0fca6ea1SDimitry Andric SetTheory Sets; 427*0fca6ea1SDimitry Andric 428*0fca6ea1SDimitry Andric // List of unique processor models. 429*0fca6ea1SDimitry Andric std::vector<CodeGenProcModel> ProcModels; 430*0fca6ea1SDimitry Andric 431*0fca6ea1SDimitry Andric // Map Processor's MachineModel or ProcItin to a CodeGenProcModel index. 432*0fca6ea1SDimitry Andric ProcModelMapTy ProcModelMap; 433*0fca6ea1SDimitry Andric 434*0fca6ea1SDimitry Andric // Per-operand SchedReadWrite types. 435*0fca6ea1SDimitry Andric std::vector<CodeGenSchedRW> SchedWrites; 436*0fca6ea1SDimitry Andric std::vector<CodeGenSchedRW> SchedReads; 437*0fca6ea1SDimitry Andric 438*0fca6ea1SDimitry Andric // List of unique SchedClasses. 439*0fca6ea1SDimitry Andric std::vector<CodeGenSchedClass> SchedClasses; 440*0fca6ea1SDimitry Andric 441*0fca6ea1SDimitry Andric // Any inferred SchedClass has an index greater than NumInstrSchedClassses. 442*0fca6ea1SDimitry Andric unsigned NumInstrSchedClasses; 443*0fca6ea1SDimitry Andric 444*0fca6ea1SDimitry Andric RecVec ProcResourceDefs; 445*0fca6ea1SDimitry Andric RecVec ProcResGroups; 446*0fca6ea1SDimitry Andric 447*0fca6ea1SDimitry Andric // Map each instruction to its unique SchedClass index considering the 448*0fca6ea1SDimitry Andric // combination of it's itinerary class, SchedRW list, and InstRW records. 449*0fca6ea1SDimitry Andric using InstClassMapTy = DenseMap<Record *, unsigned>; 450*0fca6ea1SDimitry Andric InstClassMapTy InstrClassMap; 451*0fca6ea1SDimitry Andric 452*0fca6ea1SDimitry Andric std::vector<STIPredicateFunction> STIPredicates; 453*0fca6ea1SDimitry Andric std::vector<unsigned> getAllProcIndices() const; 454*0fca6ea1SDimitry Andric 455*0fca6ea1SDimitry Andric public: 456*0fca6ea1SDimitry Andric CodeGenSchedModels(RecordKeeper &RK, const CodeGenTarget &TGT); 457*0fca6ea1SDimitry Andric 458*0fca6ea1SDimitry Andric // iterator access to the scheduling classes. 459*0fca6ea1SDimitry Andric using class_iterator = std::vector<CodeGenSchedClass>::iterator; 460*0fca6ea1SDimitry Andric using const_class_iterator = std::vector<CodeGenSchedClass>::const_iterator; 461*0fca6ea1SDimitry Andric class_iterator classes_begin() { return SchedClasses.begin(); } 462*0fca6ea1SDimitry Andric const_class_iterator classes_begin() const { return SchedClasses.begin(); } 463*0fca6ea1SDimitry Andric class_iterator classes_end() { return SchedClasses.end(); } 464*0fca6ea1SDimitry Andric const_class_iterator classes_end() const { return SchedClasses.end(); } 465*0fca6ea1SDimitry Andric iterator_range<class_iterator> classes() { 466*0fca6ea1SDimitry Andric return make_range(classes_begin(), classes_end()); 467*0fca6ea1SDimitry Andric } 468*0fca6ea1SDimitry Andric iterator_range<const_class_iterator> classes() const { 469*0fca6ea1SDimitry Andric return make_range(classes_begin(), classes_end()); 470*0fca6ea1SDimitry Andric } 471*0fca6ea1SDimitry Andric iterator_range<class_iterator> explicit_classes() { 472*0fca6ea1SDimitry Andric return make_range(classes_begin(), classes_begin() + NumInstrSchedClasses); 473*0fca6ea1SDimitry Andric } 474*0fca6ea1SDimitry Andric iterator_range<const_class_iterator> explicit_classes() const { 475*0fca6ea1SDimitry Andric return make_range(classes_begin(), classes_begin() + NumInstrSchedClasses); 476*0fca6ea1SDimitry Andric } 477*0fca6ea1SDimitry Andric 478*0fca6ea1SDimitry Andric Record *getModelOrItinDef(Record *ProcDef) const { 479*0fca6ea1SDimitry Andric Record *ModelDef = ProcDef->getValueAsDef("SchedModel"); 480*0fca6ea1SDimitry Andric Record *ItinsDef = ProcDef->getValueAsDef("ProcItin"); 481*0fca6ea1SDimitry Andric if (!ItinsDef->getValueAsListOfDefs("IID").empty()) { 482*0fca6ea1SDimitry Andric assert(ModelDef->getValueAsBit("NoModel") && 483*0fca6ea1SDimitry Andric "Itineraries must be defined within SchedMachineModel"); 484*0fca6ea1SDimitry Andric return ItinsDef; 485*0fca6ea1SDimitry Andric } 486*0fca6ea1SDimitry Andric return ModelDef; 487*0fca6ea1SDimitry Andric } 488*0fca6ea1SDimitry Andric 489*0fca6ea1SDimitry Andric const CodeGenProcModel &getModelForProc(Record *ProcDef) const { 490*0fca6ea1SDimitry Andric Record *ModelDef = getModelOrItinDef(ProcDef); 491*0fca6ea1SDimitry Andric ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef); 492*0fca6ea1SDimitry Andric assert(I != ProcModelMap.end() && "missing machine model"); 493*0fca6ea1SDimitry Andric return ProcModels[I->second]; 494*0fca6ea1SDimitry Andric } 495*0fca6ea1SDimitry Andric 496*0fca6ea1SDimitry Andric CodeGenProcModel &getProcModel(Record *ModelDef) { 497*0fca6ea1SDimitry Andric ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef); 498*0fca6ea1SDimitry Andric assert(I != ProcModelMap.end() && "missing machine model"); 499*0fca6ea1SDimitry Andric return ProcModels[I->second]; 500*0fca6ea1SDimitry Andric } 501*0fca6ea1SDimitry Andric const CodeGenProcModel &getProcModel(Record *ModelDef) const { 502*0fca6ea1SDimitry Andric return const_cast<CodeGenSchedModels *>(this)->getProcModel(ModelDef); 503*0fca6ea1SDimitry Andric } 504*0fca6ea1SDimitry Andric 505*0fca6ea1SDimitry Andric // Iterate over the unique processor models. 506*0fca6ea1SDimitry Andric using ProcIter = std::vector<CodeGenProcModel>::const_iterator; 507*0fca6ea1SDimitry Andric ProcIter procModelBegin() const { return ProcModels.begin(); } 508*0fca6ea1SDimitry Andric ProcIter procModelEnd() const { return ProcModels.end(); } 509*0fca6ea1SDimitry Andric ArrayRef<CodeGenProcModel> procModels() const { return ProcModels; } 510*0fca6ea1SDimitry Andric 511*0fca6ea1SDimitry Andric // Return true if any processors have itineraries. 512*0fca6ea1SDimitry Andric bool hasItineraries() const; 513*0fca6ea1SDimitry Andric 514*0fca6ea1SDimitry Andric // Get a SchedWrite from its index. 515*0fca6ea1SDimitry Andric const CodeGenSchedRW &getSchedWrite(unsigned Idx) const { 516*0fca6ea1SDimitry Andric assert(Idx < SchedWrites.size() && "bad SchedWrite index"); 517*0fca6ea1SDimitry Andric assert(SchedWrites[Idx].isValid() && "invalid SchedWrite"); 518*0fca6ea1SDimitry Andric return SchedWrites[Idx]; 519*0fca6ea1SDimitry Andric } 520*0fca6ea1SDimitry Andric // Get a SchedWrite from its index. 521*0fca6ea1SDimitry Andric const CodeGenSchedRW &getSchedRead(unsigned Idx) const { 522*0fca6ea1SDimitry Andric assert(Idx < SchedReads.size() && "bad SchedRead index"); 523*0fca6ea1SDimitry Andric assert(SchedReads[Idx].isValid() && "invalid SchedRead"); 524*0fca6ea1SDimitry Andric return SchedReads[Idx]; 525*0fca6ea1SDimitry Andric } 526*0fca6ea1SDimitry Andric 527*0fca6ea1SDimitry Andric const CodeGenSchedRW &getSchedRW(unsigned Idx, bool IsRead) const { 528*0fca6ea1SDimitry Andric return IsRead ? getSchedRead(Idx) : getSchedWrite(Idx); 529*0fca6ea1SDimitry Andric } 530*0fca6ea1SDimitry Andric CodeGenSchedRW &getSchedRW(Record *Def) { 531*0fca6ea1SDimitry Andric bool IsRead = Def->isSubClassOf("SchedRead"); 532*0fca6ea1SDimitry Andric unsigned Idx = getSchedRWIdx(Def, IsRead); 533*0fca6ea1SDimitry Andric return const_cast<CodeGenSchedRW &>(IsRead ? getSchedRead(Idx) 534*0fca6ea1SDimitry Andric : getSchedWrite(Idx)); 535*0fca6ea1SDimitry Andric } 536*0fca6ea1SDimitry Andric const CodeGenSchedRW &getSchedRW(Record *Def) const { 537*0fca6ea1SDimitry Andric return const_cast<CodeGenSchedModels &>(*this).getSchedRW(Def); 538*0fca6ea1SDimitry Andric } 539*0fca6ea1SDimitry Andric 540*0fca6ea1SDimitry Andric unsigned getSchedRWIdx(const Record *Def, bool IsRead) const; 541*0fca6ea1SDimitry Andric 542*0fca6ea1SDimitry Andric // Get a SchedClass from its index. 543*0fca6ea1SDimitry Andric CodeGenSchedClass &getSchedClass(unsigned Idx) { 544*0fca6ea1SDimitry Andric assert(Idx < SchedClasses.size() && "bad SchedClass index"); 545*0fca6ea1SDimitry Andric return SchedClasses[Idx]; 546*0fca6ea1SDimitry Andric } 547*0fca6ea1SDimitry Andric const CodeGenSchedClass &getSchedClass(unsigned Idx) const { 548*0fca6ea1SDimitry Andric assert(Idx < SchedClasses.size() && "bad SchedClass index"); 549*0fca6ea1SDimitry Andric return SchedClasses[Idx]; 550*0fca6ea1SDimitry Andric } 551*0fca6ea1SDimitry Andric 552*0fca6ea1SDimitry Andric // Get the SchedClass index for an instruction. Instructions with no 553*0fca6ea1SDimitry Andric // itinerary, no SchedReadWrites, and no InstrReadWrites references return 0 554*0fca6ea1SDimitry Andric // for NoItinerary. 555*0fca6ea1SDimitry Andric unsigned getSchedClassIdx(const CodeGenInstruction &Inst) const; 556*0fca6ea1SDimitry Andric 557*0fca6ea1SDimitry Andric using SchedClassIter = std::vector<CodeGenSchedClass>::const_iterator; 558*0fca6ea1SDimitry Andric SchedClassIter schedClassBegin() const { return SchedClasses.begin(); } 559*0fca6ea1SDimitry Andric SchedClassIter schedClassEnd() const { return SchedClasses.end(); } 560*0fca6ea1SDimitry Andric ArrayRef<CodeGenSchedClass> schedClasses() const { return SchedClasses; } 561*0fca6ea1SDimitry Andric 562*0fca6ea1SDimitry Andric unsigned numInstrSchedClasses() const { return NumInstrSchedClasses; } 563*0fca6ea1SDimitry Andric 564*0fca6ea1SDimitry Andric void findRWs(const RecVec &RWDefs, IdxVec &Writes, IdxVec &Reads) const; 565*0fca6ea1SDimitry Andric void findRWs(const RecVec &RWDefs, IdxVec &RWs, bool IsRead) const; 566*0fca6ea1SDimitry Andric void expandRWSequence(unsigned RWIdx, IdxVec &RWSeq, bool IsRead) const; 567*0fca6ea1SDimitry Andric void expandRWSeqForProc(unsigned RWIdx, IdxVec &RWSeq, bool IsRead, 568*0fca6ea1SDimitry Andric const CodeGenProcModel &ProcModel) const; 569*0fca6ea1SDimitry Andric 570*0fca6ea1SDimitry Andric unsigned addSchedClass(Record *ItinDef, ArrayRef<unsigned> OperWrites, 571*0fca6ea1SDimitry Andric ArrayRef<unsigned> OperReads, 572*0fca6ea1SDimitry Andric ArrayRef<unsigned> ProcIndices); 573*0fca6ea1SDimitry Andric 574*0fca6ea1SDimitry Andric unsigned findOrInsertRW(ArrayRef<unsigned> Seq, bool IsRead); 575*0fca6ea1SDimitry Andric 576*0fca6ea1SDimitry Andric Record *findProcResUnits(Record *ProcResKind, const CodeGenProcModel &PM, 577*0fca6ea1SDimitry Andric ArrayRef<SMLoc> Loc) const; 578*0fca6ea1SDimitry Andric 579*0fca6ea1SDimitry Andric ArrayRef<STIPredicateFunction> getSTIPredicates() const { 580*0fca6ea1SDimitry Andric return STIPredicates; 581*0fca6ea1SDimitry Andric } 582*0fca6ea1SDimitry Andric 583*0fca6ea1SDimitry Andric private: 584*0fca6ea1SDimitry Andric void collectProcModels(); 585*0fca6ea1SDimitry Andric 586*0fca6ea1SDimitry Andric // Initialize a new processor model if it is unique. 587*0fca6ea1SDimitry Andric void addProcModel(Record *ProcDef); 588*0fca6ea1SDimitry Andric 589*0fca6ea1SDimitry Andric void collectSchedRW(); 590*0fca6ea1SDimitry Andric 591*0fca6ea1SDimitry Andric std::string genRWName(ArrayRef<unsigned> Seq, bool IsRead); 592*0fca6ea1SDimitry Andric unsigned findRWForSequence(ArrayRef<unsigned> Seq, bool IsRead); 593*0fca6ea1SDimitry Andric 594*0fca6ea1SDimitry Andric void collectSchedClasses(); 595*0fca6ea1SDimitry Andric 596*0fca6ea1SDimitry Andric void collectRetireControlUnits(); 597*0fca6ea1SDimitry Andric 598*0fca6ea1SDimitry Andric void collectRegisterFiles(); 599*0fca6ea1SDimitry Andric 600*0fca6ea1SDimitry Andric void collectOptionalProcessorInfo(); 601*0fca6ea1SDimitry Andric 602*0fca6ea1SDimitry Andric std::string createSchedClassName(Record *ItinClassDef, 603*0fca6ea1SDimitry Andric ArrayRef<unsigned> OperWrites, 604*0fca6ea1SDimitry Andric ArrayRef<unsigned> OperReads); 605*0fca6ea1SDimitry Andric std::string createSchedClassName(const RecVec &InstDefs); 606*0fca6ea1SDimitry Andric void createInstRWClass(Record *InstRWDef); 607*0fca6ea1SDimitry Andric 608*0fca6ea1SDimitry Andric void collectProcItins(); 609*0fca6ea1SDimitry Andric 610*0fca6ea1SDimitry Andric void collectProcItinRW(); 611*0fca6ea1SDimitry Andric 612*0fca6ea1SDimitry Andric void collectProcUnsupportedFeatures(); 613*0fca6ea1SDimitry Andric 614*0fca6ea1SDimitry Andric void inferSchedClasses(); 615*0fca6ea1SDimitry Andric 616*0fca6ea1SDimitry Andric void checkMCInstPredicates() const; 617*0fca6ea1SDimitry Andric 618*0fca6ea1SDimitry Andric void checkSTIPredicates() const; 619*0fca6ea1SDimitry Andric 620*0fca6ea1SDimitry Andric void collectSTIPredicates(); 621*0fca6ea1SDimitry Andric 622*0fca6ea1SDimitry Andric void collectLoadStoreQueueInfo(); 623*0fca6ea1SDimitry Andric 624*0fca6ea1SDimitry Andric void checkCompleteness(); 625*0fca6ea1SDimitry Andric 626*0fca6ea1SDimitry Andric void inferFromRW(ArrayRef<unsigned> OperWrites, ArrayRef<unsigned> OperReads, 627*0fca6ea1SDimitry Andric unsigned FromClassIdx, ArrayRef<unsigned> ProcIndices); 628*0fca6ea1SDimitry Andric void inferFromItinClass(Record *ItinClassDef, unsigned FromClassIdx); 629*0fca6ea1SDimitry Andric void inferFromInstRWs(unsigned SCIdx); 630*0fca6ea1SDimitry Andric 631*0fca6ea1SDimitry Andric bool hasSuperGroup(RecVec &SubUnits, CodeGenProcModel &PM); 632*0fca6ea1SDimitry Andric void verifyProcResourceGroups(CodeGenProcModel &PM); 633*0fca6ea1SDimitry Andric 634*0fca6ea1SDimitry Andric void collectProcResources(); 635*0fca6ea1SDimitry Andric 636*0fca6ea1SDimitry Andric void collectItinProcResources(Record *ItinClassDef); 637*0fca6ea1SDimitry Andric 638*0fca6ea1SDimitry Andric void collectRWResources(unsigned RWIdx, bool IsRead, 639*0fca6ea1SDimitry Andric ArrayRef<unsigned> ProcIndices); 640*0fca6ea1SDimitry Andric 641*0fca6ea1SDimitry Andric void collectRWResources(ArrayRef<unsigned> Writes, ArrayRef<unsigned> Reads, 642*0fca6ea1SDimitry Andric ArrayRef<unsigned> ProcIndices); 643*0fca6ea1SDimitry Andric 644*0fca6ea1SDimitry Andric void addProcResource(Record *ProcResourceKind, CodeGenProcModel &PM, 645*0fca6ea1SDimitry Andric ArrayRef<SMLoc> Loc); 646*0fca6ea1SDimitry Andric 647*0fca6ea1SDimitry Andric void addWriteRes(Record *ProcWriteResDef, unsigned PIdx); 648*0fca6ea1SDimitry Andric 649*0fca6ea1SDimitry Andric void addReadAdvance(Record *ProcReadAdvanceDef, unsigned PIdx); 650*0fca6ea1SDimitry Andric }; 651*0fca6ea1SDimitry Andric 652*0fca6ea1SDimitry Andric } // namespace llvm 653*0fca6ea1SDimitry Andric 654*0fca6ea1SDimitry Andric #endif 655