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