CodeGenSchedule.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. //===- CodeGenSchedule.h - Scheduling Machine Models ------------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines structures to encapsulate the machine model as described in
  11. // the target description.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #ifndef LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H
  15. #define LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H
  16. #include "llvm/ADT/DenseMap.h"
  17. #include "llvm/ADT/StringMap.h"
  18. #include "llvm/Support/ErrorHandling.h"
  19. #include "llvm/TableGen/Record.h"
  20. #include "llvm/TableGen/SetTheory.h"
  21. namespace llvm {
  22. class CodeGenTarget;
  23. class CodeGenSchedModels;
  24. class CodeGenInstruction;
  25. typedef std::vector<Record*> RecVec;
  26. typedef std::vector<Record*>::const_iterator RecIter;
  27. typedef std::vector<unsigned> IdxVec;
  28. typedef std::vector<unsigned>::const_iterator IdxIter;
  29. void splitSchedReadWrites(const RecVec &RWDefs,
  30. RecVec &WriteDefs, RecVec &ReadDefs);
  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 = 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, const IdxVec &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. IdxVec ProcIndices;
  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. CodeGenSchedClass(): Index(0), ItinClassDef(nullptr) {}
  127. bool isKeyEqual(Record *IC, const IdxVec &W, const IdxVec &R) {
  128. return ItinClassDef == IC && Writes == W && Reads == R;
  129. }
  130. // Is this class generated from a variants if existing classes? Instructions
  131. // are never mapped directly to inferred scheduling classes.
  132. bool isInferred() const { return !ItinClassDef; }
  133. #ifndef NDEBUG
  134. void dump(const CodeGenSchedModels *SchedModels) const;
  135. #endif
  136. };
  137. // Processor model.
  138. //
  139. // ModelName is a unique name used to name an instantiation of MCSchedModel.
  140. //
  141. // ModelDef is NULL for inferred Models. This happens when a processor defines
  142. // an itinerary but no machine model. If the processor defines neither a machine
  143. // model nor itinerary, then ModelDef remains pointing to NoModel. NoModel has
  144. // the special "NoModel" field set to true.
  145. //
  146. // ItinsDef always points to a valid record definition, but may point to the
  147. // default NoItineraries. NoItineraries has an empty list of InstrItinData
  148. // records.
  149. //
  150. // ItinDefList orders this processor's InstrItinData records by SchedClass idx.
  151. struct CodeGenProcModel {
  152. unsigned Index;
  153. std::string ModelName;
  154. Record *ModelDef;
  155. Record *ItinsDef;
  156. // Derived members...
  157. // Array of InstrItinData records indexed by a CodeGenSchedClass index.
  158. // This list is empty if the Processor has no value for Itineraries.
  159. // Initialized by collectProcItins().
  160. RecVec ItinDefList;
  161. // Map itinerary classes to per-operand resources.
  162. // This list is empty if no ItinRW refers to this Processor.
  163. RecVec ItinRWDefs;
  164. // All read/write resources associated with this processor.
  165. RecVec WriteResDefs;
  166. RecVec ReadAdvanceDefs;
  167. // Per-operand machine model resources associated with this processor.
  168. RecVec ProcResourceDefs;
  169. RecVec ProcResGroupDefs;
  170. CodeGenProcModel(unsigned Idx, const std::string &Name, Record *MDef,
  171. Record *IDef) :
  172. Index(Idx), ModelName(Name), ModelDef(MDef), ItinsDef(IDef) {}
  173. bool hasItineraries() const {
  174. return !ItinsDef->getValueAsListOfDefs("IID").empty();
  175. }
  176. bool hasInstrSchedModel() const {
  177. return !WriteResDefs.empty() || !ItinRWDefs.empty();
  178. }
  179. unsigned getProcResourceIdx(Record *PRDef) const;
  180. #ifndef NDEBUG
  181. void dump() const;
  182. #endif
  183. };
  184. /// Top level container for machine model data.
  185. class CodeGenSchedModels {
  186. RecordKeeper &Records;
  187. const CodeGenTarget &Target;
  188. // Map dag expressions to Instruction lists.
  189. SetTheory Sets;
  190. // List of unique processor models.
  191. std::vector<CodeGenProcModel> ProcModels;
  192. // Map Processor's MachineModel or ProcItin to a CodeGenProcModel index.
  193. typedef DenseMap<Record*, unsigned> ProcModelMapTy;
  194. ProcModelMapTy ProcModelMap;
  195. // Per-operand SchedReadWrite types.
  196. std::vector<CodeGenSchedRW> SchedWrites;
  197. std::vector<CodeGenSchedRW> SchedReads;
  198. // List of unique SchedClasses.
  199. std::vector<CodeGenSchedClass> SchedClasses;
  200. // Any inferred SchedClass has an index greater than NumInstrSchedClassses.
  201. unsigned NumInstrSchedClasses;
  202. // Map each instruction to its unique SchedClass index considering the
  203. // combination of it's itinerary class, SchedRW list, and InstRW records.
  204. typedef DenseMap<Record*, unsigned> InstClassMapTy;
  205. InstClassMapTy InstrClassMap;
  206. public:
  207. CodeGenSchedModels(RecordKeeper& RK, const CodeGenTarget &TGT);
  208. // iterator access to the scheduling classes.
  209. typedef std::vector<CodeGenSchedClass>::iterator class_iterator;
  210. typedef std::vector<CodeGenSchedClass>::const_iterator const_class_iterator;
  211. class_iterator classes_begin() { return SchedClasses.begin(); }
  212. const_class_iterator classes_begin() const { return SchedClasses.begin(); }
  213. class_iterator classes_end() { return SchedClasses.end(); }
  214. const_class_iterator classes_end() const { return SchedClasses.end(); }
  215. iterator_range<class_iterator> classes() {
  216. return iterator_range<class_iterator>(classes_begin(), classes_end());
  217. }
  218. iterator_range<const_class_iterator> classes() const {
  219. return iterator_range<const_class_iterator>(classes_begin(), classes_end());
  220. }
  221. iterator_range<class_iterator> explicit_classes() {
  222. return iterator_range<class_iterator>(
  223. classes_begin(), classes_begin() + NumInstrSchedClasses);
  224. }
  225. iterator_range<const_class_iterator> explicit_classes() const {
  226. return iterator_range<const_class_iterator>(
  227. classes_begin(), classes_begin() + NumInstrSchedClasses);
  228. }
  229. Record *getModelOrItinDef(Record *ProcDef) const {
  230. Record *ModelDef = ProcDef->getValueAsDef("SchedModel");
  231. Record *ItinsDef = ProcDef->getValueAsDef("ProcItin");
  232. if (!ItinsDef->getValueAsListOfDefs("IID").empty()) {
  233. assert(ModelDef->getValueAsBit("NoModel")
  234. && "Itineraries must be defined within SchedMachineModel");
  235. return ItinsDef;
  236. }
  237. return ModelDef;
  238. }
  239. const CodeGenProcModel &getModelForProc(Record *ProcDef) const {
  240. Record *ModelDef = getModelOrItinDef(ProcDef);
  241. ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
  242. assert(I != ProcModelMap.end() && "missing machine model");
  243. return ProcModels[I->second];
  244. }
  245. CodeGenProcModel &getProcModel(Record *ModelDef) {
  246. ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
  247. assert(I != ProcModelMap.end() && "missing machine model");
  248. return ProcModels[I->second];
  249. }
  250. const CodeGenProcModel &getProcModel(Record *ModelDef) const {
  251. return const_cast<CodeGenSchedModels*>(this)->getProcModel(ModelDef);
  252. }
  253. // Iterate over the unique processor models.
  254. typedef std::vector<CodeGenProcModel>::const_iterator ProcIter;
  255. ProcIter procModelBegin() const { return ProcModels.begin(); }
  256. ProcIter procModelEnd() const { return ProcModels.end(); }
  257. // Return true if any processors have itineraries.
  258. bool hasItineraries() const;
  259. // Get a SchedWrite from its index.
  260. const CodeGenSchedRW &getSchedWrite(unsigned Idx) const {
  261. assert(Idx < SchedWrites.size() && "bad SchedWrite index");
  262. assert(SchedWrites[Idx].isValid() && "invalid SchedWrite");
  263. return SchedWrites[Idx];
  264. }
  265. // Get a SchedWrite from its index.
  266. const CodeGenSchedRW &getSchedRead(unsigned Idx) const {
  267. assert(Idx < SchedReads.size() && "bad SchedRead index");
  268. assert(SchedReads[Idx].isValid() && "invalid SchedRead");
  269. return SchedReads[Idx];
  270. }
  271. const CodeGenSchedRW &getSchedRW(unsigned Idx, bool IsRead) const {
  272. return IsRead ? getSchedRead(Idx) : getSchedWrite(Idx);
  273. }
  274. CodeGenSchedRW &getSchedRW(Record *Def) {
  275. bool IsRead = Def->isSubClassOf("SchedRead");
  276. unsigned Idx = getSchedRWIdx(Def, IsRead);
  277. return const_cast<CodeGenSchedRW&>(
  278. IsRead ? getSchedRead(Idx) : getSchedWrite(Idx));
  279. }
  280. const CodeGenSchedRW &getSchedRW(Record*Def) const {
  281. return const_cast<CodeGenSchedModels&>(*this).getSchedRW(Def);
  282. }
  283. unsigned getSchedRWIdx(Record *Def, bool IsRead, unsigned After = 0) const;
  284. // Return true if the given write record is referenced by a ReadAdvance.
  285. bool hasReadOfWrite(Record *WriteDef) const;
  286. // Get a SchedClass from its index.
  287. CodeGenSchedClass &getSchedClass(unsigned Idx) {
  288. assert(Idx < SchedClasses.size() && "bad SchedClass index");
  289. return SchedClasses[Idx];
  290. }
  291. const CodeGenSchedClass &getSchedClass(unsigned Idx) const {
  292. assert(Idx < SchedClasses.size() && "bad SchedClass index");
  293. return SchedClasses[Idx];
  294. }
  295. // Get the SchedClass index for an instruction. Instructions with no
  296. // itinerary, no SchedReadWrites, and no InstrReadWrites references return 0
  297. // for NoItinerary.
  298. unsigned getSchedClassIdx(const CodeGenInstruction &Inst) const;
  299. typedef std::vector<CodeGenSchedClass>::const_iterator SchedClassIter;
  300. SchedClassIter schedClassBegin() const { return SchedClasses.begin(); }
  301. SchedClassIter schedClassEnd() const { return SchedClasses.end(); }
  302. unsigned numInstrSchedClasses() const { return NumInstrSchedClasses; }
  303. void findRWs(const RecVec &RWDefs, IdxVec &Writes, IdxVec &Reads) const;
  304. void findRWs(const RecVec &RWDefs, IdxVec &RWs, bool IsRead) const;
  305. void expandRWSequence(unsigned RWIdx, IdxVec &RWSeq, bool IsRead) const;
  306. void expandRWSeqForProc(unsigned RWIdx, IdxVec &RWSeq, bool IsRead,
  307. const CodeGenProcModel &ProcModel) const;
  308. unsigned addSchedClass(Record *ItinDef, const IdxVec &OperWrites,
  309. const IdxVec &OperReads, const IdxVec &ProcIndices);
  310. unsigned findOrInsertRW(ArrayRef<unsigned> Seq, bool IsRead);
  311. unsigned findSchedClassIdx(Record *ItinClassDef,
  312. const IdxVec &Writes,
  313. const IdxVec &Reads) const;
  314. Record *findProcResUnits(Record *ProcResKind,
  315. const CodeGenProcModel &PM) const;
  316. private:
  317. void collectProcModels();
  318. // Initialize a new processor model if it is unique.
  319. void addProcModel(Record *ProcDef);
  320. void collectSchedRW();
  321. std::string genRWName(const IdxVec& Seq, bool IsRead);
  322. unsigned findRWForSequence(const IdxVec &Seq, bool IsRead);
  323. void collectSchedClasses();
  324. std::string createSchedClassName(Record *ItinClassDef,
  325. const IdxVec &OperWrites,
  326. const IdxVec &OperReads);
  327. std::string createSchedClassName(const RecVec &InstDefs);
  328. void createInstRWClass(Record *InstRWDef);
  329. void collectProcItins();
  330. void collectProcItinRW();
  331. void inferSchedClasses();
  332. void inferFromRW(const IdxVec &OperWrites, const IdxVec &OperReads,
  333. unsigned FromClassIdx, const IdxVec &ProcIndices);
  334. void inferFromItinClass(Record *ItinClassDef, unsigned FromClassIdx);
  335. void inferFromInstRWs(unsigned SCIdx);
  336. bool hasSuperGroup(RecVec &SubUnits, CodeGenProcModel &PM);
  337. void verifyProcResourceGroups(CodeGenProcModel &PM);
  338. void collectProcResources();
  339. void collectItinProcResources(Record *ItinClassDef);
  340. void collectRWResources(unsigned RWIdx, bool IsRead,
  341. const IdxVec &ProcIndices);
  342. void collectRWResources(const IdxVec &Writes, const IdxVec &Reads,
  343. const IdxVec &ProcIndices);
  344. void addProcResource(Record *ProcResourceKind, CodeGenProcModel &PM);
  345. void addWriteRes(Record *ProcWriteResDef, unsigned PIdx);
  346. void addReadAdvance(Record *ProcReadAdvanceDef, unsigned PIdx);
  347. };
  348. } // namespace llvm
  349. #endif