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