CodeGenSchedule.h 23 KB

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