1*0b57cec5SDimitry Andric //===- DFAPacketizerEmitter.cpp - Packetization DFA for a VLIW machine ----===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This class parses the Schedule.td file and produces an API that can be used
10*0b57cec5SDimitry Andric // to reason about whether an instruction can be added to a packet on a VLIW
11*0b57cec5SDimitry Andric // architecture. The class internally generates a deterministic finite
12*0b57cec5SDimitry Andric // automaton (DFA) that models all possible mappings of machine instructions
13*0b57cec5SDimitry Andric // to functional units as instructions are added to a packet.
14*0b57cec5SDimitry Andric //
15*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
16*0b57cec5SDimitry Andric 
17*0b57cec5SDimitry Andric #define DEBUG_TYPE "dfa-emitter"
18*0b57cec5SDimitry Andric 
19*0b57cec5SDimitry Andric #include "CodeGenTarget.h"
20*0b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
21*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
22*0b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
23*0b57cec5SDimitry Andric #include "llvm/TableGen/Record.h"
24*0b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
25*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
26*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
27*0b57cec5SDimitry Andric #include <cassert>
28*0b57cec5SDimitry Andric #include <cstdint>
29*0b57cec5SDimitry Andric #include <map>
30*0b57cec5SDimitry Andric #include <set>
31*0b57cec5SDimitry Andric #include <string>
32*0b57cec5SDimitry Andric #include <vector>
33*0b57cec5SDimitry Andric 
34*0b57cec5SDimitry Andric using namespace llvm;
35*0b57cec5SDimitry Andric 
36*0b57cec5SDimitry Andric // --------------------------------------------------------------------
37*0b57cec5SDimitry Andric // Definitions shared between DFAPacketizer.cpp and DFAPacketizerEmitter.cpp
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric // DFA_MAX_RESTERMS * DFA_MAX_RESOURCES must fit within sizeof DFAInput.
40*0b57cec5SDimitry Andric // This is verified in DFAPacketizer.cpp:DFAPacketizer::DFAPacketizer.
41*0b57cec5SDimitry Andric //
42*0b57cec5SDimitry Andric // e.g. terms x resource bit combinations that fit in uint32_t:
43*0b57cec5SDimitry Andric //      4 terms x 8  bits = 32 bits
44*0b57cec5SDimitry Andric //      3 terms x 10 bits = 30 bits
45*0b57cec5SDimitry Andric //      2 terms x 16 bits = 32 bits
46*0b57cec5SDimitry Andric //
47*0b57cec5SDimitry Andric // e.g. terms x resource bit combinations that fit in uint64_t:
48*0b57cec5SDimitry Andric //      8 terms x 8  bits = 64 bits
49*0b57cec5SDimitry Andric //      7 terms x 9  bits = 63 bits
50*0b57cec5SDimitry Andric //      6 terms x 10 bits = 60 bits
51*0b57cec5SDimitry Andric //      5 terms x 12 bits = 60 bits
52*0b57cec5SDimitry Andric //      4 terms x 16 bits = 64 bits <--- current
53*0b57cec5SDimitry Andric //      3 terms x 21 bits = 63 bits
54*0b57cec5SDimitry Andric //      2 terms x 32 bits = 64 bits
55*0b57cec5SDimitry Andric //
56*0b57cec5SDimitry Andric #define DFA_MAX_RESTERMS        4   // The max # of AND'ed resource terms.
57*0b57cec5SDimitry Andric #define DFA_MAX_RESOURCES       16  // The max # of resource bits in one term.
58*0b57cec5SDimitry Andric 
59*0b57cec5SDimitry Andric typedef uint64_t                DFAInput;
60*0b57cec5SDimitry Andric typedef int64_t                 DFAStateInput;
61*0b57cec5SDimitry Andric #define DFA_TBLTYPE             "int64_t" // For generating DFAStateInputTable.
62*0b57cec5SDimitry Andric 
63*0b57cec5SDimitry Andric namespace {
64*0b57cec5SDimitry Andric 
65*0b57cec5SDimitry Andric   DFAInput addDFAFuncUnits(DFAInput Inp, unsigned FuncUnits) {
66*0b57cec5SDimitry Andric     return (Inp << DFA_MAX_RESOURCES) | FuncUnits;
67*0b57cec5SDimitry Andric   }
68*0b57cec5SDimitry Andric 
69*0b57cec5SDimitry Andric   /// Return the DFAInput for an instruction class input vector.
70*0b57cec5SDimitry Andric   /// This function is used in both DFAPacketizer.cpp and in
71*0b57cec5SDimitry Andric   /// DFAPacketizerEmitter.cpp.
72*0b57cec5SDimitry Andric   DFAInput getDFAInsnInput(const std::vector<unsigned> &InsnClass) {
73*0b57cec5SDimitry Andric     DFAInput InsnInput = 0;
74*0b57cec5SDimitry Andric     assert((InsnClass.size() <= DFA_MAX_RESTERMS) &&
75*0b57cec5SDimitry Andric            "Exceeded maximum number of DFA terms");
76*0b57cec5SDimitry Andric     for (auto U : InsnClass)
77*0b57cec5SDimitry Andric       InsnInput = addDFAFuncUnits(InsnInput, U);
78*0b57cec5SDimitry Andric     return InsnInput;
79*0b57cec5SDimitry Andric   }
80*0b57cec5SDimitry Andric 
81*0b57cec5SDimitry Andric } // end anonymous namespace
82*0b57cec5SDimitry Andric 
83*0b57cec5SDimitry Andric // --------------------------------------------------------------------
84*0b57cec5SDimitry Andric 
85*0b57cec5SDimitry Andric #ifndef NDEBUG
86*0b57cec5SDimitry Andric // To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter".
87*0b57cec5SDimitry Andric //
88*0b57cec5SDimitry Andric // dbgsInsnClass - When debugging, print instruction class stages.
89*0b57cec5SDimitry Andric //
90*0b57cec5SDimitry Andric void dbgsInsnClass(const std::vector<unsigned> &InsnClass);
91*0b57cec5SDimitry Andric //
92*0b57cec5SDimitry Andric // dbgsStateInfo - When debugging, print the set of state info.
93*0b57cec5SDimitry Andric //
94*0b57cec5SDimitry Andric void dbgsStateInfo(const std::set<unsigned> &stateInfo);
95*0b57cec5SDimitry Andric //
96*0b57cec5SDimitry Andric // dbgsIndent - When debugging, indent by the specified amount.
97*0b57cec5SDimitry Andric //
98*0b57cec5SDimitry Andric void dbgsIndent(unsigned indent);
99*0b57cec5SDimitry Andric #endif
100*0b57cec5SDimitry Andric 
101*0b57cec5SDimitry Andric //
102*0b57cec5SDimitry Andric // class DFAPacketizerEmitter: class that generates and prints out the DFA
103*0b57cec5SDimitry Andric // for resource tracking.
104*0b57cec5SDimitry Andric //
105*0b57cec5SDimitry Andric namespace {
106*0b57cec5SDimitry Andric 
107*0b57cec5SDimitry Andric class DFAPacketizerEmitter {
108*0b57cec5SDimitry Andric private:
109*0b57cec5SDimitry Andric   std::string TargetName;
110*0b57cec5SDimitry Andric   //
111*0b57cec5SDimitry Andric   // allInsnClasses is the set of all possible resources consumed by an
112*0b57cec5SDimitry Andric   // InstrStage.
113*0b57cec5SDimitry Andric   //
114*0b57cec5SDimitry Andric   std::vector<std::vector<unsigned>> allInsnClasses;
115*0b57cec5SDimitry Andric   RecordKeeper &Records;
116*0b57cec5SDimitry Andric 
117*0b57cec5SDimitry Andric public:
118*0b57cec5SDimitry Andric   DFAPacketizerEmitter(RecordKeeper &R);
119*0b57cec5SDimitry Andric 
120*0b57cec5SDimitry Andric   //
121*0b57cec5SDimitry Andric   // collectAllFuncUnits - Construct a map of function unit names to bits.
122*0b57cec5SDimitry Andric   //
123*0b57cec5SDimitry Andric   int collectAllFuncUnits(std::vector<Record*> &ProcItinList,
124*0b57cec5SDimitry Andric                            std::map<std::string, unsigned> &FUNameToBitsMap,
125*0b57cec5SDimitry Andric                            int &maxResources,
126*0b57cec5SDimitry Andric                            raw_ostream &OS);
127*0b57cec5SDimitry Andric 
128*0b57cec5SDimitry Andric   //
129*0b57cec5SDimitry Andric   // collectAllComboFuncs - Construct a map from a combo function unit bit to
130*0b57cec5SDimitry Andric   //                        the bits of all included functional units.
131*0b57cec5SDimitry Andric   //
132*0b57cec5SDimitry Andric   int collectAllComboFuncs(std::vector<Record*> &ComboFuncList,
133*0b57cec5SDimitry Andric                            std::map<std::string, unsigned> &FUNameToBitsMap,
134*0b57cec5SDimitry Andric                            std::map<unsigned, unsigned> &ComboBitToBitsMap,
135*0b57cec5SDimitry Andric                            raw_ostream &OS);
136*0b57cec5SDimitry Andric 
137*0b57cec5SDimitry Andric   //
138*0b57cec5SDimitry Andric   // collectOneInsnClass - Populate allInsnClasses with one instruction class.
139*0b57cec5SDimitry Andric   //
140*0b57cec5SDimitry Andric   int collectOneInsnClass(const std::string &ProcName,
141*0b57cec5SDimitry Andric                            std::vector<Record*> &ProcItinList,
142*0b57cec5SDimitry Andric                            std::map<std::string, unsigned> &FUNameToBitsMap,
143*0b57cec5SDimitry Andric                            Record *ItinData,
144*0b57cec5SDimitry Andric                            raw_ostream &OS);
145*0b57cec5SDimitry Andric 
146*0b57cec5SDimitry Andric   //
147*0b57cec5SDimitry Andric   // collectAllInsnClasses - Populate allInsnClasses which is a set of units
148*0b57cec5SDimitry Andric   // used in each stage.
149*0b57cec5SDimitry Andric   //
150*0b57cec5SDimitry Andric   int collectAllInsnClasses(const std::string &ProcName,
151*0b57cec5SDimitry Andric                            std::vector<Record*> &ProcItinList,
152*0b57cec5SDimitry Andric                            std::map<std::string, unsigned> &FUNameToBitsMap,
153*0b57cec5SDimitry Andric                            std::vector<Record*> &ItinDataList,
154*0b57cec5SDimitry Andric                            int &maxStages,
155*0b57cec5SDimitry Andric                            raw_ostream &OS);
156*0b57cec5SDimitry Andric 
157*0b57cec5SDimitry Andric   void run(raw_ostream &OS);
158*0b57cec5SDimitry Andric };
159*0b57cec5SDimitry Andric 
160*0b57cec5SDimitry Andric //
161*0b57cec5SDimitry Andric // State represents the usage of machine resources if the packet contains
162*0b57cec5SDimitry Andric // a set of instruction classes.
163*0b57cec5SDimitry Andric //
164*0b57cec5SDimitry Andric // Specifically, currentState is a set of bit-masks.
165*0b57cec5SDimitry Andric // The nth bit in a bit-mask indicates whether the nth resource is being used
166*0b57cec5SDimitry Andric // by this state. The set of bit-masks in a state represent the different
167*0b57cec5SDimitry Andric // possible outcomes of transitioning to this state.
168*0b57cec5SDimitry Andric // For example: consider a two resource architecture: resource L and resource M
169*0b57cec5SDimitry Andric // with three instruction classes: L, M, and L_or_M.
170*0b57cec5SDimitry Andric // From the initial state (currentState = 0x00), if we add instruction class
171*0b57cec5SDimitry Andric // L_or_M we will transition to a state with currentState = [0x01, 0x10]. This
172*0b57cec5SDimitry Andric // represents the possible resource states that can result from adding a L_or_M
173*0b57cec5SDimitry Andric // instruction
174*0b57cec5SDimitry Andric //
175*0b57cec5SDimitry Andric // Another way of thinking about this transition is we are mapping a NDFA with
176*0b57cec5SDimitry Andric // two states [0x01] and [0x10] into a DFA with a single state [0x01, 0x10].
177*0b57cec5SDimitry Andric //
178*0b57cec5SDimitry Andric // A State instance also contains a collection of transitions from that state:
179*0b57cec5SDimitry Andric // a map from inputs to new states.
180*0b57cec5SDimitry Andric //
181*0b57cec5SDimitry Andric class State {
182*0b57cec5SDimitry Andric  public:
183*0b57cec5SDimitry Andric   static int currentStateNum;
184*0b57cec5SDimitry Andric   // stateNum is the only member used for equality/ordering, all other members
185*0b57cec5SDimitry Andric   // can be mutated even in const State objects.
186*0b57cec5SDimitry Andric   const int stateNum;
187*0b57cec5SDimitry Andric   mutable bool isInitial;
188*0b57cec5SDimitry Andric   mutable std::set<unsigned> stateInfo;
189*0b57cec5SDimitry Andric   typedef std::map<std::vector<unsigned>, const State *> TransitionMap;
190*0b57cec5SDimitry Andric   mutable TransitionMap Transitions;
191*0b57cec5SDimitry Andric 
192*0b57cec5SDimitry Andric   State();
193*0b57cec5SDimitry Andric 
194*0b57cec5SDimitry Andric   bool operator<(const State &s) const {
195*0b57cec5SDimitry Andric     return stateNum < s.stateNum;
196*0b57cec5SDimitry Andric   }
197*0b57cec5SDimitry Andric 
198*0b57cec5SDimitry Andric   //
199*0b57cec5SDimitry Andric   // canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass
200*0b57cec5SDimitry Andric   // may be a valid transition from this state i.e., can an instruction of type
201*0b57cec5SDimitry Andric   // InsnClass be added to the packet represented by this state.
202*0b57cec5SDimitry Andric   //
203*0b57cec5SDimitry Andric   // Note that for multiple stages, this quick check does not take into account
204*0b57cec5SDimitry Andric   // any possible resource competition between the stages themselves.  That is
205*0b57cec5SDimitry Andric   // enforced in AddInsnClassStages which checks the cross product of all
206*0b57cec5SDimitry Andric   // stages for resource availability (which is a more involved check).
207*0b57cec5SDimitry Andric   //
208*0b57cec5SDimitry Andric   bool canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,
209*0b57cec5SDimitry Andric                         std::map<unsigned, unsigned> &ComboBitToBitsMap) const;
210*0b57cec5SDimitry Andric 
211*0b57cec5SDimitry Andric   //
212*0b57cec5SDimitry Andric   // AddInsnClass - Return all combinations of resource reservation
213*0b57cec5SDimitry Andric   // which are possible from this state (PossibleStates).
214*0b57cec5SDimitry Andric   //
215*0b57cec5SDimitry Andric   // PossibleStates is the set of valid resource states that ensue from valid
216*0b57cec5SDimitry Andric   // transitions.
217*0b57cec5SDimitry Andric   //
218*0b57cec5SDimitry Andric   void AddInsnClass(std::vector<unsigned> &InsnClass,
219*0b57cec5SDimitry Andric                         std::map<unsigned, unsigned> &ComboBitToBitsMap,
220*0b57cec5SDimitry Andric                         std::set<unsigned> &PossibleStates) const;
221*0b57cec5SDimitry Andric 
222*0b57cec5SDimitry Andric   //
223*0b57cec5SDimitry Andric   // AddInsnClassStages - Return all combinations of resource reservation
224*0b57cec5SDimitry Andric   // resulting from the cross product of all stages for this InsnClass
225*0b57cec5SDimitry Andric   // which are possible from this state (PossibleStates).
226*0b57cec5SDimitry Andric   //
227*0b57cec5SDimitry Andric   void AddInsnClassStages(std::vector<unsigned> &InsnClass,
228*0b57cec5SDimitry Andric                         std::map<unsigned, unsigned> &ComboBitToBitsMap,
229*0b57cec5SDimitry Andric                         unsigned chkstage, unsigned numstages,
230*0b57cec5SDimitry Andric                         unsigned prevState, unsigned origState,
231*0b57cec5SDimitry Andric                         DenseSet<unsigned> &VisitedResourceStates,
232*0b57cec5SDimitry Andric                         std::set<unsigned> &PossibleStates) const;
233*0b57cec5SDimitry Andric 
234*0b57cec5SDimitry Andric   //
235*0b57cec5SDimitry Andric   // addTransition - Add a transition from this state given the input InsnClass
236*0b57cec5SDimitry Andric   //
237*0b57cec5SDimitry Andric   void addTransition(std::vector<unsigned> InsnClass, const State *To) const;
238*0b57cec5SDimitry Andric 
239*0b57cec5SDimitry Andric   //
240*0b57cec5SDimitry Andric   // hasTransition - Returns true if there is a transition from this state
241*0b57cec5SDimitry Andric   // given the input InsnClass
242*0b57cec5SDimitry Andric   //
243*0b57cec5SDimitry Andric   bool hasTransition(std::vector<unsigned> InsnClass) const;
244*0b57cec5SDimitry Andric };
245*0b57cec5SDimitry Andric 
246*0b57cec5SDimitry Andric //
247*0b57cec5SDimitry Andric // class DFA: deterministic finite automaton for processor resource tracking.
248*0b57cec5SDimitry Andric //
249*0b57cec5SDimitry Andric class DFA {
250*0b57cec5SDimitry Andric public:
251*0b57cec5SDimitry Andric   DFA() = default;
252*0b57cec5SDimitry Andric 
253*0b57cec5SDimitry Andric   // Set of states. Need to keep this sorted to emit the transition table.
254*0b57cec5SDimitry Andric   typedef std::set<State> StateSet;
255*0b57cec5SDimitry Andric   StateSet states;
256*0b57cec5SDimitry Andric 
257*0b57cec5SDimitry Andric   State *currentState = nullptr;
258*0b57cec5SDimitry Andric 
259*0b57cec5SDimitry Andric   //
260*0b57cec5SDimitry Andric   // Modify the DFA.
261*0b57cec5SDimitry Andric   //
262*0b57cec5SDimitry Andric   const State &newState();
263*0b57cec5SDimitry Andric 
264*0b57cec5SDimitry Andric   //
265*0b57cec5SDimitry Andric   // writeTable: Print out a table representing the DFA.
266*0b57cec5SDimitry Andric   //
267*0b57cec5SDimitry Andric   void writeTableAndAPI(raw_ostream &OS, const std::string &ClassName,
268*0b57cec5SDimitry Andric                  int numInsnClasses = 0,
269*0b57cec5SDimitry Andric                  int maxResources = 0, int numCombos = 0, int maxStages = 0);
270*0b57cec5SDimitry Andric };
271*0b57cec5SDimitry Andric 
272*0b57cec5SDimitry Andric } // end anonymous namespace
273*0b57cec5SDimitry Andric 
274*0b57cec5SDimitry Andric #ifndef NDEBUG
275*0b57cec5SDimitry Andric // To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter".
276*0b57cec5SDimitry Andric //
277*0b57cec5SDimitry Andric // dbgsInsnClass - When debugging, print instruction class stages.
278*0b57cec5SDimitry Andric //
279*0b57cec5SDimitry Andric void dbgsInsnClass(const std::vector<unsigned> &InsnClass) {
280*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "InsnClass: ");
281*0b57cec5SDimitry Andric   for (unsigned i = 0; i < InsnClass.size(); ++i) {
282*0b57cec5SDimitry Andric     if (i > 0) {
283*0b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << ", ");
284*0b57cec5SDimitry Andric     }
285*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "0x" << Twine::utohexstr(InsnClass[i]));
286*0b57cec5SDimitry Andric   }
287*0b57cec5SDimitry Andric   DFAInput InsnInput = getDFAInsnInput(InsnClass);
288*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << " (input: 0x" << Twine::utohexstr(InsnInput) << ")");
289*0b57cec5SDimitry Andric }
290*0b57cec5SDimitry Andric 
291*0b57cec5SDimitry Andric //
292*0b57cec5SDimitry Andric // dbgsStateInfo - When debugging, print the set of state info.
293*0b57cec5SDimitry Andric //
294*0b57cec5SDimitry Andric void dbgsStateInfo(const std::set<unsigned> &stateInfo) {
295*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "StateInfo: ");
296*0b57cec5SDimitry Andric   unsigned i = 0;
297*0b57cec5SDimitry Andric   for (std::set<unsigned>::iterator SI = stateInfo.begin();
298*0b57cec5SDimitry Andric        SI != stateInfo.end(); ++SI, ++i) {
299*0b57cec5SDimitry Andric     unsigned thisState = *SI;
300*0b57cec5SDimitry Andric     if (i > 0) {
301*0b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << ", ");
302*0b57cec5SDimitry Andric     }
303*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "0x" << Twine::utohexstr(thisState));
304*0b57cec5SDimitry Andric   }
305*0b57cec5SDimitry Andric }
306*0b57cec5SDimitry Andric 
307*0b57cec5SDimitry Andric //
308*0b57cec5SDimitry Andric // dbgsIndent - When debugging, indent by the specified amount.
309*0b57cec5SDimitry Andric //
310*0b57cec5SDimitry Andric void dbgsIndent(unsigned indent) {
311*0b57cec5SDimitry Andric   for (unsigned i = 0; i < indent; ++i) {
312*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << " ");
313*0b57cec5SDimitry Andric   }
314*0b57cec5SDimitry Andric }
315*0b57cec5SDimitry Andric #endif // NDEBUG
316*0b57cec5SDimitry Andric 
317*0b57cec5SDimitry Andric //
318*0b57cec5SDimitry Andric // Constructors and destructors for State and DFA
319*0b57cec5SDimitry Andric //
320*0b57cec5SDimitry Andric State::State() :
321*0b57cec5SDimitry Andric   stateNum(currentStateNum++), isInitial(false) {}
322*0b57cec5SDimitry Andric 
323*0b57cec5SDimitry Andric //
324*0b57cec5SDimitry Andric // addTransition - Add a transition from this state given the input InsnClass
325*0b57cec5SDimitry Andric //
326*0b57cec5SDimitry Andric void State::addTransition(std::vector<unsigned> InsnClass, const State *To)
327*0b57cec5SDimitry Andric       const {
328*0b57cec5SDimitry Andric   assert(!Transitions.count(InsnClass) &&
329*0b57cec5SDimitry Andric       "Cannot have multiple transitions for the same input");
330*0b57cec5SDimitry Andric   Transitions[InsnClass] = To;
331*0b57cec5SDimitry Andric }
332*0b57cec5SDimitry Andric 
333*0b57cec5SDimitry Andric //
334*0b57cec5SDimitry Andric // hasTransition - Returns true if there is a transition from this state
335*0b57cec5SDimitry Andric // given the input InsnClass
336*0b57cec5SDimitry Andric //
337*0b57cec5SDimitry Andric bool State::hasTransition(std::vector<unsigned> InsnClass) const {
338*0b57cec5SDimitry Andric   return Transitions.count(InsnClass) > 0;
339*0b57cec5SDimitry Andric }
340*0b57cec5SDimitry Andric 
341*0b57cec5SDimitry Andric //
342*0b57cec5SDimitry Andric // AddInsnClass - Return all combinations of resource reservation
343*0b57cec5SDimitry Andric // which are possible from this state (PossibleStates).
344*0b57cec5SDimitry Andric //
345*0b57cec5SDimitry Andric // PossibleStates is the set of valid resource states that ensue from valid
346*0b57cec5SDimitry Andric // transitions.
347*0b57cec5SDimitry Andric //
348*0b57cec5SDimitry Andric void State::AddInsnClass(std::vector<unsigned> &InsnClass,
349*0b57cec5SDimitry Andric                         std::map<unsigned, unsigned> &ComboBitToBitsMap,
350*0b57cec5SDimitry Andric                         std::set<unsigned> &PossibleStates) const {
351*0b57cec5SDimitry Andric   //
352*0b57cec5SDimitry Andric   // Iterate over all resource states in currentState.
353*0b57cec5SDimitry Andric   //
354*0b57cec5SDimitry Andric   unsigned numstages = InsnClass.size();
355*0b57cec5SDimitry Andric   assert((numstages > 0) && "InsnClass has no stages");
356*0b57cec5SDimitry Andric 
357*0b57cec5SDimitry Andric   for (std::set<unsigned>::iterator SI = stateInfo.begin();
358*0b57cec5SDimitry Andric        SI != stateInfo.end(); ++SI) {
359*0b57cec5SDimitry Andric     unsigned thisState = *SI;
360*0b57cec5SDimitry Andric 
361*0b57cec5SDimitry Andric     DenseSet<unsigned> VisitedResourceStates;
362*0b57cec5SDimitry Andric 
363*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "  thisState: 0x" << Twine::utohexstr(thisState)
364*0b57cec5SDimitry Andric                       << "\n");
365*0b57cec5SDimitry Andric     AddInsnClassStages(InsnClass, ComboBitToBitsMap,
366*0b57cec5SDimitry Andric                                 numstages - 1, numstages,
367*0b57cec5SDimitry Andric                                 thisState, thisState,
368*0b57cec5SDimitry Andric                                 VisitedResourceStates, PossibleStates);
369*0b57cec5SDimitry Andric   }
370*0b57cec5SDimitry Andric }
371*0b57cec5SDimitry Andric 
372*0b57cec5SDimitry Andric void State::AddInsnClassStages(std::vector<unsigned> &InsnClass,
373*0b57cec5SDimitry Andric                         std::map<unsigned, unsigned> &ComboBitToBitsMap,
374*0b57cec5SDimitry Andric                         unsigned chkstage, unsigned numstages,
375*0b57cec5SDimitry Andric                         unsigned prevState, unsigned origState,
376*0b57cec5SDimitry Andric                         DenseSet<unsigned> &VisitedResourceStates,
377*0b57cec5SDimitry Andric                         std::set<unsigned> &PossibleStates) const {
378*0b57cec5SDimitry Andric   assert((chkstage < numstages) && "AddInsnClassStages: stage out of range");
379*0b57cec5SDimitry Andric   unsigned thisStage = InsnClass[chkstage];
380*0b57cec5SDimitry Andric 
381*0b57cec5SDimitry Andric   LLVM_DEBUG({
382*0b57cec5SDimitry Andric     dbgsIndent((1 + numstages - chkstage) << 1);
383*0b57cec5SDimitry Andric     dbgs() << "AddInsnClassStages " << chkstage << " (0x"
384*0b57cec5SDimitry Andric            << Twine::utohexstr(thisStage) << ") from ";
385*0b57cec5SDimitry Andric     dbgsInsnClass(InsnClass);
386*0b57cec5SDimitry Andric     dbgs() << "\n";
387*0b57cec5SDimitry Andric   });
388*0b57cec5SDimitry Andric 
389*0b57cec5SDimitry Andric   //
390*0b57cec5SDimitry Andric   // Iterate over all possible resources used in thisStage.
391*0b57cec5SDimitry Andric   // For ex: for thisStage = 0x11, all resources = {0x01, 0x10}.
392*0b57cec5SDimitry Andric   //
393*0b57cec5SDimitry Andric   for (unsigned int j = 0; j < DFA_MAX_RESOURCES; ++j) {
394*0b57cec5SDimitry Andric     unsigned resourceMask = (0x1 << j);
395*0b57cec5SDimitry Andric     if (resourceMask & thisStage) {
396*0b57cec5SDimitry Andric       unsigned combo = ComboBitToBitsMap[resourceMask];
397*0b57cec5SDimitry Andric       if (combo && ((~prevState & combo) != combo)) {
398*0b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "\tSkipped Add 0x" << Twine::utohexstr(prevState)
399*0b57cec5SDimitry Andric                           << " - combo op 0x" << Twine::utohexstr(resourceMask)
400*0b57cec5SDimitry Andric                           << " (0x" << Twine::utohexstr(combo)
401*0b57cec5SDimitry Andric                           << ") cannot be scheduled\n");
402*0b57cec5SDimitry Andric         continue;
403*0b57cec5SDimitry Andric       }
404*0b57cec5SDimitry Andric       //
405*0b57cec5SDimitry Andric       // For each possible resource used in thisStage, generate the
406*0b57cec5SDimitry Andric       // resource state if that resource was used.
407*0b57cec5SDimitry Andric       //
408*0b57cec5SDimitry Andric       unsigned ResultingResourceState = prevState | resourceMask | combo;
409*0b57cec5SDimitry Andric       LLVM_DEBUG({
410*0b57cec5SDimitry Andric         dbgsIndent((2 + numstages - chkstage) << 1);
411*0b57cec5SDimitry Andric         dbgs() << "0x" << Twine::utohexstr(prevState) << " | 0x"
412*0b57cec5SDimitry Andric                << Twine::utohexstr(resourceMask);
413*0b57cec5SDimitry Andric         if (combo)
414*0b57cec5SDimitry Andric           dbgs() << " | 0x" << Twine::utohexstr(combo);
415*0b57cec5SDimitry Andric         dbgs() << " = 0x" << Twine::utohexstr(ResultingResourceState) << " ";
416*0b57cec5SDimitry Andric       });
417*0b57cec5SDimitry Andric 
418*0b57cec5SDimitry Andric       //
419*0b57cec5SDimitry Andric       // If this is the final stage for this class
420*0b57cec5SDimitry Andric       //
421*0b57cec5SDimitry Andric       if (chkstage == 0) {
422*0b57cec5SDimitry Andric         //
423*0b57cec5SDimitry Andric         // Check if the resulting resource state can be accommodated in this
424*0b57cec5SDimitry Andric         // packet.
425*0b57cec5SDimitry Andric         // We compute resource OR prevState (originally started as origState).
426*0b57cec5SDimitry Andric         // If the result of the OR is different than origState, it implies
427*0b57cec5SDimitry Andric         // that there is at least one resource that can be used to schedule
428*0b57cec5SDimitry Andric         // thisStage in the current packet.
429*0b57cec5SDimitry Andric         // Insert ResultingResourceState into PossibleStates only if we haven't
430*0b57cec5SDimitry Andric         // processed ResultingResourceState before.
431*0b57cec5SDimitry Andric         //
432*0b57cec5SDimitry Andric         if (ResultingResourceState != prevState) {
433*0b57cec5SDimitry Andric           if (VisitedResourceStates.count(ResultingResourceState) == 0) {
434*0b57cec5SDimitry Andric             VisitedResourceStates.insert(ResultingResourceState);
435*0b57cec5SDimitry Andric             PossibleStates.insert(ResultingResourceState);
436*0b57cec5SDimitry Andric             LLVM_DEBUG(dbgs()
437*0b57cec5SDimitry Andric                        << "\tResultingResourceState: 0x"
438*0b57cec5SDimitry Andric                        << Twine::utohexstr(ResultingResourceState) << "\n");
439*0b57cec5SDimitry Andric           } else {
440*0b57cec5SDimitry Andric             LLVM_DEBUG(dbgs() << "\tSkipped Add - state already seen\n");
441*0b57cec5SDimitry Andric           }
442*0b57cec5SDimitry Andric         } else {
443*0b57cec5SDimitry Andric           LLVM_DEBUG(dbgs()
444*0b57cec5SDimitry Andric                      << "\tSkipped Add - no final resources available\n");
445*0b57cec5SDimitry Andric         }
446*0b57cec5SDimitry Andric       } else {
447*0b57cec5SDimitry Andric         //
448*0b57cec5SDimitry Andric         // If the current resource can be accommodated, check the next
449*0b57cec5SDimitry Andric         // stage in InsnClass for available resources.
450*0b57cec5SDimitry Andric         //
451*0b57cec5SDimitry Andric         if (ResultingResourceState != prevState) {
452*0b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "\n");
453*0b57cec5SDimitry Andric           AddInsnClassStages(InsnClass, ComboBitToBitsMap,
454*0b57cec5SDimitry Andric                                 chkstage - 1, numstages,
455*0b57cec5SDimitry Andric                                 ResultingResourceState, origState,
456*0b57cec5SDimitry Andric                                 VisitedResourceStates, PossibleStates);
457*0b57cec5SDimitry Andric         } else {
458*0b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "\tSkipped Add - no resources available\n");
459*0b57cec5SDimitry Andric         }
460*0b57cec5SDimitry Andric       }
461*0b57cec5SDimitry Andric     }
462*0b57cec5SDimitry Andric   }
463*0b57cec5SDimitry Andric }
464*0b57cec5SDimitry Andric 
465*0b57cec5SDimitry Andric //
466*0b57cec5SDimitry Andric // canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass
467*0b57cec5SDimitry Andric // may be a valid transition from this state i.e., can an instruction of type
468*0b57cec5SDimitry Andric // InsnClass be added to the packet represented by this state.
469*0b57cec5SDimitry Andric //
470*0b57cec5SDimitry Andric // Note that this routine is performing conservative checks that can be
471*0b57cec5SDimitry Andric // quickly executed acting as a filter before calling AddInsnClassStages.
472*0b57cec5SDimitry Andric // Any cases allowed through here will be caught later in AddInsnClassStages
473*0b57cec5SDimitry Andric // which performs the more expensive exact check.
474*0b57cec5SDimitry Andric //
475*0b57cec5SDimitry Andric bool State::canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,
476*0b57cec5SDimitry Andric                     std::map<unsigned, unsigned> &ComboBitToBitsMap) const {
477*0b57cec5SDimitry Andric   for (std::set<unsigned>::const_iterator SI = stateInfo.begin();
478*0b57cec5SDimitry Andric        SI != stateInfo.end(); ++SI) {
479*0b57cec5SDimitry Andric     // Check to see if all required resources are available.
480*0b57cec5SDimitry Andric     bool available = true;
481*0b57cec5SDimitry Andric 
482*0b57cec5SDimitry Andric     // Inspect each stage independently.
483*0b57cec5SDimitry Andric     // note: This is a conservative check as we aren't checking for
484*0b57cec5SDimitry Andric     //       possible resource competition between the stages themselves
485*0b57cec5SDimitry Andric     //       The full cross product is examined later in AddInsnClass.
486*0b57cec5SDimitry Andric     for (unsigned i = 0; i < InsnClass.size(); ++i) {
487*0b57cec5SDimitry Andric       unsigned resources = *SI;
488*0b57cec5SDimitry Andric       if ((~resources & InsnClass[i]) == 0) {
489*0b57cec5SDimitry Andric         available = false;
490*0b57cec5SDimitry Andric         break;
491*0b57cec5SDimitry Andric       }
492*0b57cec5SDimitry Andric       // Make sure _all_ resources for a combo function are available.
493*0b57cec5SDimitry Andric       // note: This is a quick conservative check as it won't catch an
494*0b57cec5SDimitry Andric       //       unscheduleable combo if this stage is an OR expression
495*0b57cec5SDimitry Andric       //       containing a combo.
496*0b57cec5SDimitry Andric       //       These cases are caught later in AddInsnClass.
497*0b57cec5SDimitry Andric       unsigned combo = ComboBitToBitsMap[InsnClass[i]];
498*0b57cec5SDimitry Andric       if (combo && ((~resources & combo) != combo)) {
499*0b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "\tSkipped canMaybeAdd 0x"
500*0b57cec5SDimitry Andric                           << Twine::utohexstr(resources) << " - combo op 0x"
501*0b57cec5SDimitry Andric                           << Twine::utohexstr(InsnClass[i]) << " (0x"
502*0b57cec5SDimitry Andric                           << Twine::utohexstr(combo)
503*0b57cec5SDimitry Andric                           << ") cannot be scheduled\n");
504*0b57cec5SDimitry Andric         available = false;
505*0b57cec5SDimitry Andric         break;
506*0b57cec5SDimitry Andric       }
507*0b57cec5SDimitry Andric     }
508*0b57cec5SDimitry Andric 
509*0b57cec5SDimitry Andric     if (available) {
510*0b57cec5SDimitry Andric       return true;
511*0b57cec5SDimitry Andric     }
512*0b57cec5SDimitry Andric   }
513*0b57cec5SDimitry Andric   return false;
514*0b57cec5SDimitry Andric }
515*0b57cec5SDimitry Andric 
516*0b57cec5SDimitry Andric const State &DFA::newState() {
517*0b57cec5SDimitry Andric   auto IterPair = states.insert(State());
518*0b57cec5SDimitry Andric   assert(IterPair.second && "State already exists");
519*0b57cec5SDimitry Andric   return *IterPair.first;
520*0b57cec5SDimitry Andric }
521*0b57cec5SDimitry Andric 
522*0b57cec5SDimitry Andric int State::currentStateNum = 0;
523*0b57cec5SDimitry Andric 
524*0b57cec5SDimitry Andric DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R):
525*0b57cec5SDimitry Andric   TargetName(CodeGenTarget(R).getName()), Records(R) {}
526*0b57cec5SDimitry Andric 
527*0b57cec5SDimitry Andric //
528*0b57cec5SDimitry Andric // writeTableAndAPI - Print out a table representing the DFA and the
529*0b57cec5SDimitry Andric // associated API to create a DFA packetizer.
530*0b57cec5SDimitry Andric //
531*0b57cec5SDimitry Andric // Format:
532*0b57cec5SDimitry Andric // DFAStateInputTable[][2] = pairs of <Input, Transition> for all valid
533*0b57cec5SDimitry Andric //                           transitions.
534*0b57cec5SDimitry Andric // DFAStateEntryTable[i] = Index of the first entry in DFAStateInputTable for
535*0b57cec5SDimitry Andric //                         the ith state.
536*0b57cec5SDimitry Andric //
537*0b57cec5SDimitry Andric //
538*0b57cec5SDimitry Andric void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName,
539*0b57cec5SDimitry Andric                            int numInsnClasses,
540*0b57cec5SDimitry Andric                            int maxResources, int numCombos, int maxStages) {
541*0b57cec5SDimitry Andric   unsigned numStates = states.size();
542*0b57cec5SDimitry Andric 
543*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "-------------------------------------------------------"
544*0b57cec5SDimitry Andric                        "----------------------\n");
545*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "writeTableAndAPI\n");
546*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Total states: " << numStates << "\n");
547*0b57cec5SDimitry Andric 
548*0b57cec5SDimitry Andric   OS << "namespace llvm {\n";
549*0b57cec5SDimitry Andric 
550*0b57cec5SDimitry Andric   OS << "\n// Input format:\n";
551*0b57cec5SDimitry Andric   OS << "#define DFA_MAX_RESTERMS        " << DFA_MAX_RESTERMS
552*0b57cec5SDimitry Andric      << "\t// maximum AND'ed resource terms\n";
553*0b57cec5SDimitry Andric   OS << "#define DFA_MAX_RESOURCES       " << DFA_MAX_RESOURCES
554*0b57cec5SDimitry Andric      << "\t// maximum resource bits in one term\n";
555*0b57cec5SDimitry Andric 
556*0b57cec5SDimitry Andric   OS << "\n// " << TargetName << "DFAStateInputTable[][2] = "
557*0b57cec5SDimitry Andric      << "pairs of <Input, NextState> for all valid\n";
558*0b57cec5SDimitry Andric   OS << "//                           transitions.\n";
559*0b57cec5SDimitry Andric   OS << "// " << numStates << "\tstates\n";
560*0b57cec5SDimitry Andric   OS << "// " << numInsnClasses << "\tinstruction classes\n";
561*0b57cec5SDimitry Andric   OS << "// " << maxResources << "\tresources max\n";
562*0b57cec5SDimitry Andric   OS << "// " << numCombos << "\tcombo resources\n";
563*0b57cec5SDimitry Andric   OS << "// " << maxStages << "\tstages max\n";
564*0b57cec5SDimitry Andric   OS << "const " << DFA_TBLTYPE << " "
565*0b57cec5SDimitry Andric      << TargetName << "DFAStateInputTable[][2] = {\n";
566*0b57cec5SDimitry Andric 
567*0b57cec5SDimitry Andric   // This table provides a map to the beginning of the transitions for State s
568*0b57cec5SDimitry Andric   // in DFAStateInputTable.
569*0b57cec5SDimitry Andric   std::vector<int> StateEntry(numStates+1);
570*0b57cec5SDimitry Andric   static const std::string SentinelEntry = "{-1, -1}";
571*0b57cec5SDimitry Andric 
572*0b57cec5SDimitry Andric   // Tracks the total valid transitions encountered so far. It is used
573*0b57cec5SDimitry Andric   // to construct the StateEntry table.
574*0b57cec5SDimitry Andric   int ValidTransitions = 0;
575*0b57cec5SDimitry Andric   DFA::StateSet::iterator SI = states.begin();
576*0b57cec5SDimitry Andric   for (unsigned i = 0; i < numStates; ++i, ++SI) {
577*0b57cec5SDimitry Andric     assert ((SI->stateNum == (int) i) && "Mismatch in state numbers");
578*0b57cec5SDimitry Andric     StateEntry[i] = ValidTransitions;
579*0b57cec5SDimitry Andric     for (State::TransitionMap::iterator
580*0b57cec5SDimitry Andric         II = SI->Transitions.begin(), IE = SI->Transitions.end();
581*0b57cec5SDimitry Andric         II != IE; ++II) {
582*0b57cec5SDimitry Andric       OS << "{0x" << Twine::utohexstr(getDFAInsnInput(II->first)) << ", "
583*0b57cec5SDimitry Andric          << II->second->stateNum << "},\t";
584*0b57cec5SDimitry Andric     }
585*0b57cec5SDimitry Andric     ValidTransitions += SI->Transitions.size();
586*0b57cec5SDimitry Andric 
587*0b57cec5SDimitry Andric     // If there are no valid transitions from this stage, we need a sentinel
588*0b57cec5SDimitry Andric     // transition.
589*0b57cec5SDimitry Andric     if (ValidTransitions == StateEntry[i]) {
590*0b57cec5SDimitry Andric       OS << SentinelEntry << ",\t";
591*0b57cec5SDimitry Andric       ++ValidTransitions;
592*0b57cec5SDimitry Andric     }
593*0b57cec5SDimitry Andric 
594*0b57cec5SDimitry Andric     OS << " // state " << i << ": " << StateEntry[i];
595*0b57cec5SDimitry Andric     if (StateEntry[i] != (ValidTransitions-1)) {   // More than one transition.
596*0b57cec5SDimitry Andric        OS << "-" << (ValidTransitions-1);
597*0b57cec5SDimitry Andric     }
598*0b57cec5SDimitry Andric     OS << "\n";
599*0b57cec5SDimitry Andric   }
600*0b57cec5SDimitry Andric 
601*0b57cec5SDimitry Andric   // Print out a sentinel entry at the end of the StateInputTable. This is
602*0b57cec5SDimitry Andric   // needed to iterate over StateInputTable in DFAPacketizer::ReadTable()
603*0b57cec5SDimitry Andric   OS << SentinelEntry << "\t";
604*0b57cec5SDimitry Andric   OS << " // state " << numStates << ": " << ValidTransitions;
605*0b57cec5SDimitry Andric   OS << "\n";
606*0b57cec5SDimitry Andric 
607*0b57cec5SDimitry Andric   OS << "};\n\n";
608*0b57cec5SDimitry Andric   OS << "// " << TargetName << "DFAStateEntryTable[i] = "
609*0b57cec5SDimitry Andric      << "Index of the first entry in DFAStateInputTable for\n";
610*0b57cec5SDimitry Andric   OS << "//                         "
611*0b57cec5SDimitry Andric      << "the ith state.\n";
612*0b57cec5SDimitry Andric   OS << "// " << numStates << " states\n";
613*0b57cec5SDimitry Andric   OS << "const unsigned int " << TargetName << "DFAStateEntryTable[] = {\n";
614*0b57cec5SDimitry Andric 
615*0b57cec5SDimitry Andric   // Multiply i by 2 since each entry in DFAStateInputTable is a set of
616*0b57cec5SDimitry Andric   // two numbers.
617*0b57cec5SDimitry Andric   unsigned lastState = 0;
618*0b57cec5SDimitry Andric   for (unsigned i = 0; i < numStates; ++i) {
619*0b57cec5SDimitry Andric     if (i && ((i % 10) == 0)) {
620*0b57cec5SDimitry Andric         lastState = i-1;
621*0b57cec5SDimitry Andric         OS << "   // states " << (i-10) << ":" << lastState << "\n";
622*0b57cec5SDimitry Andric     }
623*0b57cec5SDimitry Andric     OS << StateEntry[i] << ", ";
624*0b57cec5SDimitry Andric   }
625*0b57cec5SDimitry Andric 
626*0b57cec5SDimitry Andric   // Print out the index to the sentinel entry in StateInputTable
627*0b57cec5SDimitry Andric   OS << ValidTransitions << ", ";
628*0b57cec5SDimitry Andric   OS << "   // states " << (lastState+1) << ":" << numStates << "\n";
629*0b57cec5SDimitry Andric 
630*0b57cec5SDimitry Andric   OS << "};\n";
631*0b57cec5SDimitry Andric   OS << "} // namespace\n";
632*0b57cec5SDimitry Andric 
633*0b57cec5SDimitry Andric   //
634*0b57cec5SDimitry Andric   // Emit DFA Packetizer tables if the target is a VLIW machine.
635*0b57cec5SDimitry Andric   //
636*0b57cec5SDimitry Andric   std::string SubTargetClassName = TargetName + "GenSubtargetInfo";
637*0b57cec5SDimitry Andric   OS << "\n" << "#include \"llvm/CodeGen/DFAPacketizer.h\"\n";
638*0b57cec5SDimitry Andric   OS << "namespace llvm {\n";
639*0b57cec5SDimitry Andric   OS << "DFAPacketizer *" << SubTargetClassName << "::"
640*0b57cec5SDimitry Andric      << "createDFAPacketizer(const InstrItineraryData *IID) const {\n"
641*0b57cec5SDimitry Andric      << "   return new DFAPacketizer(IID, " << TargetName
642*0b57cec5SDimitry Andric      << "DFAStateInputTable, " << TargetName << "DFAStateEntryTable);\n}\n\n";
643*0b57cec5SDimitry Andric   OS << "} // End llvm namespace \n";
644*0b57cec5SDimitry Andric }
645*0b57cec5SDimitry Andric 
646*0b57cec5SDimitry Andric //
647*0b57cec5SDimitry Andric // collectAllFuncUnits - Construct a map of function unit names to bits.
648*0b57cec5SDimitry Andric //
649*0b57cec5SDimitry Andric int DFAPacketizerEmitter::collectAllFuncUnits(
650*0b57cec5SDimitry Andric                             std::vector<Record*> &ProcItinList,
651*0b57cec5SDimitry Andric                             std::map<std::string, unsigned> &FUNameToBitsMap,
652*0b57cec5SDimitry Andric                             int &maxFUs,
653*0b57cec5SDimitry Andric                             raw_ostream &OS) {
654*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "-------------------------------------------------------"
655*0b57cec5SDimitry Andric                        "----------------------\n");
656*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "collectAllFuncUnits");
657*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << " (" << ProcItinList.size() << " itineraries)\n");
658*0b57cec5SDimitry Andric 
659*0b57cec5SDimitry Andric   int totalFUs = 0;
660*0b57cec5SDimitry Andric   // Parse functional units for all the itineraries.
661*0b57cec5SDimitry Andric   for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) {
662*0b57cec5SDimitry Andric     Record *Proc = ProcItinList[i];
663*0b57cec5SDimitry Andric     std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU");
664*0b57cec5SDimitry Andric 
665*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "    FU:" << i << " (" << FUs.size() << " FUs) "
666*0b57cec5SDimitry Andric                       << Proc->getName());
667*0b57cec5SDimitry Andric 
668*0b57cec5SDimitry Andric     // Convert macros to bits for each stage.
669*0b57cec5SDimitry Andric     unsigned numFUs = FUs.size();
670*0b57cec5SDimitry Andric     for (unsigned j = 0; j < numFUs; ++j) {
671*0b57cec5SDimitry Andric       assert ((j < DFA_MAX_RESOURCES) &&
672*0b57cec5SDimitry Andric                       "Exceeded maximum number of representable resources");
673*0b57cec5SDimitry Andric       unsigned FuncResources = (unsigned) (1U << j);
674*0b57cec5SDimitry Andric       FUNameToBitsMap[FUs[j]->getName()] = FuncResources;
675*0b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << " " << FUs[j]->getName() << ":0x"
676*0b57cec5SDimitry Andric                         << Twine::utohexstr(FuncResources));
677*0b57cec5SDimitry Andric     }
678*0b57cec5SDimitry Andric     if (((int) numFUs) > maxFUs) {
679*0b57cec5SDimitry Andric       maxFUs = numFUs;
680*0b57cec5SDimitry Andric     }
681*0b57cec5SDimitry Andric     totalFUs += numFUs;
682*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\n");
683*0b57cec5SDimitry Andric   }
684*0b57cec5SDimitry Andric   return totalFUs;
685*0b57cec5SDimitry Andric }
686*0b57cec5SDimitry Andric 
687*0b57cec5SDimitry Andric //
688*0b57cec5SDimitry Andric // collectAllComboFuncs - Construct a map from a combo function unit bit to
689*0b57cec5SDimitry Andric //                        the bits of all included functional units.
690*0b57cec5SDimitry Andric //
691*0b57cec5SDimitry Andric int DFAPacketizerEmitter::collectAllComboFuncs(
692*0b57cec5SDimitry Andric                             std::vector<Record*> &ComboFuncList,
693*0b57cec5SDimitry Andric                             std::map<std::string, unsigned> &FUNameToBitsMap,
694*0b57cec5SDimitry Andric                             std::map<unsigned, unsigned> &ComboBitToBitsMap,
695*0b57cec5SDimitry Andric                             raw_ostream &OS) {
696*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "-------------------------------------------------------"
697*0b57cec5SDimitry Andric                        "----------------------\n");
698*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "collectAllComboFuncs");
699*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << " (" << ComboFuncList.size() << " sets)\n");
700*0b57cec5SDimitry Andric 
701*0b57cec5SDimitry Andric   int numCombos = 0;
702*0b57cec5SDimitry Andric   for (unsigned i = 0, N = ComboFuncList.size(); i < N; ++i) {
703*0b57cec5SDimitry Andric     Record *Func = ComboFuncList[i];
704*0b57cec5SDimitry Andric     std::vector<Record*> FUs = Func->getValueAsListOfDefs("CFD");
705*0b57cec5SDimitry Andric 
706*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "    CFD:" << i << " (" << FUs.size() << " combo FUs) "
707*0b57cec5SDimitry Andric                       << Func->getName() << "\n");
708*0b57cec5SDimitry Andric 
709*0b57cec5SDimitry Andric     // Convert macros to bits for each stage.
710*0b57cec5SDimitry Andric     for (unsigned j = 0, N = FUs.size(); j < N; ++j) {
711*0b57cec5SDimitry Andric       assert ((j < DFA_MAX_RESOURCES) &&
712*0b57cec5SDimitry Andric                       "Exceeded maximum number of DFA resources");
713*0b57cec5SDimitry Andric       Record *FuncData = FUs[j];
714*0b57cec5SDimitry Andric       Record *ComboFunc = FuncData->getValueAsDef("TheComboFunc");
715*0b57cec5SDimitry Andric       const std::vector<Record*> &FuncList =
716*0b57cec5SDimitry Andric                                    FuncData->getValueAsListOfDefs("FuncList");
717*0b57cec5SDimitry Andric       const std::string &ComboFuncName = ComboFunc->getName();
718*0b57cec5SDimitry Andric       unsigned ComboBit = FUNameToBitsMap[ComboFuncName];
719*0b57cec5SDimitry Andric       unsigned ComboResources = ComboBit;
720*0b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "      combo: " << ComboFuncName << ":0x"
721*0b57cec5SDimitry Andric                         << Twine::utohexstr(ComboResources) << "\n");
722*0b57cec5SDimitry Andric       for (unsigned k = 0, M = FuncList.size(); k < M; ++k) {
723*0b57cec5SDimitry Andric         std::string FuncName = FuncList[k]->getName();
724*0b57cec5SDimitry Andric         unsigned FuncResources = FUNameToBitsMap[FuncName];
725*0b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "        " << FuncName << ":0x"
726*0b57cec5SDimitry Andric                           << Twine::utohexstr(FuncResources) << "\n");
727*0b57cec5SDimitry Andric         ComboResources |= FuncResources;
728*0b57cec5SDimitry Andric       }
729*0b57cec5SDimitry Andric       ComboBitToBitsMap[ComboBit] = ComboResources;
730*0b57cec5SDimitry Andric       numCombos++;
731*0b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "          => combo bits: " << ComboFuncName << ":0x"
732*0b57cec5SDimitry Andric                         << Twine::utohexstr(ComboBit) << " = 0x"
733*0b57cec5SDimitry Andric                         << Twine::utohexstr(ComboResources) << "\n");
734*0b57cec5SDimitry Andric     }
735*0b57cec5SDimitry Andric   }
736*0b57cec5SDimitry Andric   return numCombos;
737*0b57cec5SDimitry Andric }
738*0b57cec5SDimitry Andric 
739*0b57cec5SDimitry Andric //
740*0b57cec5SDimitry Andric // collectOneInsnClass - Populate allInsnClasses with one instruction class
741*0b57cec5SDimitry Andric //
742*0b57cec5SDimitry Andric int DFAPacketizerEmitter::collectOneInsnClass(const std::string &ProcName,
743*0b57cec5SDimitry Andric                         std::vector<Record*> &ProcItinList,
744*0b57cec5SDimitry Andric                         std::map<std::string, unsigned> &FUNameToBitsMap,
745*0b57cec5SDimitry Andric                         Record *ItinData,
746*0b57cec5SDimitry Andric                         raw_ostream &OS) {
747*0b57cec5SDimitry Andric   const std::vector<Record*> &StageList =
748*0b57cec5SDimitry Andric     ItinData->getValueAsListOfDefs("Stages");
749*0b57cec5SDimitry Andric 
750*0b57cec5SDimitry Andric   // The number of stages.
751*0b57cec5SDimitry Andric   unsigned NStages = StageList.size();
752*0b57cec5SDimitry Andric 
753*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "    " << ItinData->getValueAsDef("TheClass")->getName()
754*0b57cec5SDimitry Andric                     << "\n");
755*0b57cec5SDimitry Andric 
756*0b57cec5SDimitry Andric   std::vector<unsigned> UnitBits;
757*0b57cec5SDimitry Andric 
758*0b57cec5SDimitry Andric   // Compute the bitwise or of each unit used in this stage.
759*0b57cec5SDimitry Andric   for (unsigned i = 0; i < NStages; ++i) {
760*0b57cec5SDimitry Andric     const Record *Stage = StageList[i];
761*0b57cec5SDimitry Andric 
762*0b57cec5SDimitry Andric     // Get unit list.
763*0b57cec5SDimitry Andric     const std::vector<Record*> &UnitList =
764*0b57cec5SDimitry Andric       Stage->getValueAsListOfDefs("Units");
765*0b57cec5SDimitry Andric 
766*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "        stage:" << i << " [" << UnitList.size()
767*0b57cec5SDimitry Andric                       << " units]:");
768*0b57cec5SDimitry Andric     unsigned dbglen = 26;  // cursor after stage dbgs
769*0b57cec5SDimitry Andric 
770*0b57cec5SDimitry Andric     // Compute the bitwise or of each unit used in this stage.
771*0b57cec5SDimitry Andric     unsigned UnitBitValue = 0;
772*0b57cec5SDimitry Andric     for (unsigned j = 0, M = UnitList.size(); j < M; ++j) {
773*0b57cec5SDimitry Andric       // Conduct bitwise or.
774*0b57cec5SDimitry Andric       std::string UnitName = UnitList[j]->getName();
775*0b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << " " << j << ":" << UnitName);
776*0b57cec5SDimitry Andric       dbglen += 3 + UnitName.length();
777*0b57cec5SDimitry Andric       assert(FUNameToBitsMap.count(UnitName));
778*0b57cec5SDimitry Andric       UnitBitValue |= FUNameToBitsMap[UnitName];
779*0b57cec5SDimitry Andric     }
780*0b57cec5SDimitry Andric 
781*0b57cec5SDimitry Andric     if (UnitBitValue != 0)
782*0b57cec5SDimitry Andric       UnitBits.push_back(UnitBitValue);
783*0b57cec5SDimitry Andric 
784*0b57cec5SDimitry Andric     while (dbglen <= 64) {   // line up bits dbgs
785*0b57cec5SDimitry Andric         dbglen += 8;
786*0b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "\t");
787*0b57cec5SDimitry Andric     }
788*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << " (bits: 0x" << Twine::utohexstr(UnitBitValue)
789*0b57cec5SDimitry Andric                       << ")\n");
790*0b57cec5SDimitry Andric   }
791*0b57cec5SDimitry Andric 
792*0b57cec5SDimitry Andric   if (!UnitBits.empty())
793*0b57cec5SDimitry Andric     allInsnClasses.push_back(UnitBits);
794*0b57cec5SDimitry Andric 
795*0b57cec5SDimitry Andric   LLVM_DEBUG({
796*0b57cec5SDimitry Andric     dbgs() << "        ";
797*0b57cec5SDimitry Andric     dbgsInsnClass(UnitBits);
798*0b57cec5SDimitry Andric     dbgs() << "\n";
799*0b57cec5SDimitry Andric   });
800*0b57cec5SDimitry Andric 
801*0b57cec5SDimitry Andric   return NStages;
802*0b57cec5SDimitry Andric }
803*0b57cec5SDimitry Andric 
804*0b57cec5SDimitry Andric //
805*0b57cec5SDimitry Andric // collectAllInsnClasses - Populate allInsnClasses which is a set of units
806*0b57cec5SDimitry Andric // used in each stage.
807*0b57cec5SDimitry Andric //
808*0b57cec5SDimitry Andric int DFAPacketizerEmitter::collectAllInsnClasses(const std::string &ProcName,
809*0b57cec5SDimitry Andric                             std::vector<Record*> &ProcItinList,
810*0b57cec5SDimitry Andric                             std::map<std::string, unsigned> &FUNameToBitsMap,
811*0b57cec5SDimitry Andric                             std::vector<Record*> &ItinDataList,
812*0b57cec5SDimitry Andric                             int &maxStages,
813*0b57cec5SDimitry Andric                             raw_ostream &OS) {
814*0b57cec5SDimitry Andric   // Collect all instruction classes.
815*0b57cec5SDimitry Andric   unsigned M = ItinDataList.size();
816*0b57cec5SDimitry Andric 
817*0b57cec5SDimitry Andric   int numInsnClasses = 0;
818*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "-------------------------------------------------------"
819*0b57cec5SDimitry Andric                        "----------------------\n"
820*0b57cec5SDimitry Andric                     << "collectAllInsnClasses " << ProcName << " (" << M
821*0b57cec5SDimitry Andric                     << " classes)\n");
822*0b57cec5SDimitry Andric 
823*0b57cec5SDimitry Andric   // Collect stages for each instruction class for all itinerary data
824*0b57cec5SDimitry Andric   for (unsigned j = 0; j < M; j++) {
825*0b57cec5SDimitry Andric     Record *ItinData = ItinDataList[j];
826*0b57cec5SDimitry Andric     int NStages = collectOneInsnClass(ProcName, ProcItinList,
827*0b57cec5SDimitry Andric                                       FUNameToBitsMap, ItinData, OS);
828*0b57cec5SDimitry Andric     if (NStages > maxStages) {
829*0b57cec5SDimitry Andric       maxStages = NStages;
830*0b57cec5SDimitry Andric     }
831*0b57cec5SDimitry Andric     numInsnClasses++;
832*0b57cec5SDimitry Andric   }
833*0b57cec5SDimitry Andric   return numInsnClasses;
834*0b57cec5SDimitry Andric }
835*0b57cec5SDimitry Andric 
836*0b57cec5SDimitry Andric //
837*0b57cec5SDimitry Andric // Run the worklist algorithm to generate the DFA.
838*0b57cec5SDimitry Andric //
839*0b57cec5SDimitry Andric void DFAPacketizerEmitter::run(raw_ostream &OS) {
840*0b57cec5SDimitry Andric   // Collect processor iteraries.
841*0b57cec5SDimitry Andric   std::vector<Record*> ProcItinList =
842*0b57cec5SDimitry Andric     Records.getAllDerivedDefinitions("ProcessorItineraries");
843*0b57cec5SDimitry Andric 
844*0b57cec5SDimitry Andric   //
845*0b57cec5SDimitry Andric   // Collect the Functional units.
846*0b57cec5SDimitry Andric   //
847*0b57cec5SDimitry Andric   std::map<std::string, unsigned> FUNameToBitsMap;
848*0b57cec5SDimitry Andric   int maxResources = 0;
849*0b57cec5SDimitry Andric   collectAllFuncUnits(ProcItinList,
850*0b57cec5SDimitry Andric                               FUNameToBitsMap, maxResources, OS);
851*0b57cec5SDimitry Andric 
852*0b57cec5SDimitry Andric   //
853*0b57cec5SDimitry Andric   // Collect the Combo Functional units.
854*0b57cec5SDimitry Andric   //
855*0b57cec5SDimitry Andric   std::map<unsigned, unsigned> ComboBitToBitsMap;
856*0b57cec5SDimitry Andric   std::vector<Record*> ComboFuncList =
857*0b57cec5SDimitry Andric     Records.getAllDerivedDefinitions("ComboFuncUnits");
858*0b57cec5SDimitry Andric   int numCombos = collectAllComboFuncs(ComboFuncList,
859*0b57cec5SDimitry Andric                               FUNameToBitsMap, ComboBitToBitsMap, OS);
860*0b57cec5SDimitry Andric 
861*0b57cec5SDimitry Andric   //
862*0b57cec5SDimitry Andric   // Collect the itineraries.
863*0b57cec5SDimitry Andric   //
864*0b57cec5SDimitry Andric   int maxStages = 0;
865*0b57cec5SDimitry Andric   int numInsnClasses = 0;
866*0b57cec5SDimitry Andric   for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
867*0b57cec5SDimitry Andric     Record *Proc = ProcItinList[i];
868*0b57cec5SDimitry Andric 
869*0b57cec5SDimitry Andric     // Get processor itinerary name.
870*0b57cec5SDimitry Andric     const std::string &ProcName = Proc->getName();
871*0b57cec5SDimitry Andric 
872*0b57cec5SDimitry Andric     // Skip default.
873*0b57cec5SDimitry Andric     if (ProcName == "NoItineraries")
874*0b57cec5SDimitry Andric       continue;
875*0b57cec5SDimitry Andric 
876*0b57cec5SDimitry Andric     // Sanity check for at least one instruction itinerary class.
877*0b57cec5SDimitry Andric     unsigned NItinClasses =
878*0b57cec5SDimitry Andric       Records.getAllDerivedDefinitions("InstrItinClass").size();
879*0b57cec5SDimitry Andric     if (NItinClasses == 0)
880*0b57cec5SDimitry Andric       return;
881*0b57cec5SDimitry Andric 
882*0b57cec5SDimitry Andric     // Get itinerary data list.
883*0b57cec5SDimitry Andric     std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID");
884*0b57cec5SDimitry Andric 
885*0b57cec5SDimitry Andric     // Collect all instruction classes
886*0b57cec5SDimitry Andric     numInsnClasses += collectAllInsnClasses(ProcName, ProcItinList,
887*0b57cec5SDimitry Andric                           FUNameToBitsMap, ItinDataList, maxStages, OS);
888*0b57cec5SDimitry Andric   }
889*0b57cec5SDimitry Andric 
890*0b57cec5SDimitry Andric   //
891*0b57cec5SDimitry Andric   // Run a worklist algorithm to generate the DFA.
892*0b57cec5SDimitry Andric   //
893*0b57cec5SDimitry Andric   DFA D;
894*0b57cec5SDimitry Andric   const State *Initial = &D.newState();
895*0b57cec5SDimitry Andric   Initial->isInitial = true;
896*0b57cec5SDimitry Andric   Initial->stateInfo.insert(0x0);
897*0b57cec5SDimitry Andric   SmallVector<const State*, 32> WorkList;
898*0b57cec5SDimitry Andric   std::map<std::set<unsigned>, const State*> Visited;
899*0b57cec5SDimitry Andric 
900*0b57cec5SDimitry Andric   WorkList.push_back(Initial);
901*0b57cec5SDimitry Andric 
902*0b57cec5SDimitry Andric   //
903*0b57cec5SDimitry Andric   // Worklist algorithm to create a DFA for processor resource tracking.
904*0b57cec5SDimitry Andric   // C = {set of InsnClasses}
905*0b57cec5SDimitry Andric   // Begin with initial node in worklist. Initial node does not have
906*0b57cec5SDimitry Andric   // any consumed resources,
907*0b57cec5SDimitry Andric   //     ResourceState = 0x0
908*0b57cec5SDimitry Andric   // Visited = {}
909*0b57cec5SDimitry Andric   // While worklist != empty
910*0b57cec5SDimitry Andric   //    S = first element of worklist
911*0b57cec5SDimitry Andric   //    For every instruction class C
912*0b57cec5SDimitry Andric   //      if we can accommodate C in S:
913*0b57cec5SDimitry Andric   //          S' = state with resource states = {S Union C}
914*0b57cec5SDimitry Andric   //          Add a new transition: S x C -> S'
915*0b57cec5SDimitry Andric   //          If S' is not in Visited:
916*0b57cec5SDimitry Andric   //             Add S' to worklist
917*0b57cec5SDimitry Andric   //             Add S' to Visited
918*0b57cec5SDimitry Andric   //
919*0b57cec5SDimitry Andric   while (!WorkList.empty()) {
920*0b57cec5SDimitry Andric     const State *current = WorkList.pop_back_val();
921*0b57cec5SDimitry Andric     LLVM_DEBUG({
922*0b57cec5SDimitry Andric       dbgs() << "---------------------\n";
923*0b57cec5SDimitry Andric       dbgs() << "Processing state: " << current->stateNum << " - ";
924*0b57cec5SDimitry Andric       dbgsStateInfo(current->stateInfo);
925*0b57cec5SDimitry Andric       dbgs() << "\n";
926*0b57cec5SDimitry Andric     });
927*0b57cec5SDimitry Andric     for (unsigned i = 0; i < allInsnClasses.size(); i++) {
928*0b57cec5SDimitry Andric       std::vector<unsigned> InsnClass = allInsnClasses[i];
929*0b57cec5SDimitry Andric       LLVM_DEBUG({
930*0b57cec5SDimitry Andric         dbgs() << i << " ";
931*0b57cec5SDimitry Andric         dbgsInsnClass(InsnClass);
932*0b57cec5SDimitry Andric         dbgs() << "\n";
933*0b57cec5SDimitry Andric       });
934*0b57cec5SDimitry Andric 
935*0b57cec5SDimitry Andric       std::set<unsigned> NewStateResources;
936*0b57cec5SDimitry Andric       //
937*0b57cec5SDimitry Andric       // If we haven't already created a transition for this input
938*0b57cec5SDimitry Andric       // and the state can accommodate this InsnClass, create a transition.
939*0b57cec5SDimitry Andric       //
940*0b57cec5SDimitry Andric       if (!current->hasTransition(InsnClass) &&
941*0b57cec5SDimitry Andric           current->canMaybeAddInsnClass(InsnClass, ComboBitToBitsMap)) {
942*0b57cec5SDimitry Andric         const State *NewState = nullptr;
943*0b57cec5SDimitry Andric         current->AddInsnClass(InsnClass, ComboBitToBitsMap, NewStateResources);
944*0b57cec5SDimitry Andric         if (NewStateResources.empty()) {
945*0b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "  Skipped - no new states generated\n");
946*0b57cec5SDimitry Andric           continue;
947*0b57cec5SDimitry Andric         }
948*0b57cec5SDimitry Andric 
949*0b57cec5SDimitry Andric         LLVM_DEBUG({
950*0b57cec5SDimitry Andric           dbgs() << "\t";
951*0b57cec5SDimitry Andric           dbgsStateInfo(NewStateResources);
952*0b57cec5SDimitry Andric           dbgs() << "\n";
953*0b57cec5SDimitry Andric         });
954*0b57cec5SDimitry Andric 
955*0b57cec5SDimitry Andric         //
956*0b57cec5SDimitry Andric         // If we have seen this state before, then do not create a new state.
957*0b57cec5SDimitry Andric         //
958*0b57cec5SDimitry Andric         auto VI = Visited.find(NewStateResources);
959*0b57cec5SDimitry Andric         if (VI != Visited.end()) {
960*0b57cec5SDimitry Andric           NewState = VI->second;
961*0b57cec5SDimitry Andric           LLVM_DEBUG({
962*0b57cec5SDimitry Andric             dbgs() << "\tFound existing state: " << NewState->stateNum
963*0b57cec5SDimitry Andric                    << " - ";
964*0b57cec5SDimitry Andric             dbgsStateInfo(NewState->stateInfo);
965*0b57cec5SDimitry Andric             dbgs() << "\n";
966*0b57cec5SDimitry Andric           });
967*0b57cec5SDimitry Andric         } else {
968*0b57cec5SDimitry Andric           NewState = &D.newState();
969*0b57cec5SDimitry Andric           NewState->stateInfo = NewStateResources;
970*0b57cec5SDimitry Andric           Visited[NewStateResources] = NewState;
971*0b57cec5SDimitry Andric           WorkList.push_back(NewState);
972*0b57cec5SDimitry Andric           LLVM_DEBUG({
973*0b57cec5SDimitry Andric             dbgs() << "\tAccepted new state: " << NewState->stateNum << " - ";
974*0b57cec5SDimitry Andric             dbgsStateInfo(NewState->stateInfo);
975*0b57cec5SDimitry Andric             dbgs() << "\n";
976*0b57cec5SDimitry Andric           });
977*0b57cec5SDimitry Andric         }
978*0b57cec5SDimitry Andric 
979*0b57cec5SDimitry Andric         current->addTransition(InsnClass, NewState);
980*0b57cec5SDimitry Andric       }
981*0b57cec5SDimitry Andric     }
982*0b57cec5SDimitry Andric   }
983*0b57cec5SDimitry Andric 
984*0b57cec5SDimitry Andric   // Print out the table.
985*0b57cec5SDimitry Andric   D.writeTableAndAPI(OS, TargetName,
986*0b57cec5SDimitry Andric                numInsnClasses, maxResources, numCombos, maxStages);
987*0b57cec5SDimitry Andric }
988*0b57cec5SDimitry Andric 
989*0b57cec5SDimitry Andric namespace llvm {
990*0b57cec5SDimitry Andric 
991*0b57cec5SDimitry Andric void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS) {
992*0b57cec5SDimitry Andric   emitSourceFileHeader("Target DFA Packetizer Tables", OS);
993*0b57cec5SDimitry Andric   DFAPacketizerEmitter(RK).run(OS);
994*0b57cec5SDimitry Andric }
995*0b57cec5SDimitry Andric 
996*0b57cec5SDimitry Andric } // end namespace llvm
997