13ca95b02SDimitry Andric //===- DFAPacketizerEmitter.cpp - Packetization DFA for a VLIW machine ----===//
2dff0c46cSDimitry Andric //
3dff0c46cSDimitry Andric // The LLVM Compiler Infrastructure
4dff0c46cSDimitry Andric //
5dff0c46cSDimitry Andric // This file is distributed under the University of Illinois Open Source
6dff0c46cSDimitry Andric // License. See LICENSE.TXT for details.
7dff0c46cSDimitry Andric //
8dff0c46cSDimitry Andric //===----------------------------------------------------------------------===//
9dff0c46cSDimitry Andric //
10dff0c46cSDimitry Andric // This class parses the Schedule.td file and produces an API that can be used
11dff0c46cSDimitry Andric // to reason about whether an instruction can be added to a packet on a VLIW
12dff0c46cSDimitry Andric // architecture. The class internally generates a deterministic finite
13dff0c46cSDimitry Andric // automaton (DFA) that models all possible mappings of machine instructions
14dff0c46cSDimitry Andric // to functional units as instructions are added to a packet.
15dff0c46cSDimitry Andric //
16dff0c46cSDimitry Andric //===----------------------------------------------------------------------===//
17dff0c46cSDimitry Andric
187d523365SDimitry Andric #define DEBUG_TYPE "dfa-emitter"
197d523365SDimitry Andric
20dff0c46cSDimitry Andric #include "CodeGenTarget.h"
217ae0e2c9SDimitry Andric #include "llvm/ADT/DenseSet.h"
22d88c1a5aSDimitry Andric #include "llvm/ADT/SmallVector.h"
237d523365SDimitry Andric #include "llvm/ADT/StringExtras.h"
247ae0e2c9SDimitry Andric #include "llvm/TableGen/Record.h"
257ae0e2c9SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
267d523365SDimitry Andric #include "llvm/Support/Debug.h"
27d88c1a5aSDimitry Andric #include "llvm/Support/raw_ostream.h"
28d88c1a5aSDimitry Andric #include <cassert>
29d88c1a5aSDimitry Andric #include <cstdint>
307ae0e2c9SDimitry Andric #include <map>
31d88c1a5aSDimitry Andric #include <set>
327ae0e2c9SDimitry Andric #include <string>
33d88c1a5aSDimitry Andric #include <vector>
343ca95b02SDimitry Andric
35dff0c46cSDimitry Andric using namespace llvm;
36dff0c46cSDimitry Andric
377d523365SDimitry Andric // --------------------------------------------------------------------
387d523365SDimitry Andric // Definitions shared between DFAPacketizer.cpp and DFAPacketizerEmitter.cpp
397d523365SDimitry Andric
407d523365SDimitry Andric // DFA_MAX_RESTERMS * DFA_MAX_RESOURCES must fit within sizeof DFAInput.
417d523365SDimitry Andric // This is verified in DFAPacketizer.cpp:DFAPacketizer::DFAPacketizer.
427d523365SDimitry Andric //
437d523365SDimitry Andric // e.g. terms x resource bit combinations that fit in uint32_t:
447d523365SDimitry Andric // 4 terms x 8 bits = 32 bits
457d523365SDimitry Andric // 3 terms x 10 bits = 30 bits
467d523365SDimitry Andric // 2 terms x 16 bits = 32 bits
477d523365SDimitry Andric //
487d523365SDimitry Andric // e.g. terms x resource bit combinations that fit in uint64_t:
497d523365SDimitry Andric // 8 terms x 8 bits = 64 bits
507d523365SDimitry Andric // 7 terms x 9 bits = 63 bits
517d523365SDimitry Andric // 6 terms x 10 bits = 60 bits
527d523365SDimitry Andric // 5 terms x 12 bits = 60 bits
537d523365SDimitry Andric // 4 terms x 16 bits = 64 bits <--- current
547d523365SDimitry Andric // 3 terms x 21 bits = 63 bits
557d523365SDimitry Andric // 2 terms x 32 bits = 64 bits
567d523365SDimitry Andric //
577d523365SDimitry Andric #define DFA_MAX_RESTERMS 4 // The max # of AND'ed resource terms.
587d523365SDimitry Andric #define DFA_MAX_RESOURCES 16 // The max # of resource bits in one term.
597d523365SDimitry Andric
607d523365SDimitry Andric typedef uint64_t DFAInput;
617d523365SDimitry Andric typedef int64_t DFAStateInput;
627d523365SDimitry Andric #define DFA_TBLTYPE "int64_t" // For generating DFAStateInputTable.
637d523365SDimitry Andric
647d523365SDimitry Andric namespace {
65d88c1a5aSDimitry Andric
addDFAFuncUnits(DFAInput Inp,unsigned FuncUnits)667d523365SDimitry Andric DFAInput addDFAFuncUnits(DFAInput Inp, unsigned FuncUnits) {
677d523365SDimitry Andric return (Inp << DFA_MAX_RESOURCES) | FuncUnits;
687d523365SDimitry Andric }
697d523365SDimitry Andric
707d523365SDimitry Andric /// Return the DFAInput for an instruction class input vector.
717d523365SDimitry Andric /// This function is used in both DFAPacketizer.cpp and in
727d523365SDimitry Andric /// DFAPacketizerEmitter.cpp.
getDFAInsnInput(const std::vector<unsigned> & InsnClass)737d523365SDimitry Andric DFAInput getDFAInsnInput(const std::vector<unsigned> &InsnClass) {
747d523365SDimitry Andric DFAInput InsnInput = 0;
757d523365SDimitry Andric assert((InsnClass.size() <= DFA_MAX_RESTERMS) &&
767d523365SDimitry Andric "Exceeded maximum number of DFA terms");
777d523365SDimitry Andric for (auto U : InsnClass)
787d523365SDimitry Andric InsnInput = addDFAFuncUnits(InsnInput, U);
797d523365SDimitry Andric return InsnInput;
807d523365SDimitry Andric }
81d88c1a5aSDimitry Andric
823ca95b02SDimitry Andric } // end anonymous namespace
833ca95b02SDimitry Andric
847d523365SDimitry Andric // --------------------------------------------------------------------
857d523365SDimitry Andric
867d523365SDimitry Andric #ifndef NDEBUG
877d523365SDimitry Andric // To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter".
887d523365SDimitry Andric //
897d523365SDimitry Andric // dbgsInsnClass - When debugging, print instruction class stages.
907d523365SDimitry Andric //
917d523365SDimitry Andric void dbgsInsnClass(const std::vector<unsigned> &InsnClass);
927d523365SDimitry Andric //
937d523365SDimitry Andric // dbgsStateInfo - When debugging, print the set of state info.
947d523365SDimitry Andric //
957d523365SDimitry Andric void dbgsStateInfo(const std::set<unsigned> &stateInfo);
967d523365SDimitry Andric //
977d523365SDimitry Andric // dbgsIndent - When debugging, indent by the specified amount.
987d523365SDimitry Andric //
997d523365SDimitry Andric void dbgsIndent(unsigned indent);
1007d523365SDimitry Andric #endif
1017d523365SDimitry Andric
102dff0c46cSDimitry Andric //
1037ae0e2c9SDimitry Andric // class DFAPacketizerEmitter: class that generates and prints out the DFA
1047ae0e2c9SDimitry Andric // for resource tracking.
1057ae0e2c9SDimitry Andric //
1067ae0e2c9SDimitry Andric namespace {
107d88c1a5aSDimitry Andric
1087ae0e2c9SDimitry Andric class DFAPacketizerEmitter {
1097ae0e2c9SDimitry Andric private:
1107ae0e2c9SDimitry Andric std::string TargetName;
1117ae0e2c9SDimitry Andric //
1127ae0e2c9SDimitry Andric // allInsnClasses is the set of all possible resources consumed by an
1137ae0e2c9SDimitry Andric // InstrStage.
1147ae0e2c9SDimitry Andric //
1157d523365SDimitry Andric std::vector<std::vector<unsigned>> allInsnClasses;
1167ae0e2c9SDimitry Andric RecordKeeper &Records;
1177ae0e2c9SDimitry Andric
1187ae0e2c9SDimitry Andric public:
1197ae0e2c9SDimitry Andric DFAPacketizerEmitter(RecordKeeper &R);
1207ae0e2c9SDimitry Andric
1217ae0e2c9SDimitry Andric //
1227d523365SDimitry Andric // collectAllFuncUnits - Construct a map of function unit names to bits.
1237d523365SDimitry Andric //
1247d523365SDimitry Andric int collectAllFuncUnits(std::vector<Record*> &ProcItinList,
1257d523365SDimitry Andric std::map<std::string, unsigned> &FUNameToBitsMap,
1267d523365SDimitry Andric int &maxResources,
1277d523365SDimitry Andric raw_ostream &OS);
1287d523365SDimitry Andric
1297d523365SDimitry Andric //
1307d523365SDimitry Andric // collectAllComboFuncs - Construct a map from a combo function unit bit to
1317d523365SDimitry Andric // the bits of all included functional units.
1327d523365SDimitry Andric //
1337d523365SDimitry Andric int collectAllComboFuncs(std::vector<Record*> &ComboFuncList,
1347d523365SDimitry Andric std::map<std::string, unsigned> &FUNameToBitsMap,
1357d523365SDimitry Andric std::map<unsigned, unsigned> &ComboBitToBitsMap,
1367d523365SDimitry Andric raw_ostream &OS);
1377d523365SDimitry Andric
1387d523365SDimitry Andric //
1397d523365SDimitry Andric // collectOneInsnClass - Populate allInsnClasses with one instruction class.
1407d523365SDimitry Andric //
1417d523365SDimitry Andric int collectOneInsnClass(const std::string &ProcName,
1427d523365SDimitry Andric std::vector<Record*> &ProcItinList,
1437d523365SDimitry Andric std::map<std::string, unsigned> &FUNameToBitsMap,
1447d523365SDimitry Andric Record *ItinData,
1457d523365SDimitry Andric raw_ostream &OS);
1467d523365SDimitry Andric
1477d523365SDimitry Andric //
1487d523365SDimitry Andric // collectAllInsnClasses - Populate allInsnClasses which is a set of units
1497ae0e2c9SDimitry Andric // used in each stage.
1507ae0e2c9SDimitry Andric //
1517d523365SDimitry Andric int collectAllInsnClasses(const std::string &ProcName,
1527d523365SDimitry Andric std::vector<Record*> &ProcItinList,
1537d523365SDimitry Andric std::map<std::string, unsigned> &FUNameToBitsMap,
1547d523365SDimitry Andric std::vector<Record*> &ItinDataList,
1557d523365SDimitry Andric int &maxStages,
1567ae0e2c9SDimitry Andric raw_ostream &OS);
1577ae0e2c9SDimitry Andric
1587ae0e2c9SDimitry Andric void run(raw_ostream &OS);
1597ae0e2c9SDimitry Andric };
1607ae0e2c9SDimitry Andric
1617ae0e2c9SDimitry Andric //
162dff0c46cSDimitry Andric // State represents the usage of machine resources if the packet contains
163dff0c46cSDimitry Andric // a set of instruction classes.
164dff0c46cSDimitry Andric //
165dff0c46cSDimitry Andric // Specifically, currentState is a set of bit-masks.
166dff0c46cSDimitry Andric // The nth bit in a bit-mask indicates whether the nth resource is being used
167dff0c46cSDimitry Andric // by this state. The set of bit-masks in a state represent the different
168dff0c46cSDimitry Andric // possible outcomes of transitioning to this state.
169dff0c46cSDimitry Andric // For example: consider a two resource architecture: resource L and resource M
170dff0c46cSDimitry Andric // with three instruction classes: L, M, and L_or_M.
171dff0c46cSDimitry Andric // From the initial state (currentState = 0x00), if we add instruction class
172dff0c46cSDimitry Andric // L_or_M we will transition to a state with currentState = [0x01, 0x10]. This
173dff0c46cSDimitry Andric // represents the possible resource states that can result from adding a L_or_M
174dff0c46cSDimitry Andric // instruction
175dff0c46cSDimitry Andric //
176dff0c46cSDimitry Andric // Another way of thinking about this transition is we are mapping a NDFA with
177dff0c46cSDimitry Andric // two states [0x01] and [0x10] into a DFA with a single state [0x01, 0x10].
178dff0c46cSDimitry Andric //
1793861d79fSDimitry Andric // A State instance also contains a collection of transitions from that state:
1803861d79fSDimitry Andric // a map from inputs to new states.
181dff0c46cSDimitry Andric //
182dff0c46cSDimitry Andric class State {
183dff0c46cSDimitry Andric public:
184dff0c46cSDimitry Andric static int currentStateNum;
18591bc56edSDimitry Andric // stateNum is the only member used for equality/ordering, all other members
18691bc56edSDimitry Andric // can be mutated even in const State objects.
18791bc56edSDimitry Andric const int stateNum;
18891bc56edSDimitry Andric mutable bool isInitial;
18991bc56edSDimitry Andric mutable std::set<unsigned> stateInfo;
1907d523365SDimitry Andric typedef std::map<std::vector<unsigned>, const State *> TransitionMap;
19191bc56edSDimitry Andric mutable TransitionMap Transitions;
192dff0c46cSDimitry Andric
193dff0c46cSDimitry Andric State();
194dff0c46cSDimitry Andric
operator <(const State & s) const1953861d79fSDimitry Andric bool operator<(const State &s) const {
1963861d79fSDimitry Andric return stateNum < s.stateNum;
1973861d79fSDimitry Andric }
1983861d79fSDimitry Andric
199dff0c46cSDimitry Andric //
2007d523365SDimitry Andric // canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass
2017d523365SDimitry Andric // may be a valid transition from this state i.e., can an instruction of type
2027d523365SDimitry Andric // InsnClass be added to the packet represented by this state.
203dff0c46cSDimitry Andric //
2047d523365SDimitry Andric // Note that for multiple stages, this quick check does not take into account
2057d523365SDimitry Andric // any possible resource competition between the stages themselves. That is
2067d523365SDimitry Andric // enforced in AddInsnClassStages which checks the cross product of all
2077d523365SDimitry Andric // stages for resource availability (which is a more involved check).
208dff0c46cSDimitry Andric //
2097d523365SDimitry Andric bool canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,
2107d523365SDimitry Andric std::map<unsigned, unsigned> &ComboBitToBitsMap) const;
211d88c1a5aSDimitry Andric
2127ae0e2c9SDimitry Andric //
2137ae0e2c9SDimitry Andric // AddInsnClass - Return all combinations of resource reservation
2147ae0e2c9SDimitry Andric // which are possible from this state (PossibleStates).
2157ae0e2c9SDimitry Andric //
2167d523365SDimitry Andric // PossibleStates is the set of valid resource states that ensue from valid
2177d523365SDimitry Andric // transitions.
2187d523365SDimitry Andric //
2197d523365SDimitry Andric void AddInsnClass(std::vector<unsigned> &InsnClass,
2207d523365SDimitry Andric std::map<unsigned, unsigned> &ComboBitToBitsMap,
2217d523365SDimitry Andric std::set<unsigned> &PossibleStates) const;
222d88c1a5aSDimitry Andric
2237d523365SDimitry Andric //
2247d523365SDimitry Andric // AddInsnClassStages - Return all combinations of resource reservation
2257d523365SDimitry Andric // resulting from the cross product of all stages for this InsnClass
2267d523365SDimitry Andric // which are possible from this state (PossibleStates).
2277d523365SDimitry Andric //
2287d523365SDimitry Andric void AddInsnClassStages(std::vector<unsigned> &InsnClass,
2297d523365SDimitry Andric std::map<unsigned, unsigned> &ComboBitToBitsMap,
2307d523365SDimitry Andric unsigned chkstage, unsigned numstages,
2317d523365SDimitry Andric unsigned prevState, unsigned origState,
2327d523365SDimitry Andric DenseSet<unsigned> &VisitedResourceStates,
2337d523365SDimitry Andric std::set<unsigned> &PossibleStates) const;
234d88c1a5aSDimitry Andric
235dff0c46cSDimitry Andric //
2363861d79fSDimitry Andric // addTransition - Add a transition from this state given the input InsnClass
237dff0c46cSDimitry Andric //
2387d523365SDimitry Andric void addTransition(std::vector<unsigned> InsnClass, const State *To) const;
239d88c1a5aSDimitry Andric
2403861d79fSDimitry Andric //
2413861d79fSDimitry Andric // hasTransition - Returns true if there is a transition from this state
2423861d79fSDimitry Andric // given the input InsnClass
2433861d79fSDimitry Andric //
2447d523365SDimitry Andric bool hasTransition(std::vector<unsigned> InsnClass) const;
2457ae0e2c9SDimitry Andric };
246dff0c46cSDimitry Andric
247dff0c46cSDimitry Andric //
248dff0c46cSDimitry Andric // class DFA: deterministic finite automaton for processor resource tracking.
249dff0c46cSDimitry Andric //
250dff0c46cSDimitry Andric class DFA {
251dff0c46cSDimitry Andric public:
252d88c1a5aSDimitry Andric DFA() = default;
253dff0c46cSDimitry Andric
254dff0c46cSDimitry Andric // Set of states. Need to keep this sorted to emit the transition table.
25591bc56edSDimitry Andric typedef std::set<State> StateSet;
2563861d79fSDimitry Andric StateSet states;
257dff0c46cSDimitry Andric
258d88c1a5aSDimitry Andric State *currentState = nullptr;
259dff0c46cSDimitry Andric
260dff0c46cSDimitry Andric //
261dff0c46cSDimitry Andric // Modify the DFA.
262dff0c46cSDimitry Andric //
26391bc56edSDimitry Andric const State &newState();
264dff0c46cSDimitry Andric
265dff0c46cSDimitry Andric //
266dff0c46cSDimitry Andric // writeTable: Print out a table representing the DFA.
267dff0c46cSDimitry Andric //
2687d523365SDimitry Andric void writeTableAndAPI(raw_ostream &OS, const std::string &ClassName,
2697d523365SDimitry Andric int numInsnClasses = 0,
2707d523365SDimitry Andric int maxResources = 0, int numCombos = 0, int maxStages = 0);
271dff0c46cSDimitry Andric };
272d88c1a5aSDimitry Andric
2733ca95b02SDimitry Andric } // end anonymous namespace
274dff0c46cSDimitry Andric
2757d523365SDimitry Andric #ifndef NDEBUG
2767d523365SDimitry Andric // To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter".
2777d523365SDimitry Andric //
2787d523365SDimitry Andric // dbgsInsnClass - When debugging, print instruction class stages.
2797d523365SDimitry Andric //
dbgsInsnClass(const std::vector<unsigned> & InsnClass)2807d523365SDimitry Andric void dbgsInsnClass(const std::vector<unsigned> &InsnClass) {
281*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "InsnClass: ");
2827d523365SDimitry Andric for (unsigned i = 0; i < InsnClass.size(); ++i) {
2837d523365SDimitry Andric if (i > 0) {
284*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << ", ");
2857d523365SDimitry Andric }
286*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "0x" << Twine::utohexstr(InsnClass[i]));
2877d523365SDimitry Andric }
2887d523365SDimitry Andric DFAInput InsnInput = getDFAInsnInput(InsnClass);
289*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " (input: 0x" << Twine::utohexstr(InsnInput) << ")");
2907d523365SDimitry Andric }
2917d523365SDimitry Andric
2927d523365SDimitry Andric //
2937d523365SDimitry Andric // dbgsStateInfo - When debugging, print the set of state info.
2947d523365SDimitry Andric //
dbgsStateInfo(const std::set<unsigned> & stateInfo)2957d523365SDimitry Andric void dbgsStateInfo(const std::set<unsigned> &stateInfo) {
296*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "StateInfo: ");
2977d523365SDimitry Andric unsigned i = 0;
2987d523365SDimitry Andric for (std::set<unsigned>::iterator SI = stateInfo.begin();
2997d523365SDimitry Andric SI != stateInfo.end(); ++SI, ++i) {
3007d523365SDimitry Andric unsigned thisState = *SI;
3017d523365SDimitry Andric if (i > 0) {
302*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << ", ");
3037d523365SDimitry Andric }
304*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "0x" << Twine::utohexstr(thisState));
3057d523365SDimitry Andric }
3067d523365SDimitry Andric }
3077d523365SDimitry Andric
3087d523365SDimitry Andric //
3097d523365SDimitry Andric // dbgsIndent - When debugging, indent by the specified amount.
3107d523365SDimitry Andric //
dbgsIndent(unsigned indent)3117d523365SDimitry Andric void dbgsIndent(unsigned indent) {
3127d523365SDimitry Andric for (unsigned i = 0; i < indent; ++i) {
313*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " ");
3147d523365SDimitry Andric }
3157d523365SDimitry Andric }
3163ca95b02SDimitry Andric #endif // NDEBUG
317dff0c46cSDimitry Andric
318dff0c46cSDimitry Andric //
3193861d79fSDimitry Andric // Constructors and destructors for State and DFA
320dff0c46cSDimitry Andric //
State()321dff0c46cSDimitry Andric State::State() :
322dff0c46cSDimitry Andric stateNum(currentStateNum++), isInitial(false) {}
323dff0c46cSDimitry Andric
3243861d79fSDimitry Andric //
3253861d79fSDimitry Andric // addTransition - Add a transition from this state given the input InsnClass
3263861d79fSDimitry Andric //
addTransition(std::vector<unsigned> InsnClass,const State * To) const3277d523365SDimitry Andric void State::addTransition(std::vector<unsigned> InsnClass, const State *To)
3287d523365SDimitry Andric const {
3293861d79fSDimitry Andric assert(!Transitions.count(InsnClass) &&
3303861d79fSDimitry Andric "Cannot have multiple transitions for the same input");
3313861d79fSDimitry Andric Transitions[InsnClass] = To;
3323861d79fSDimitry Andric }
3333861d79fSDimitry Andric
3343861d79fSDimitry Andric //
3353861d79fSDimitry Andric // hasTransition - Returns true if there is a transition from this state
3363861d79fSDimitry Andric // given the input InsnClass
3373861d79fSDimitry Andric //
hasTransition(std::vector<unsigned> InsnClass) const3387d523365SDimitry Andric bool State::hasTransition(std::vector<unsigned> InsnClass) const {
3393861d79fSDimitry Andric return Transitions.count(InsnClass) > 0;
3407ae0e2c9SDimitry Andric }
341dff0c46cSDimitry Andric
342dff0c46cSDimitry Andric //
3437ae0e2c9SDimitry Andric // AddInsnClass - Return all combinations of resource reservation
3447ae0e2c9SDimitry Andric // which are possible from this state (PossibleStates).
345dff0c46cSDimitry Andric //
3467d523365SDimitry Andric // PossibleStates is the set of valid resource states that ensue from valid
3477d523365SDimitry Andric // transitions.
3487d523365SDimitry Andric //
AddInsnClass(std::vector<unsigned> & InsnClass,std::map<unsigned,unsigned> & ComboBitToBitsMap,std::set<unsigned> & PossibleStates) const3497d523365SDimitry Andric void State::AddInsnClass(std::vector<unsigned> &InsnClass,
3507d523365SDimitry Andric std::map<unsigned, unsigned> &ComboBitToBitsMap,
35191bc56edSDimitry Andric std::set<unsigned> &PossibleStates) const {
352dff0c46cSDimitry Andric //
353dff0c46cSDimitry Andric // Iterate over all resource states in currentState.
354dff0c46cSDimitry Andric //
3557d523365SDimitry Andric unsigned numstages = InsnClass.size();
3567d523365SDimitry Andric assert((numstages > 0) && "InsnClass has no stages");
357dff0c46cSDimitry Andric
358dff0c46cSDimitry Andric for (std::set<unsigned>::iterator SI = stateInfo.begin();
359dff0c46cSDimitry Andric SI != stateInfo.end(); ++SI) {
360dff0c46cSDimitry Andric unsigned thisState = *SI;
361dff0c46cSDimitry Andric
362dff0c46cSDimitry Andric DenseSet<unsigned> VisitedResourceStates;
3637d523365SDimitry Andric
364*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " thisState: 0x" << Twine::utohexstr(thisState)
365*4ba319b5SDimitry Andric << "\n");
3667d523365SDimitry Andric AddInsnClassStages(InsnClass, ComboBitToBitsMap,
3677d523365SDimitry Andric numstages - 1, numstages,
3687d523365SDimitry Andric thisState, thisState,
3697d523365SDimitry Andric VisitedResourceStates, PossibleStates);
3707d523365SDimitry Andric }
3717d523365SDimitry Andric }
3727d523365SDimitry Andric
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) const3737d523365SDimitry Andric void State::AddInsnClassStages(std::vector<unsigned> &InsnClass,
3747d523365SDimitry Andric std::map<unsigned, unsigned> &ComboBitToBitsMap,
3757d523365SDimitry Andric unsigned chkstage, unsigned numstages,
3767d523365SDimitry Andric unsigned prevState, unsigned origState,
3777d523365SDimitry Andric DenseSet<unsigned> &VisitedResourceStates,
3787d523365SDimitry Andric std::set<unsigned> &PossibleStates) const {
3797d523365SDimitry Andric assert((chkstage < numstages) && "AddInsnClassStages: stage out of range");
3807d523365SDimitry Andric unsigned thisStage = InsnClass[chkstage];
3817d523365SDimitry Andric
382*4ba319b5SDimitry Andric LLVM_DEBUG({
3837d523365SDimitry Andric dbgsIndent((1 + numstages - chkstage) << 1);
3847d523365SDimitry Andric dbgs() << "AddInsnClassStages " << chkstage << " (0x"
385fe4fed2eSDimitry Andric << Twine::utohexstr(thisStage) << ") from ";
3867d523365SDimitry Andric dbgsInsnClass(InsnClass);
3877d523365SDimitry Andric dbgs() << "\n";
3887d523365SDimitry Andric });
3897d523365SDimitry Andric
390dff0c46cSDimitry Andric //
3917d523365SDimitry Andric // Iterate over all possible resources used in thisStage.
3927d523365SDimitry Andric // For ex: for thisStage = 0x11, all resources = {0x01, 0x10}.
3937d523365SDimitry Andric //
3947d523365SDimitry Andric for (unsigned int j = 0; j < DFA_MAX_RESOURCES; ++j) {
3957d523365SDimitry Andric unsigned resourceMask = (0x1 << j);
3967d523365SDimitry Andric if (resourceMask & thisStage) {
3977d523365SDimitry Andric unsigned combo = ComboBitToBitsMap[resourceMask];
3987d523365SDimitry Andric if (combo && ((~prevState & combo) != combo)) {
399*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\tSkipped Add 0x" << Twine::utohexstr(prevState)
400fe4fed2eSDimitry Andric << " - combo op 0x" << Twine::utohexstr(resourceMask)
401fe4fed2eSDimitry Andric << " (0x" << Twine::utohexstr(combo)
402fe4fed2eSDimitry Andric << ") cannot be scheduled\n");
4037d523365SDimitry Andric continue;
4047d523365SDimitry Andric }
4057d523365SDimitry Andric //
4067d523365SDimitry Andric // For each possible resource used in thisStage, generate the
407dff0c46cSDimitry Andric // resource state if that resource was used.
408dff0c46cSDimitry Andric //
4097d523365SDimitry Andric unsigned ResultingResourceState = prevState | resourceMask | combo;
410*4ba319b5SDimitry Andric LLVM_DEBUG({
4117d523365SDimitry Andric dbgsIndent((2 + numstages - chkstage) << 1);
412fe4fed2eSDimitry Andric dbgs() << "0x" << Twine::utohexstr(prevState) << " | 0x"
413fe4fed2eSDimitry Andric << Twine::utohexstr(resourceMask);
4147d523365SDimitry Andric if (combo)
415fe4fed2eSDimitry Andric dbgs() << " | 0x" << Twine::utohexstr(combo);
416fe4fed2eSDimitry Andric dbgs() << " = 0x" << Twine::utohexstr(ResultingResourceState) << " ";
4177d523365SDimitry Andric });
4187d523365SDimitry Andric
4197d523365SDimitry Andric //
4207d523365SDimitry Andric // If this is the final stage for this class
4217d523365SDimitry Andric //
4227d523365SDimitry Andric if (chkstage == 0) {
423dff0c46cSDimitry Andric //
424dff0c46cSDimitry Andric // Check if the resulting resource state can be accommodated in this
425dff0c46cSDimitry Andric // packet.
4267d523365SDimitry Andric // We compute resource OR prevState (originally started as origState).
4277d523365SDimitry Andric // If the result of the OR is different than origState, it implies
428dff0c46cSDimitry Andric // that there is at least one resource that can be used to schedule
4297d523365SDimitry Andric // thisStage in the current packet.
430dff0c46cSDimitry Andric // Insert ResultingResourceState into PossibleStates only if we haven't
431dff0c46cSDimitry Andric // processed ResultingResourceState before.
432dff0c46cSDimitry Andric //
4337d523365SDimitry Andric if (ResultingResourceState != prevState) {
4347d523365SDimitry Andric if (VisitedResourceStates.count(ResultingResourceState) == 0) {
435dff0c46cSDimitry Andric VisitedResourceStates.insert(ResultingResourceState);
436dff0c46cSDimitry Andric PossibleStates.insert(ResultingResourceState);
437*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs()
438*4ba319b5SDimitry Andric << "\tResultingResourceState: 0x"
439fe4fed2eSDimitry Andric << Twine::utohexstr(ResultingResourceState) << "\n");
4407d523365SDimitry Andric } else {
441*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\tSkipped Add - state already seen\n");
4427d523365SDimitry Andric }
4437d523365SDimitry Andric } else {
444*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs()
445*4ba319b5SDimitry Andric << "\tSkipped Add - no final resources available\n");
4467d523365SDimitry Andric }
4477d523365SDimitry Andric } else {
4487d523365SDimitry Andric //
4497d523365SDimitry Andric // If the current resource can be accommodated, check the next
4507d523365SDimitry Andric // stage in InsnClass for available resources.
4517d523365SDimitry Andric //
4527d523365SDimitry Andric if (ResultingResourceState != prevState) {
453*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
4547d523365SDimitry Andric AddInsnClassStages(InsnClass, ComboBitToBitsMap,
4557d523365SDimitry Andric chkstage - 1, numstages,
4567d523365SDimitry Andric ResultingResourceState, origState,
4577d523365SDimitry Andric VisitedResourceStates, PossibleStates);
4587d523365SDimitry Andric } else {
459*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\tSkipped Add - no resources available\n");
460dff0c46cSDimitry Andric }
461dff0c46cSDimitry Andric }
462dff0c46cSDimitry Andric }
463dff0c46cSDimitry Andric }
4647ae0e2c9SDimitry Andric }
4657ae0e2c9SDimitry Andric
4667ae0e2c9SDimitry Andric //
4677d523365SDimitry Andric // canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass
4687d523365SDimitry Andric // may be a valid transition from this state i.e., can an instruction of type
4697d523365SDimitry Andric // InsnClass be added to the packet represented by this state.
4707ae0e2c9SDimitry Andric //
4717d523365SDimitry Andric // Note that this routine is performing conservative checks that can be
4727d523365SDimitry Andric // quickly executed acting as a filter before calling AddInsnClassStages.
4737d523365SDimitry Andric // Any cases allowed through here will be caught later in AddInsnClassStages
4747d523365SDimitry Andric // which performs the more expensive exact check.
4757d523365SDimitry Andric //
canMaybeAddInsnClass(std::vector<unsigned> & InsnClass,std::map<unsigned,unsigned> & ComboBitToBitsMap) const4767d523365SDimitry Andric bool State::canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,
4777d523365SDimitry Andric std::map<unsigned, unsigned> &ComboBitToBitsMap) const {
4787ae0e2c9SDimitry Andric for (std::set<unsigned>::const_iterator SI = stateInfo.begin();
4797ae0e2c9SDimitry Andric SI != stateInfo.end(); ++SI) {
4807d523365SDimitry Andric // Check to see if all required resources are available.
4817d523365SDimitry Andric bool available = true;
4827d523365SDimitry Andric
4837d523365SDimitry Andric // Inspect each stage independently.
4847d523365SDimitry Andric // note: This is a conservative check as we aren't checking for
4857d523365SDimitry Andric // possible resource competition between the stages themselves
4867d523365SDimitry Andric // The full cross product is examined later in AddInsnClass.
4877d523365SDimitry Andric for (unsigned i = 0; i < InsnClass.size(); ++i) {
4887d523365SDimitry Andric unsigned resources = *SI;
4897d523365SDimitry Andric if ((~resources & InsnClass[i]) == 0) {
4907d523365SDimitry Andric available = false;
4917d523365SDimitry Andric break;
4927d523365SDimitry Andric }
4937d523365SDimitry Andric // Make sure _all_ resources for a combo function are available.
4947d523365SDimitry Andric // note: This is a quick conservative check as it won't catch an
4957d523365SDimitry Andric // unscheduleable combo if this stage is an OR expression
4967d523365SDimitry Andric // containing a combo.
4977d523365SDimitry Andric // These cases are caught later in AddInsnClass.
4987d523365SDimitry Andric unsigned combo = ComboBitToBitsMap[InsnClass[i]];
4997d523365SDimitry Andric if (combo && ((~resources & combo) != combo)) {
500*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\tSkipped canMaybeAdd 0x"
501fe4fed2eSDimitry Andric << Twine::utohexstr(resources) << " - combo op 0x"
502fe4fed2eSDimitry Andric << Twine::utohexstr(InsnClass[i]) << " (0x"
503*4ba319b5SDimitry Andric << Twine::utohexstr(combo)
504*4ba319b5SDimitry Andric << ") cannot be scheduled\n");
5057d523365SDimitry Andric available = false;
5067d523365SDimitry Andric break;
5077d523365SDimitry Andric }
5087d523365SDimitry Andric }
5097d523365SDimitry Andric
5107d523365SDimitry Andric if (available) {
5117ae0e2c9SDimitry Andric return true;
5127ae0e2c9SDimitry Andric }
5137d523365SDimitry Andric }
5147ae0e2c9SDimitry Andric return false;
515dff0c46cSDimitry Andric }
516dff0c46cSDimitry Andric
newState()51791bc56edSDimitry Andric const State &DFA::newState() {
51891bc56edSDimitry Andric auto IterPair = states.insert(State());
51991bc56edSDimitry Andric assert(IterPair.second && "State already exists");
52091bc56edSDimitry Andric return *IterPair.first;
521dff0c46cSDimitry Andric }
522dff0c46cSDimitry Andric
523dff0c46cSDimitry Andric int State::currentStateNum = 0;
524dff0c46cSDimitry Andric
DFAPacketizerEmitter(RecordKeeper & R)5257ae0e2c9SDimitry Andric DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R):
526d88c1a5aSDimitry Andric TargetName(CodeGenTarget(R).getName()), Records(R) {}
527dff0c46cSDimitry Andric
528dff0c46cSDimitry Andric //
529dff0c46cSDimitry Andric // writeTableAndAPI - Print out a table representing the DFA and the
530dff0c46cSDimitry Andric // associated API to create a DFA packetizer.
531dff0c46cSDimitry Andric //
532dff0c46cSDimitry Andric // Format:
533dff0c46cSDimitry Andric // DFAStateInputTable[][2] = pairs of <Input, Transition> for all valid
534dff0c46cSDimitry Andric // transitions.
535dff0c46cSDimitry Andric // DFAStateEntryTable[i] = Index of the first entry in DFAStateInputTable for
536dff0c46cSDimitry Andric // the ith state.
537dff0c46cSDimitry Andric //
538dff0c46cSDimitry Andric //
writeTableAndAPI(raw_ostream & OS,const std::string & TargetName,int numInsnClasses,int maxResources,int numCombos,int maxStages)5397d523365SDimitry Andric void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName,
5407d523365SDimitry Andric int numInsnClasses,
5417d523365SDimitry Andric int maxResources, int numCombos, int maxStages) {
5427d523365SDimitry Andric unsigned numStates = states.size();
5437d523365SDimitry Andric
544*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "-------------------------------------------------------"
545*4ba319b5SDimitry Andric "----------------------\n");
546*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "writeTableAndAPI\n");
547*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Total states: " << numStates << "\n");
5487d523365SDimitry Andric
5497d523365SDimitry Andric OS << "namespace llvm {\n";
5507d523365SDimitry Andric
5517d523365SDimitry Andric OS << "\n// Input format:\n";
5527d523365SDimitry Andric OS << "#define DFA_MAX_RESTERMS " << DFA_MAX_RESTERMS
5537d523365SDimitry Andric << "\t// maximum AND'ed resource terms\n";
5547d523365SDimitry Andric OS << "#define DFA_MAX_RESOURCES " << DFA_MAX_RESOURCES
5557d523365SDimitry Andric << "\t// maximum resource bits in one term\n";
5567d523365SDimitry Andric
5577d523365SDimitry Andric OS << "\n// " << TargetName << "DFAStateInputTable[][2] = "
5587d523365SDimitry Andric << "pairs of <Input, NextState> for all valid\n";
5597d523365SDimitry Andric OS << "// transitions.\n";
5607d523365SDimitry Andric OS << "// " << numStates << "\tstates\n";
5617d523365SDimitry Andric OS << "// " << numInsnClasses << "\tinstruction classes\n";
5627d523365SDimitry Andric OS << "// " << maxResources << "\tresources max\n";
5637d523365SDimitry Andric OS << "// " << numCombos << "\tcombo resources\n";
5647d523365SDimitry Andric OS << "// " << maxStages << "\tstages max\n";
5657d523365SDimitry Andric OS << "const " << DFA_TBLTYPE << " "
5667d523365SDimitry Andric << TargetName << "DFAStateInputTable[][2] = {\n";
5677d523365SDimitry Andric
568dff0c46cSDimitry Andric // This table provides a map to the beginning of the transitions for State s
569dff0c46cSDimitry Andric // in DFAStateInputTable.
5707d523365SDimitry Andric std::vector<int> StateEntry(numStates+1);
5717d523365SDimitry Andric static const std::string SentinelEntry = "{-1, -1}";
572dff0c46cSDimitry Andric
573dff0c46cSDimitry Andric // Tracks the total valid transitions encountered so far. It is used
574dff0c46cSDimitry Andric // to construct the StateEntry table.
575dff0c46cSDimitry Andric int ValidTransitions = 0;
5767d523365SDimitry Andric DFA::StateSet::iterator SI = states.begin();
5777d523365SDimitry Andric for (unsigned i = 0; i < numStates; ++i, ++SI) {
57891bc56edSDimitry Andric assert ((SI->stateNum == (int) i) && "Mismatch in state numbers");
5793861d79fSDimitry Andric StateEntry[i] = ValidTransitions;
5803861d79fSDimitry Andric for (State::TransitionMap::iterator
58191bc56edSDimitry Andric II = SI->Transitions.begin(), IE = SI->Transitions.end();
5823861d79fSDimitry Andric II != IE; ++II) {
583fe4fed2eSDimitry Andric OS << "{0x" << Twine::utohexstr(getDFAInsnInput(II->first)) << ", "
584fe4fed2eSDimitry Andric << II->second->stateNum << "},\t";
585dff0c46cSDimitry Andric }
58691bc56edSDimitry Andric ValidTransitions += SI->Transitions.size();
587dff0c46cSDimitry Andric
588dff0c46cSDimitry Andric // If there are no valid transitions from this stage, we need a sentinel
589dff0c46cSDimitry Andric // transition.
590dff0c46cSDimitry Andric if (ValidTransitions == StateEntry[i]) {
5917d523365SDimitry Andric OS << SentinelEntry << ",\t";
592dff0c46cSDimitry Andric ++ValidTransitions;
593dff0c46cSDimitry Andric }
594dff0c46cSDimitry Andric
5957d523365SDimitry Andric OS << " // state " << i << ": " << StateEntry[i];
5967d523365SDimitry Andric if (StateEntry[i] != (ValidTransitions-1)) { // More than one transition.
5977d523365SDimitry Andric OS << "-" << (ValidTransitions-1);
5987d523365SDimitry Andric }
599dff0c46cSDimitry Andric OS << "\n";
600dff0c46cSDimitry Andric }
601139f7f9bSDimitry Andric
602139f7f9bSDimitry Andric // Print out a sentinel entry at the end of the StateInputTable. This is
603139f7f9bSDimitry Andric // needed to iterate over StateInputTable in DFAPacketizer::ReadTable()
6047d523365SDimitry Andric OS << SentinelEntry << "\t";
6057d523365SDimitry Andric OS << " // state " << numStates << ": " << ValidTransitions;
6067d523365SDimitry Andric OS << "\n";
607139f7f9bSDimitry Andric
608dff0c46cSDimitry Andric OS << "};\n\n";
6097d523365SDimitry Andric OS << "// " << TargetName << "DFAStateEntryTable[i] = "
6107d523365SDimitry Andric << "Index of the first entry in DFAStateInputTable for\n";
6117d523365SDimitry Andric OS << "// "
6127d523365SDimitry Andric << "the ith state.\n";
6137d523365SDimitry Andric OS << "// " << numStates << " states\n";
614dff0c46cSDimitry Andric OS << "const unsigned int " << TargetName << "DFAStateEntryTable[] = {\n";
615dff0c46cSDimitry Andric
616dff0c46cSDimitry Andric // Multiply i by 2 since each entry in DFAStateInputTable is a set of
617dff0c46cSDimitry Andric // two numbers.
6187d523365SDimitry Andric unsigned lastState = 0;
6197d523365SDimitry Andric for (unsigned i = 0; i < numStates; ++i) {
6207d523365SDimitry Andric if (i && ((i % 10) == 0)) {
6217d523365SDimitry Andric lastState = i-1;
6227d523365SDimitry Andric OS << " // states " << (i-10) << ":" << lastState << "\n";
6237d523365SDimitry Andric }
624dff0c46cSDimitry Andric OS << StateEntry[i] << ", ";
6257d523365SDimitry Andric }
626dff0c46cSDimitry Andric
627139f7f9bSDimitry Andric // Print out the index to the sentinel entry in StateInputTable
628139f7f9bSDimitry Andric OS << ValidTransitions << ", ";
6297d523365SDimitry Andric OS << " // states " << (lastState+1) << ":" << numStates << "\n";
630139f7f9bSDimitry Andric
6317d523365SDimitry Andric OS << "};\n";
632dff0c46cSDimitry Andric OS << "} // namespace\n";
633dff0c46cSDimitry Andric
634dff0c46cSDimitry Andric //
635dff0c46cSDimitry Andric // Emit DFA Packetizer tables if the target is a VLIW machine.
636dff0c46cSDimitry Andric //
637dff0c46cSDimitry Andric std::string SubTargetClassName = TargetName + "GenSubtargetInfo";
638dff0c46cSDimitry Andric OS << "\n" << "#include \"llvm/CodeGen/DFAPacketizer.h\"\n";
639dff0c46cSDimitry Andric OS << "namespace llvm {\n";
640dff0c46cSDimitry Andric OS << "DFAPacketizer *" << SubTargetClassName << "::"
641dff0c46cSDimitry Andric << "createDFAPacketizer(const InstrItineraryData *IID) const {\n"
642dff0c46cSDimitry Andric << " return new DFAPacketizer(IID, " << TargetName
643dff0c46cSDimitry Andric << "DFAStateInputTable, " << TargetName << "DFAStateEntryTable);\n}\n\n";
644dff0c46cSDimitry Andric OS << "} // End llvm namespace \n";
645dff0c46cSDimitry Andric }
646dff0c46cSDimitry Andric
647dff0c46cSDimitry Andric //
6487d523365SDimitry Andric // collectAllFuncUnits - Construct a map of function unit names to bits.
649dff0c46cSDimitry Andric //
collectAllFuncUnits(std::vector<Record * > & ProcItinList,std::map<std::string,unsigned> & FUNameToBitsMap,int & maxFUs,raw_ostream & OS)6507d523365SDimitry Andric int DFAPacketizerEmitter::collectAllFuncUnits(
6517d523365SDimitry Andric std::vector<Record*> &ProcItinList,
6527d523365SDimitry Andric std::map<std::string, unsigned> &FUNameToBitsMap,
6537d523365SDimitry Andric int &maxFUs,
654dff0c46cSDimitry Andric raw_ostream &OS) {
655*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "-------------------------------------------------------"
656*4ba319b5SDimitry Andric "----------------------\n");
657*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "collectAllFuncUnits");
658*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " (" << ProcItinList.size() << " itineraries)\n");
659dff0c46cSDimitry Andric
6607d523365SDimitry Andric int totalFUs = 0;
661dff0c46cSDimitry Andric // Parse functional units for all the itineraries.
662dff0c46cSDimitry Andric for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) {
663dff0c46cSDimitry Andric Record *Proc = ProcItinList[i];
664dff0c46cSDimitry Andric std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU");
665dff0c46cSDimitry Andric
666*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " FU:" << i << " (" << FUs.size() << " FUs) "
6677d523365SDimitry Andric << Proc->getName());
6687d523365SDimitry Andric
669dff0c46cSDimitry Andric // Convert macros to bits for each stage.
6707d523365SDimitry Andric unsigned numFUs = FUs.size();
6717d523365SDimitry Andric for (unsigned j = 0; j < numFUs; ++j) {
6727d523365SDimitry Andric assert ((j < DFA_MAX_RESOURCES) &&
6737d523365SDimitry Andric "Exceeded maximum number of representable resources");
6747d523365SDimitry Andric unsigned FuncResources = (unsigned) (1U << j);
6757d523365SDimitry Andric FUNameToBitsMap[FUs[j]->getName()] = FuncResources;
676*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " " << FUs[j]->getName() << ":0x"
677fe4fed2eSDimitry Andric << Twine::utohexstr(FuncResources));
6787d523365SDimitry Andric }
6797d523365SDimitry Andric if (((int) numFUs) > maxFUs) {
6807d523365SDimitry Andric maxFUs = numFUs;
6817d523365SDimitry Andric }
6827d523365SDimitry Andric totalFUs += numFUs;
683*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
6847d523365SDimitry Andric }
6857d523365SDimitry Andric return totalFUs;
686dff0c46cSDimitry Andric }
687dff0c46cSDimitry Andric
6887d523365SDimitry Andric //
6897d523365SDimitry Andric // collectAllComboFuncs - Construct a map from a combo function unit bit to
6907d523365SDimitry Andric // the bits of all included functional units.
6917d523365SDimitry Andric //
collectAllComboFuncs(std::vector<Record * > & ComboFuncList,std::map<std::string,unsigned> & FUNameToBitsMap,std::map<unsigned,unsigned> & ComboBitToBitsMap,raw_ostream & OS)6927d523365SDimitry Andric int DFAPacketizerEmitter::collectAllComboFuncs(
6937d523365SDimitry Andric std::vector<Record*> &ComboFuncList,
6947d523365SDimitry Andric std::map<std::string, unsigned> &FUNameToBitsMap,
6957d523365SDimitry Andric std::map<unsigned, unsigned> &ComboBitToBitsMap,
6967d523365SDimitry Andric raw_ostream &OS) {
697*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "-------------------------------------------------------"
698*4ba319b5SDimitry Andric "----------------------\n");
699*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "collectAllComboFuncs");
700*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " (" << ComboFuncList.size() << " sets)\n");
7017d523365SDimitry Andric
7027d523365SDimitry Andric int numCombos = 0;
7037d523365SDimitry Andric for (unsigned i = 0, N = ComboFuncList.size(); i < N; ++i) {
7047d523365SDimitry Andric Record *Func = ComboFuncList[i];
7057d523365SDimitry Andric std::vector<Record*> FUs = Func->getValueAsListOfDefs("CFD");
7067d523365SDimitry Andric
707*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " CFD:" << i << " (" << FUs.size() << " combo FUs) "
7087d523365SDimitry Andric << Func->getName() << "\n");
7097d523365SDimitry Andric
7107d523365SDimitry Andric // Convert macros to bits for each stage.
7117d523365SDimitry Andric for (unsigned j = 0, N = FUs.size(); j < N; ++j) {
7127d523365SDimitry Andric assert ((j < DFA_MAX_RESOURCES) &&
7137d523365SDimitry Andric "Exceeded maximum number of DFA resources");
7147d523365SDimitry Andric Record *FuncData = FUs[j];
7157d523365SDimitry Andric Record *ComboFunc = FuncData->getValueAsDef("TheComboFunc");
7167d523365SDimitry Andric const std::vector<Record*> &FuncList =
7177d523365SDimitry Andric FuncData->getValueAsListOfDefs("FuncList");
7183ca95b02SDimitry Andric const std::string &ComboFuncName = ComboFunc->getName();
7197d523365SDimitry Andric unsigned ComboBit = FUNameToBitsMap[ComboFuncName];
7207d523365SDimitry Andric unsigned ComboResources = ComboBit;
721*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " combo: " << ComboFuncName << ":0x"
722fe4fed2eSDimitry Andric << Twine::utohexstr(ComboResources) << "\n");
7237d523365SDimitry Andric for (unsigned k = 0, M = FuncList.size(); k < M; ++k) {
7247d523365SDimitry Andric std::string FuncName = FuncList[k]->getName();
7257d523365SDimitry Andric unsigned FuncResources = FUNameToBitsMap[FuncName];
726*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " " << FuncName << ":0x"
727fe4fed2eSDimitry Andric << Twine::utohexstr(FuncResources) << "\n");
7287d523365SDimitry Andric ComboResources |= FuncResources;
7297d523365SDimitry Andric }
7307d523365SDimitry Andric ComboBitToBitsMap[ComboBit] = ComboResources;
7317d523365SDimitry Andric numCombos++;
732*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " => combo bits: " << ComboFuncName << ":0x"
733fe4fed2eSDimitry Andric << Twine::utohexstr(ComboBit) << " = 0x"
734fe4fed2eSDimitry Andric << Twine::utohexstr(ComboResources) << "\n");
7357d523365SDimitry Andric }
7367d523365SDimitry Andric }
7377d523365SDimitry Andric return numCombos;
7387d523365SDimitry Andric }
7397d523365SDimitry Andric
7407d523365SDimitry Andric //
7417d523365SDimitry Andric // collectOneInsnClass - Populate allInsnClasses with one instruction class
7427d523365SDimitry Andric //
collectOneInsnClass(const std::string & ProcName,std::vector<Record * > & ProcItinList,std::map<std::string,unsigned> & FUNameToBitsMap,Record * ItinData,raw_ostream & OS)7437d523365SDimitry Andric int DFAPacketizerEmitter::collectOneInsnClass(const std::string &ProcName,
7447d523365SDimitry Andric std::vector<Record*> &ProcItinList,
7457d523365SDimitry Andric std::map<std::string, unsigned> &FUNameToBitsMap,
7467d523365SDimitry Andric Record *ItinData,
7477d523365SDimitry Andric raw_ostream &OS) {
748dff0c46cSDimitry Andric const std::vector<Record*> &StageList =
749dff0c46cSDimitry Andric ItinData->getValueAsListOfDefs("Stages");
750dff0c46cSDimitry Andric
751dff0c46cSDimitry Andric // The number of stages.
7527d523365SDimitry Andric unsigned NStages = StageList.size();
753dff0c46cSDimitry Andric
754*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " " << ItinData->getValueAsDef("TheClass")->getName()
7557d523365SDimitry Andric << "\n");
7567d523365SDimitry Andric
7577d523365SDimitry Andric std::vector<unsigned> UnitBits;
758dff0c46cSDimitry Andric
759dff0c46cSDimitry Andric // Compute the bitwise or of each unit used in this stage.
760dff0c46cSDimitry Andric for (unsigned i = 0; i < NStages; ++i) {
761dff0c46cSDimitry Andric const Record *Stage = StageList[i];
762dff0c46cSDimitry Andric
763dff0c46cSDimitry Andric // Get unit list.
764dff0c46cSDimitry Andric const std::vector<Record*> &UnitList =
765dff0c46cSDimitry Andric Stage->getValueAsListOfDefs("Units");
766dff0c46cSDimitry Andric
767*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " stage:" << i << " [" << UnitList.size()
768*4ba319b5SDimitry Andric << " units]:");
7697d523365SDimitry Andric unsigned dbglen = 26; // cursor after stage dbgs
7707d523365SDimitry Andric
7717d523365SDimitry Andric // Compute the bitwise or of each unit used in this stage.
7727d523365SDimitry Andric unsigned UnitBitValue = 0;
773dff0c46cSDimitry Andric for (unsigned j = 0, M = UnitList.size(); j < M; ++j) {
774dff0c46cSDimitry Andric // Conduct bitwise or.
775dff0c46cSDimitry Andric std::string UnitName = UnitList[j]->getName();
776*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " " << j << ":" << UnitName);
7777d523365SDimitry Andric dbglen += 3 + UnitName.length();
7787d523365SDimitry Andric assert(FUNameToBitsMap.count(UnitName));
7797d523365SDimitry Andric UnitBitValue |= FUNameToBitsMap[UnitName];
780dff0c46cSDimitry Andric }
781dff0c46cSDimitry Andric
782dff0c46cSDimitry Andric if (UnitBitValue != 0)
7837d523365SDimitry Andric UnitBits.push_back(UnitBitValue);
7847d523365SDimitry Andric
7857d523365SDimitry Andric while (dbglen <= 64) { // line up bits dbgs
7867d523365SDimitry Andric dbglen += 8;
787*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\t");
788dff0c46cSDimitry Andric }
789*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " (bits: 0x" << Twine::utohexstr(UnitBitValue)
790*4ba319b5SDimitry Andric << ")\n");
791dff0c46cSDimitry Andric }
792dff0c46cSDimitry Andric
793d88c1a5aSDimitry Andric if (!UnitBits.empty())
7947d523365SDimitry Andric allInsnClasses.push_back(UnitBits);
7957d523365SDimitry Andric
796*4ba319b5SDimitry Andric LLVM_DEBUG({
7977d523365SDimitry Andric dbgs() << " ";
7987d523365SDimitry Andric dbgsInsnClass(UnitBits);
7997d523365SDimitry Andric dbgs() << "\n";
8007d523365SDimitry Andric });
8017d523365SDimitry Andric
8027d523365SDimitry Andric return NStages;
8037d523365SDimitry Andric }
8047d523365SDimitry Andric
8057d523365SDimitry Andric //
8067d523365SDimitry Andric // collectAllInsnClasses - Populate allInsnClasses which is a set of units
8077d523365SDimitry Andric // used in each stage.
8087d523365SDimitry Andric //
collectAllInsnClasses(const std::string & ProcName,std::vector<Record * > & ProcItinList,std::map<std::string,unsigned> & FUNameToBitsMap,std::vector<Record * > & ItinDataList,int & maxStages,raw_ostream & OS)8097d523365SDimitry Andric int DFAPacketizerEmitter::collectAllInsnClasses(const std::string &ProcName,
8107d523365SDimitry Andric std::vector<Record*> &ProcItinList,
8117d523365SDimitry Andric std::map<std::string, unsigned> &FUNameToBitsMap,
8127d523365SDimitry Andric std::vector<Record*> &ItinDataList,
8137d523365SDimitry Andric int &maxStages,
8147d523365SDimitry Andric raw_ostream &OS) {
8157d523365SDimitry Andric // Collect all instruction classes.
8167d523365SDimitry Andric unsigned M = ItinDataList.size();
8177d523365SDimitry Andric
8187d523365SDimitry Andric int numInsnClasses = 0;
819*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "-------------------------------------------------------"
820*4ba319b5SDimitry Andric "----------------------\n"
821*4ba319b5SDimitry Andric << "collectAllInsnClasses " << ProcName << " (" << M
822*4ba319b5SDimitry Andric << " classes)\n");
8237d523365SDimitry Andric
8247d523365SDimitry Andric // Collect stages for each instruction class for all itinerary data
8257d523365SDimitry Andric for (unsigned j = 0; j < M; j++) {
8267d523365SDimitry Andric Record *ItinData = ItinDataList[j];
8277d523365SDimitry Andric int NStages = collectOneInsnClass(ProcName, ProcItinList,
8287d523365SDimitry Andric FUNameToBitsMap, ItinData, OS);
8297d523365SDimitry Andric if (NStages > maxStages) {
8307d523365SDimitry Andric maxStages = NStages;
8317d523365SDimitry Andric }
8327d523365SDimitry Andric numInsnClasses++;
8337d523365SDimitry Andric }
8347d523365SDimitry Andric return numInsnClasses;
8357d523365SDimitry Andric }
836dff0c46cSDimitry Andric
837dff0c46cSDimitry Andric //
838dff0c46cSDimitry Andric // Run the worklist algorithm to generate the DFA.
839dff0c46cSDimitry Andric //
run(raw_ostream & OS)8407ae0e2c9SDimitry Andric void DFAPacketizerEmitter::run(raw_ostream &OS) {
841dff0c46cSDimitry Andric // Collect processor iteraries.
842dff0c46cSDimitry Andric std::vector<Record*> ProcItinList =
843dff0c46cSDimitry Andric Records.getAllDerivedDefinitions("ProcessorItineraries");
844dff0c46cSDimitry Andric
845dff0c46cSDimitry Andric //
8467d523365SDimitry Andric // Collect the Functional units.
847dff0c46cSDimitry Andric //
8487d523365SDimitry Andric std::map<std::string, unsigned> FUNameToBitsMap;
8497d523365SDimitry Andric int maxResources = 0;
8507d523365SDimitry Andric collectAllFuncUnits(ProcItinList,
8517d523365SDimitry Andric FUNameToBitsMap, maxResources, OS);
8527d523365SDimitry Andric
8537d523365SDimitry Andric //
8547d523365SDimitry Andric // Collect the Combo Functional units.
8557d523365SDimitry Andric //
8567d523365SDimitry Andric std::map<unsigned, unsigned> ComboBitToBitsMap;
8577d523365SDimitry Andric std::vector<Record*> ComboFuncList =
8587d523365SDimitry Andric Records.getAllDerivedDefinitions("ComboFuncUnits");
8597d523365SDimitry Andric int numCombos = collectAllComboFuncs(ComboFuncList,
8607d523365SDimitry Andric FUNameToBitsMap, ComboBitToBitsMap, OS);
8617d523365SDimitry Andric
8627d523365SDimitry Andric //
8637d523365SDimitry Andric // Collect the itineraries.
8647d523365SDimitry Andric //
8657d523365SDimitry Andric int maxStages = 0;
8667d523365SDimitry Andric int numInsnClasses = 0;
867dff0c46cSDimitry Andric for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
868dff0c46cSDimitry Andric Record *Proc = ProcItinList[i];
869dff0c46cSDimitry Andric
870dff0c46cSDimitry Andric // Get processor itinerary name.
8717d523365SDimitry Andric const std::string &ProcName = Proc->getName();
872dff0c46cSDimitry Andric
873dff0c46cSDimitry Andric // Skip default.
8747d523365SDimitry Andric if (ProcName == "NoItineraries")
875dff0c46cSDimitry Andric continue;
876dff0c46cSDimitry Andric
877dff0c46cSDimitry Andric // Sanity check for at least one instruction itinerary class.
878dff0c46cSDimitry Andric unsigned NItinClasses =
879dff0c46cSDimitry Andric Records.getAllDerivedDefinitions("InstrItinClass").size();
880dff0c46cSDimitry Andric if (NItinClasses == 0)
881dff0c46cSDimitry Andric return;
882dff0c46cSDimitry Andric
883dff0c46cSDimitry Andric // Get itinerary data list.
884dff0c46cSDimitry Andric std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID");
885dff0c46cSDimitry Andric
8867d523365SDimitry Andric // Collect all instruction classes
8877d523365SDimitry Andric numInsnClasses += collectAllInsnClasses(ProcName, ProcItinList,
8887d523365SDimitry Andric FUNameToBitsMap, ItinDataList, maxStages, OS);
889dff0c46cSDimitry Andric }
890dff0c46cSDimitry Andric
891dff0c46cSDimitry Andric //
892dff0c46cSDimitry Andric // Run a worklist algorithm to generate the DFA.
893dff0c46cSDimitry Andric //
894dff0c46cSDimitry Andric DFA D;
89591bc56edSDimitry Andric const State *Initial = &D.newState();
896dff0c46cSDimitry Andric Initial->isInitial = true;
897dff0c46cSDimitry Andric Initial->stateInfo.insert(0x0);
89891bc56edSDimitry Andric SmallVector<const State*, 32> WorkList;
89991bc56edSDimitry Andric std::map<std::set<unsigned>, const State*> Visited;
900dff0c46cSDimitry Andric
901dff0c46cSDimitry Andric WorkList.push_back(Initial);
902dff0c46cSDimitry Andric
903dff0c46cSDimitry Andric //
904dff0c46cSDimitry Andric // Worklist algorithm to create a DFA for processor resource tracking.
905dff0c46cSDimitry Andric // C = {set of InsnClasses}
906dff0c46cSDimitry Andric // Begin with initial node in worklist. Initial node does not have
907dff0c46cSDimitry Andric // any consumed resources,
908dff0c46cSDimitry Andric // ResourceState = 0x0
909dff0c46cSDimitry Andric // Visited = {}
910dff0c46cSDimitry Andric // While worklist != empty
911dff0c46cSDimitry Andric // S = first element of worklist
912dff0c46cSDimitry Andric // For every instruction class C
913dff0c46cSDimitry Andric // if we can accommodate C in S:
914dff0c46cSDimitry Andric // S' = state with resource states = {S Union C}
915dff0c46cSDimitry Andric // Add a new transition: S x C -> S'
916dff0c46cSDimitry Andric // If S' is not in Visited:
917dff0c46cSDimitry Andric // Add S' to worklist
918dff0c46cSDimitry Andric // Add S' to Visited
919dff0c46cSDimitry Andric //
920dff0c46cSDimitry Andric while (!WorkList.empty()) {
92191bc56edSDimitry Andric const State *current = WorkList.pop_back_val();
922*4ba319b5SDimitry Andric LLVM_DEBUG({
9237d523365SDimitry Andric dbgs() << "---------------------\n";
9247d523365SDimitry Andric dbgs() << "Processing state: " << current->stateNum << " - ";
9257d523365SDimitry Andric dbgsStateInfo(current->stateInfo);
9267d523365SDimitry Andric dbgs() << "\n";
9277d523365SDimitry Andric });
9287d523365SDimitry Andric for (unsigned i = 0; i < allInsnClasses.size(); i++) {
9297d523365SDimitry Andric std::vector<unsigned> InsnClass = allInsnClasses[i];
930*4ba319b5SDimitry Andric LLVM_DEBUG({
9317d523365SDimitry Andric dbgs() << i << " ";
9327d523365SDimitry Andric dbgsInsnClass(InsnClass);
9337d523365SDimitry Andric dbgs() << "\n";
9347d523365SDimitry Andric });
935dff0c46cSDimitry Andric
936dff0c46cSDimitry Andric std::set<unsigned> NewStateResources;
937dff0c46cSDimitry Andric //
938dff0c46cSDimitry Andric // If we haven't already created a transition for this input
939dff0c46cSDimitry Andric // and the state can accommodate this InsnClass, create a transition.
940dff0c46cSDimitry Andric //
9413861d79fSDimitry Andric if (!current->hasTransition(InsnClass) &&
9427d523365SDimitry Andric current->canMaybeAddInsnClass(InsnClass, ComboBitToBitsMap)) {
9433ca95b02SDimitry Andric const State *NewState = nullptr;
9447d523365SDimitry Andric current->AddInsnClass(InsnClass, ComboBitToBitsMap, NewStateResources);
945d88c1a5aSDimitry Andric if (NewStateResources.empty()) {
946*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " Skipped - no new states generated\n");
9477d523365SDimitry Andric continue;
9487d523365SDimitry Andric }
9497d523365SDimitry Andric
950*4ba319b5SDimitry Andric LLVM_DEBUG({
9517d523365SDimitry Andric dbgs() << "\t";
9527d523365SDimitry Andric dbgsStateInfo(NewStateResources);
9537d523365SDimitry Andric dbgs() << "\n";
9547d523365SDimitry Andric });
955dff0c46cSDimitry Andric
956dff0c46cSDimitry Andric //
957dff0c46cSDimitry Andric // If we have seen this state before, then do not create a new state.
958dff0c46cSDimitry Andric //
95991bc56edSDimitry Andric auto VI = Visited.find(NewStateResources);
9607d523365SDimitry Andric if (VI != Visited.end()) {
961dff0c46cSDimitry Andric NewState = VI->second;
962*4ba319b5SDimitry Andric LLVM_DEBUG({
9637d523365SDimitry Andric dbgs() << "\tFound existing state: " << NewState->stateNum
9647d523365SDimitry Andric << " - ";
9657d523365SDimitry Andric dbgsStateInfo(NewState->stateInfo);
9667d523365SDimitry Andric dbgs() << "\n";
9677d523365SDimitry Andric });
9687d523365SDimitry Andric } else {
96991bc56edSDimitry Andric NewState = &D.newState();
970dff0c46cSDimitry Andric NewState->stateInfo = NewStateResources;
971dff0c46cSDimitry Andric Visited[NewStateResources] = NewState;
972dff0c46cSDimitry Andric WorkList.push_back(NewState);
973*4ba319b5SDimitry Andric LLVM_DEBUG({
9747d523365SDimitry Andric dbgs() << "\tAccepted new state: " << NewState->stateNum << " - ";
9757d523365SDimitry Andric dbgsStateInfo(NewState->stateInfo);
9767d523365SDimitry Andric dbgs() << "\n";
9777d523365SDimitry Andric });
978dff0c46cSDimitry Andric }
979dff0c46cSDimitry Andric
9803861d79fSDimitry Andric current->addTransition(InsnClass, NewState);
981dff0c46cSDimitry Andric }
982dff0c46cSDimitry Andric }
983dff0c46cSDimitry Andric }
984dff0c46cSDimitry Andric
985dff0c46cSDimitry Andric // Print out the table.
9867d523365SDimitry Andric D.writeTableAndAPI(OS, TargetName,
9877d523365SDimitry Andric numInsnClasses, maxResources, numCombos, maxStages);
988dff0c46cSDimitry Andric }
9897ae0e2c9SDimitry Andric
9907ae0e2c9SDimitry Andric namespace llvm {
9917ae0e2c9SDimitry Andric
EmitDFAPacketizer(RecordKeeper & RK,raw_ostream & OS)9927ae0e2c9SDimitry Andric void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS) {
9937ae0e2c9SDimitry Andric emitSourceFileHeader("Target DFA Packetizer Tables", OS);
9947ae0e2c9SDimitry Andric DFAPacketizerEmitter(RK).run(OS);
9957ae0e2c9SDimitry Andric }
9967ae0e2c9SDimitry Andric
997d88c1a5aSDimitry Andric } // end namespace llvm
998