CodeGenSchedule.h 23 KB

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