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