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