CodeGenSchedule.h 23 KB

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