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