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