summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp')
-rw-r--r--contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp997
1 files changed, 997 insertions, 0 deletions
diff --git a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
new file mode 100644
index 0000000..77afff7
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
@@ -0,0 +1,997 @@
+//===- DFAPacketizerEmitter.cpp - Packetization DFA for a VLIW machine-----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class parses the Schedule.td file and produces an API that can be used
+// to reason about whether an instruction can be added to a packet on a VLIW
+// architecture. The class internally generates a deterministic finite
+// automaton (DFA) that models all possible mappings of machine instructions
+// to functional units as instructions are added to a packet.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "dfa-emitter"
+
+#include "CodeGenTarget.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include "llvm/Support/Debug.h"
+#include <list>
+#include <map>
+#include <string>
+#include <queue>
+using namespace llvm;
+
+// --------------------------------------------------------------------
+// Definitions shared between DFAPacketizer.cpp and DFAPacketizerEmitter.cpp
+
+// DFA_MAX_RESTERMS * DFA_MAX_RESOURCES must fit within sizeof DFAInput.
+// This is verified in DFAPacketizer.cpp:DFAPacketizer::DFAPacketizer.
+//
+// e.g. terms x resource bit combinations that fit in uint32_t:
+// 4 terms x 8 bits = 32 bits
+// 3 terms x 10 bits = 30 bits
+// 2 terms x 16 bits = 32 bits
+//
+// e.g. terms x resource bit combinations that fit in uint64_t:
+// 8 terms x 8 bits = 64 bits
+// 7 terms x 9 bits = 63 bits
+// 6 terms x 10 bits = 60 bits
+// 5 terms x 12 bits = 60 bits
+// 4 terms x 16 bits = 64 bits <--- current
+// 3 terms x 21 bits = 63 bits
+// 2 terms x 32 bits = 64 bits
+//
+#define DFA_MAX_RESTERMS 4 // The max # of AND'ed resource terms.
+#define DFA_MAX_RESOURCES 16 // The max # of resource bits in one term.
+
+typedef uint64_t DFAInput;
+typedef int64_t DFAStateInput;
+#define DFA_TBLTYPE "int64_t" // For generating DFAStateInputTable.
+
+namespace {
+ DFAInput addDFAFuncUnits(DFAInput Inp, unsigned FuncUnits) {
+ return (Inp << DFA_MAX_RESOURCES) | FuncUnits;
+ }
+
+ /// Return the DFAInput for an instruction class input vector.
+ /// This function is used in both DFAPacketizer.cpp and in
+ /// DFAPacketizerEmitter.cpp.
+ DFAInput getDFAInsnInput(const std::vector<unsigned> &InsnClass) {
+ DFAInput InsnInput = 0;
+ assert ((InsnClass.size() <= DFA_MAX_RESTERMS) &&
+ "Exceeded maximum number of DFA terms");
+ for (auto U : InsnClass)
+ InsnInput = addDFAFuncUnits(InsnInput, U);
+ return InsnInput;
+ }
+}
+// --------------------------------------------------------------------
+
+#ifndef NDEBUG
+// To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter".
+//
+// dbgsInsnClass - When debugging, print instruction class stages.
+//
+void dbgsInsnClass(const std::vector<unsigned> &InsnClass);
+//
+// dbgsStateInfo - When debugging, print the set of state info.
+//
+void dbgsStateInfo(const std::set<unsigned> &stateInfo);
+//
+// dbgsIndent - When debugging, indent by the specified amount.
+//
+void dbgsIndent(unsigned indent);
+#endif
+
+//
+// class DFAPacketizerEmitter: class that generates and prints out the DFA
+// for resource tracking.
+//
+namespace {
+class DFAPacketizerEmitter {
+private:
+ std::string TargetName;
+ //
+ // allInsnClasses is the set of all possible resources consumed by an
+ // InstrStage.
+ //
+ std::vector<std::vector<unsigned>> allInsnClasses;
+ RecordKeeper &Records;
+
+public:
+ DFAPacketizerEmitter(RecordKeeper &R);
+
+ //
+ // collectAllFuncUnits - Construct a map of function unit names to bits.
+ //
+ int collectAllFuncUnits(std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ int &maxResources,
+ raw_ostream &OS);
+
+ //
+ // collectAllComboFuncs - Construct a map from a combo function unit bit to
+ // the bits of all included functional units.
+ //
+ int collectAllComboFuncs(std::vector<Record*> &ComboFuncList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ raw_ostream &OS);
+
+ //
+ // collectOneInsnClass - Populate allInsnClasses with one instruction class.
+ //
+ int collectOneInsnClass(const std::string &ProcName,
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ Record *ItinData,
+ raw_ostream &OS);
+
+ //
+ // collectAllInsnClasses - Populate allInsnClasses which is a set of units
+ // used in each stage.
+ //
+ int collectAllInsnClasses(const std::string &ProcName,
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ std::vector<Record*> &ItinDataList,
+ int &maxStages,
+ raw_ostream &OS);
+
+ void run(raw_ostream &OS);
+};
+} // End anonymous namespace.
+
+//
+//
+// State represents the usage of machine resources if the packet contains
+// a set of instruction classes.
+//
+// Specifically, currentState is a set of bit-masks.
+// The nth bit in a bit-mask indicates whether the nth resource is being used
+// by this state. The set of bit-masks in a state represent the different
+// possible outcomes of transitioning to this state.
+// For example: consider a two resource architecture: resource L and resource M
+// with three instruction classes: L, M, and L_or_M.
+// From the initial state (currentState = 0x00), if we add instruction class
+// L_or_M we will transition to a state with currentState = [0x01, 0x10]. This
+// represents the possible resource states that can result from adding a L_or_M
+// instruction
+//
+// Another way of thinking about this transition is we are mapping a NDFA with
+// two states [0x01] and [0x10] into a DFA with a single state [0x01, 0x10].
+//
+// A State instance also contains a collection of transitions from that state:
+// a map from inputs to new states.
+//
+namespace {
+class State {
+ public:
+ static int currentStateNum;
+ // stateNum is the only member used for equality/ordering, all other members
+ // can be mutated even in const State objects.
+ const int stateNum;
+ mutable bool isInitial;
+ mutable std::set<unsigned> stateInfo;
+ typedef std::map<std::vector<unsigned>, const State *> TransitionMap;
+ mutable TransitionMap Transitions;
+
+ State();
+
+ bool operator<(const State &s) const {
+ return stateNum < s.stateNum;
+ }
+
+ //
+ // canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass
+ // may be a valid transition from this state i.e., can an instruction of type
+ // InsnClass be added to the packet represented by this state.
+ //
+ // Note that for multiple stages, this quick check does not take into account
+ // any possible resource competition between the stages themselves. That is
+ // enforced in AddInsnClassStages which checks the cross product of all
+ // stages for resource availability (which is a more involved check).
+ //
+ bool canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap) const;
+ //
+ // AddInsnClass - Return all combinations of resource reservation
+ // which are possible from this state (PossibleStates).
+ //
+ // PossibleStates is the set of valid resource states that ensue from valid
+ // transitions.
+ //
+ void AddInsnClass(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ std::set<unsigned> &PossibleStates) const;
+ //
+ // AddInsnClassStages - Return all combinations of resource reservation
+ // resulting from the cross product of all stages for this InsnClass
+ // which are possible from this state (PossibleStates).
+ //
+ void 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) const;
+ //
+ // addTransition - Add a transition from this state given the input InsnClass
+ //
+ void addTransition(std::vector<unsigned> InsnClass, const State *To) const;
+ //
+ // hasTransition - Returns true if there is a transition from this state
+ // given the input InsnClass
+ //
+ bool hasTransition(std::vector<unsigned> InsnClass) const;
+};
+} // End anonymous namespace.
+
+//
+// class DFA: deterministic finite automaton for processor resource tracking.
+//
+namespace {
+class DFA {
+public:
+ DFA();
+
+ // Set of states. Need to keep this sorted to emit the transition table.
+ typedef std::set<State> StateSet;
+ StateSet states;
+
+ State *currentState;
+
+ //
+ // Modify the DFA.
+ //
+ const State &newState();
+
+ //
+ // writeTable: Print out a table representing the DFA.
+ //
+ void writeTableAndAPI(raw_ostream &OS, const std::string &ClassName,
+ int numInsnClasses = 0,
+ int maxResources = 0, int numCombos = 0, int maxStages = 0);
+};
+} // End anonymous namespace.
+
+#ifndef NDEBUG
+// To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter".
+//
+// dbgsInsnClass - When debugging, print instruction class stages.
+//
+void dbgsInsnClass(const std::vector<unsigned> &InsnClass) {
+ DEBUG(dbgs() << "InsnClass: ");
+ for (unsigned i = 0; i < InsnClass.size(); ++i) {
+ if (i > 0) {
+ DEBUG(dbgs() << ", ");
+ }
+ DEBUG(dbgs() << "0x" << utohexstr(InsnClass[i]));
+ }
+ DFAInput InsnInput = getDFAInsnInput(InsnClass);
+ DEBUG(dbgs() << " (input: 0x" << utohexstr(InsnInput) << ")");
+}
+
+//
+// dbgsStateInfo - When debugging, print the set of state info.
+//
+void dbgsStateInfo(const std::set<unsigned> &stateInfo) {
+ DEBUG(dbgs() << "StateInfo: ");
+ unsigned i = 0;
+ for (std::set<unsigned>::iterator SI = stateInfo.begin();
+ SI != stateInfo.end(); ++SI, ++i) {
+ unsigned thisState = *SI;
+ if (i > 0) {
+ DEBUG(dbgs() << ", ");
+ }
+ DEBUG(dbgs() << "0x" << utohexstr(thisState));
+ }
+}
+
+//
+// dbgsIndent - When debugging, indent by the specified amount.
+//
+void dbgsIndent(unsigned indent) {
+ for (unsigned i = 0; i < indent; ++i) {
+ DEBUG(dbgs() << " ");
+ }
+}
+#endif
+
+//
+// Constructors and destructors for State and DFA
+//
+State::State() :
+ stateNum(currentStateNum++), isInitial(false) {}
+
+DFA::DFA(): currentState(nullptr) {}
+
+//
+// addTransition - Add a transition from this state given the input InsnClass
+//
+void State::addTransition(std::vector<unsigned> InsnClass, const State *To)
+ const {
+ assert(!Transitions.count(InsnClass) &&
+ "Cannot have multiple transitions for the same input");
+ Transitions[InsnClass] = To;
+}
+
+//
+// hasTransition - Returns true if there is a transition from this state
+// given the input InsnClass
+//
+bool State::hasTransition(std::vector<unsigned> InsnClass) const {
+ return Transitions.count(InsnClass) > 0;
+}
+
+//
+// AddInsnClass - Return all combinations of resource reservation
+// which are possible from this state (PossibleStates).
+//
+// PossibleStates is the set of valid resource states that ensue from valid
+// transitions.
+//
+void State::AddInsnClass(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ std::set<unsigned> &PossibleStates) const {
+ //
+ // Iterate over all resource states in currentState.
+ //
+ unsigned numstages = InsnClass.size();
+ assert((numstages > 0) && "InsnClass has no stages");
+
+ for (std::set<unsigned>::iterator SI = stateInfo.begin();
+ SI != stateInfo.end(); ++SI) {
+ unsigned thisState = *SI;
+
+ DenseSet<unsigned> VisitedResourceStates;
+
+ DEBUG(dbgs() << " thisState: 0x" << utohexstr(thisState) << "\n");
+ AddInsnClassStages(InsnClass, ComboBitToBitsMap,
+ numstages - 1, numstages,
+ thisState, thisState,
+ VisitedResourceStates, PossibleStates);
+ }
+}
+
+void State::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) const {
+
+ assert((chkstage < numstages) && "AddInsnClassStages: stage out of range");
+ unsigned thisStage = InsnClass[chkstage];
+
+ DEBUG({
+ dbgsIndent((1 + numstages - chkstage) << 1);
+ dbgs() << "AddInsnClassStages " << chkstage << " (0x"
+ << utohexstr(thisStage) << ") from ";
+ dbgsInsnClass(InsnClass);
+ dbgs() << "\n";
+ });
+
+ //
+ // Iterate over all possible resources used in thisStage.
+ // For ex: for thisStage = 0x11, all resources = {0x01, 0x10}.
+ //
+ for (unsigned int j = 0; j < DFA_MAX_RESOURCES; ++j) {
+ unsigned resourceMask = (0x1 << j);
+ if (resourceMask & thisStage) {
+ unsigned combo = ComboBitToBitsMap[resourceMask];
+ if (combo && ((~prevState & combo) != combo)) {
+ DEBUG(dbgs() << "\tSkipped Add 0x" << utohexstr(prevState)
+ << " - combo op 0x" << utohexstr(resourceMask)
+ << " (0x" << utohexstr(combo) <<") cannot be scheduled\n");
+ continue;
+ }
+ //
+ // For each possible resource used in thisStage, generate the
+ // resource state if that resource was used.
+ //
+ unsigned ResultingResourceState = prevState | resourceMask | combo;
+ DEBUG({
+ dbgsIndent((2 + numstages - chkstage) << 1);
+ dbgs() << "0x" << utohexstr(prevState)
+ << " | 0x" << utohexstr(resourceMask);
+ if (combo)
+ dbgs() << " | 0x" << utohexstr(combo);
+ dbgs() << " = 0x" << utohexstr(ResultingResourceState) << " ";
+ });
+
+ //
+ // If this is the final stage for this class
+ //
+ if (chkstage == 0) {
+ //
+ // Check if the resulting resource state can be accommodated in this
+ // packet.
+ // We compute resource OR prevState (originally started as origState).
+ // If the result of the OR is different than origState, it implies
+ // that there is at least one resource that can be used to schedule
+ // thisStage in the current packet.
+ // Insert ResultingResourceState into PossibleStates only if we haven't
+ // processed ResultingResourceState before.
+ //
+ if (ResultingResourceState != prevState) {
+ if (VisitedResourceStates.count(ResultingResourceState) == 0) {
+ VisitedResourceStates.insert(ResultingResourceState);
+ PossibleStates.insert(ResultingResourceState);
+ DEBUG(dbgs() << "\tResultingResourceState: 0x"
+ << utohexstr(ResultingResourceState) << "\n");
+ } else {
+ DEBUG(dbgs() << "\tSkipped Add - state already seen\n");
+ }
+ } else {
+ DEBUG(dbgs() << "\tSkipped Add - no final resources available\n");
+ }
+ } else {
+ //
+ // If the current resource can be accommodated, check the next
+ // stage in InsnClass for available resources.
+ //
+ if (ResultingResourceState != prevState) {
+ DEBUG(dbgs() << "\n");
+ AddInsnClassStages(InsnClass, ComboBitToBitsMap,
+ chkstage - 1, numstages,
+ ResultingResourceState, origState,
+ VisitedResourceStates, PossibleStates);
+ } else {
+ DEBUG(dbgs() << "\tSkipped Add - no resources available\n");
+ }
+ }
+ }
+ }
+}
+
+
+//
+// canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass
+// may be a valid transition from this state i.e., can an instruction of type
+// InsnClass be added to the packet represented by this state.
+//
+// Note that this routine is performing conservative checks that can be
+// quickly executed acting as a filter before calling AddInsnClassStages.
+// Any cases allowed through here will be caught later in AddInsnClassStages
+// which performs the more expensive exact check.
+//
+bool State::canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap) const {
+ for (std::set<unsigned>::const_iterator SI = stateInfo.begin();
+ SI != stateInfo.end(); ++SI) {
+
+ // Check to see if all required resources are available.
+ bool available = true;
+
+ // Inspect each stage independently.
+ // note: This is a conservative check as we aren't checking for
+ // possible resource competition between the stages themselves
+ // The full cross product is examined later in AddInsnClass.
+ for (unsigned i = 0; i < InsnClass.size(); ++i) {
+ unsigned resources = *SI;
+ if ((~resources & InsnClass[i]) == 0) {
+ available = false;
+ break;
+ }
+ // Make sure _all_ resources for a combo function are available.
+ // note: This is a quick conservative check as it won't catch an
+ // unscheduleable combo if this stage is an OR expression
+ // containing a combo.
+ // These cases are caught later in AddInsnClass.
+ unsigned combo = ComboBitToBitsMap[InsnClass[i]];
+ if (combo && ((~resources & combo) != combo)) {
+ DEBUG(dbgs() << "\tSkipped canMaybeAdd 0x" << utohexstr(resources)
+ << " - combo op 0x" << utohexstr(InsnClass[i])
+ << " (0x" << utohexstr(combo) <<") cannot be scheduled\n");
+ available = false;
+ break;
+ }
+ }
+
+ if (available) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+const State &DFA::newState() {
+ auto IterPair = states.insert(State());
+ assert(IterPair.second && "State already exists");
+ return *IterPair.first;
+}
+
+int State::currentStateNum = 0;
+
+DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R):
+ TargetName(CodeGenTarget(R).getName()),
+ allInsnClasses(), Records(R) {}
+
+
+//
+// writeTableAndAPI - Print out a table representing the DFA and the
+// associated API to create a DFA packetizer.
+//
+// Format:
+// DFAStateInputTable[][2] = pairs of <Input, Transition> for all valid
+// transitions.
+// DFAStateEntryTable[i] = Index of the first entry in DFAStateInputTable for
+// the ith state.
+//
+//
+void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName,
+ int numInsnClasses,
+ int maxResources, int numCombos, int maxStages) {
+
+ unsigned numStates = states.size();
+
+ DEBUG(dbgs() << "-----------------------------------------------------------------------------\n");
+ DEBUG(dbgs() << "writeTableAndAPI\n");
+ DEBUG(dbgs() << "Total states: " << numStates << "\n");
+
+ OS << "namespace llvm {\n";
+
+ OS << "\n// Input format:\n";
+ OS << "#define DFA_MAX_RESTERMS " << DFA_MAX_RESTERMS
+ << "\t// maximum AND'ed resource terms\n";
+ OS << "#define DFA_MAX_RESOURCES " << DFA_MAX_RESOURCES
+ << "\t// maximum resource bits in one term\n";
+
+ OS << "\n// " << TargetName << "DFAStateInputTable[][2] = "
+ << "pairs of <Input, NextState> for all valid\n";
+ OS << "// transitions.\n";
+ OS << "// " << numStates << "\tstates\n";
+ OS << "// " << numInsnClasses << "\tinstruction classes\n";
+ OS << "// " << maxResources << "\tresources max\n";
+ OS << "// " << numCombos << "\tcombo resources\n";
+ OS << "// " << maxStages << "\tstages max\n";
+ OS << "const " << DFA_TBLTYPE << " "
+ << TargetName << "DFAStateInputTable[][2] = {\n";
+
+ // This table provides a map to the beginning of the transitions for State s
+ // in DFAStateInputTable.
+ std::vector<int> StateEntry(numStates+1);
+ static const std::string SentinelEntry = "{-1, -1}";
+
+ // Tracks the total valid transitions encountered so far. It is used
+ // to construct the StateEntry table.
+ int ValidTransitions = 0;
+ DFA::StateSet::iterator SI = states.begin();
+ for (unsigned i = 0; i < numStates; ++i, ++SI) {
+ assert ((SI->stateNum == (int) i) && "Mismatch in state numbers");
+ StateEntry[i] = ValidTransitions;
+ for (State::TransitionMap::iterator
+ II = SI->Transitions.begin(), IE = SI->Transitions.end();
+ II != IE; ++II) {
+ OS << "{0x" << utohexstr(getDFAInsnInput(II->first)) << ", "
+ << II->second->stateNum
+ << "},\t";
+ }
+ ValidTransitions += SI->Transitions.size();
+
+ // If there are no valid transitions from this stage, we need a sentinel
+ // transition.
+ if (ValidTransitions == StateEntry[i]) {
+ OS << SentinelEntry << ",\t";
+ ++ValidTransitions;
+ }
+
+ OS << " // state " << i << ": " << StateEntry[i];
+ if (StateEntry[i] != (ValidTransitions-1)) { // More than one transition.
+ OS << "-" << (ValidTransitions-1);
+ }
+ OS << "\n";
+ }
+
+ // Print out a sentinel entry at the end of the StateInputTable. This is
+ // needed to iterate over StateInputTable in DFAPacketizer::ReadTable()
+ OS << SentinelEntry << "\t";
+ OS << " // state " << numStates << ": " << ValidTransitions;
+ OS << "\n";
+
+ OS << "};\n\n";
+ OS << "// " << TargetName << "DFAStateEntryTable[i] = "
+ << "Index of the first entry in DFAStateInputTable for\n";
+ OS << "// "
+ << "the ith state.\n";
+ OS << "// " << numStates << " states\n";
+ OS << "const unsigned int " << TargetName << "DFAStateEntryTable[] = {\n";
+
+ // Multiply i by 2 since each entry in DFAStateInputTable is a set of
+ // two numbers.
+ unsigned lastState = 0;
+ for (unsigned i = 0; i < numStates; ++i) {
+ if (i && ((i % 10) == 0)) {
+ lastState = i-1;
+ OS << " // states " << (i-10) << ":" << lastState << "\n";
+ }
+ OS << StateEntry[i] << ", ";
+ }
+
+ // Print out the index to the sentinel entry in StateInputTable
+ OS << ValidTransitions << ", ";
+ OS << " // states " << (lastState+1) << ":" << numStates << "\n";
+
+ OS << "};\n";
+ OS << "} // namespace\n";
+
+
+ //
+ // Emit DFA Packetizer tables if the target is a VLIW machine.
+ //
+ std::string SubTargetClassName = TargetName + "GenSubtargetInfo";
+ OS << "\n" << "#include \"llvm/CodeGen/DFAPacketizer.h\"\n";
+ OS << "namespace llvm {\n";
+ OS << "DFAPacketizer *" << SubTargetClassName << "::"
+ << "createDFAPacketizer(const InstrItineraryData *IID) const {\n"
+ << " return new DFAPacketizer(IID, " << TargetName
+ << "DFAStateInputTable, " << TargetName << "DFAStateEntryTable);\n}\n\n";
+ OS << "} // End llvm namespace \n";
+}
+
+
+//
+// collectAllFuncUnits - Construct a map of function unit names to bits.
+//
+int DFAPacketizerEmitter::collectAllFuncUnits(
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ int &maxFUs,
+ raw_ostream &OS) {
+ DEBUG(dbgs() << "-----------------------------------------------------------------------------\n");
+ DEBUG(dbgs() << "collectAllFuncUnits");
+ DEBUG(dbgs() << " (" << ProcItinList.size() << " itineraries)\n");
+
+ int totalFUs = 0;
+ // Parse functional units for all the itineraries.
+ for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) {
+ Record *Proc = ProcItinList[i];
+ std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU");
+
+ DEBUG(dbgs() << " FU:" << i
+ << " (" << FUs.size() << " FUs) "
+ << Proc->getName());
+
+
+ // Convert macros to bits for each stage.
+ unsigned numFUs = FUs.size();
+ for (unsigned j = 0; j < numFUs; ++j) {
+ assert ((j < DFA_MAX_RESOURCES) &&
+ "Exceeded maximum number of representable resources");
+ unsigned FuncResources = (unsigned) (1U << j);
+ FUNameToBitsMap[FUs[j]->getName()] = FuncResources;
+ DEBUG(dbgs() << " " << FUs[j]->getName()
+ << ":0x" << utohexstr(FuncResources));
+ }
+ if (((int) numFUs) > maxFUs) {
+ maxFUs = numFUs;
+ }
+ totalFUs += numFUs;
+ DEBUG(dbgs() << "\n");
+ }
+ return totalFUs;
+}
+
+//
+// collectAllComboFuncs - Construct a map from a combo function unit bit to
+// the bits of all included functional units.
+//
+int DFAPacketizerEmitter::collectAllComboFuncs(
+ std::vector<Record*> &ComboFuncList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ raw_ostream &OS) {
+ DEBUG(dbgs() << "-----------------------------------------------------------------------------\n");
+ DEBUG(dbgs() << "collectAllComboFuncs");
+ DEBUG(dbgs() << " (" << ComboFuncList.size() << " sets)\n");
+
+ int numCombos = 0;
+ for (unsigned i = 0, N = ComboFuncList.size(); i < N; ++i) {
+ Record *Func = ComboFuncList[i];
+ std::vector<Record*> FUs = Func->getValueAsListOfDefs("CFD");
+
+ DEBUG(dbgs() << " CFD:" << i
+ << " (" << FUs.size() << " combo FUs) "
+ << Func->getName() << "\n");
+
+ // Convert macros to bits for each stage.
+ for (unsigned j = 0, N = FUs.size(); j < N; ++j) {
+ assert ((j < DFA_MAX_RESOURCES) &&
+ "Exceeded maximum number of DFA resources");
+ Record *FuncData = FUs[j];
+ Record *ComboFunc = FuncData->getValueAsDef("TheComboFunc");
+ const std::vector<Record*> &FuncList =
+ FuncData->getValueAsListOfDefs("FuncList");
+ std::string ComboFuncName = ComboFunc->getName();
+ unsigned ComboBit = FUNameToBitsMap[ComboFuncName];
+ unsigned ComboResources = ComboBit;
+ DEBUG(dbgs() << " combo: " << ComboFuncName
+ << ":0x" << utohexstr(ComboResources) << "\n");
+ for (unsigned k = 0, M = FuncList.size(); k < M; ++k) {
+ std::string FuncName = FuncList[k]->getName();
+ unsigned FuncResources = FUNameToBitsMap[FuncName];
+ DEBUG(dbgs() << " " << FuncName
+ << ":0x" << utohexstr(FuncResources) << "\n");
+ ComboResources |= FuncResources;
+ }
+ ComboBitToBitsMap[ComboBit] = ComboResources;
+ numCombos++;
+ DEBUG(dbgs() << " => combo bits: " << ComboFuncName << ":0x"
+ << utohexstr(ComboBit) << " = 0x"
+ << utohexstr(ComboResources) << "\n");
+ }
+ }
+ return numCombos;
+}
+
+
+//
+// collectOneInsnClass - Populate allInsnClasses with one instruction class
+//
+int DFAPacketizerEmitter::collectOneInsnClass(const std::string &ProcName,
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ Record *ItinData,
+ raw_ostream &OS) {
+ const std::vector<Record*> &StageList =
+ ItinData->getValueAsListOfDefs("Stages");
+
+ // The number of stages.
+ unsigned NStages = StageList.size();
+
+ DEBUG(dbgs() << " " << ItinData->getValueAsDef("TheClass")->getName()
+ << "\n");
+
+ std::vector<unsigned> UnitBits;
+
+ // Compute the bitwise or of each unit used in this stage.
+ for (unsigned i = 0; i < NStages; ++i) {
+ const Record *Stage = StageList[i];
+
+ // Get unit list.
+ const std::vector<Record*> &UnitList =
+ Stage->getValueAsListOfDefs("Units");
+
+ DEBUG(dbgs() << " stage:" << i
+ << " [" << UnitList.size() << " units]:");
+ unsigned dbglen = 26; // cursor after stage dbgs
+
+ // Compute the bitwise or of each unit used in this stage.
+ unsigned UnitBitValue = 0;
+ for (unsigned j = 0, M = UnitList.size(); j < M; ++j) {
+ // Conduct bitwise or.
+ std::string UnitName = UnitList[j]->getName();
+ DEBUG(dbgs() << " " << j << ":" << UnitName);
+ dbglen += 3 + UnitName.length();
+ assert(FUNameToBitsMap.count(UnitName));
+ UnitBitValue |= FUNameToBitsMap[UnitName];
+ }
+
+ if (UnitBitValue != 0)
+ UnitBits.push_back(UnitBitValue);
+
+ while (dbglen <= 64) { // line up bits dbgs
+ dbglen += 8;
+ DEBUG(dbgs() << "\t");
+ }
+ DEBUG(dbgs() << " (bits: 0x" << utohexstr(UnitBitValue) << ")\n");
+ }
+
+ if (UnitBits.size() > 0)
+ allInsnClasses.push_back(UnitBits);
+
+ DEBUG({
+ dbgs() << " ";
+ dbgsInsnClass(UnitBits);
+ dbgs() << "\n";
+ });
+
+ return NStages;
+}
+
+//
+// collectAllInsnClasses - Populate allInsnClasses which is a set of units
+// used in each stage.
+//
+int DFAPacketizerEmitter::collectAllInsnClasses(const std::string &ProcName,
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ std::vector<Record*> &ItinDataList,
+ int &maxStages,
+ raw_ostream &OS) {
+ // Collect all instruction classes.
+ unsigned M = ItinDataList.size();
+
+ int numInsnClasses = 0;
+ DEBUG(dbgs() << "-----------------------------------------------------------------------------\n"
+ << "collectAllInsnClasses "
+ << ProcName
+ << " (" << M << " classes)\n");
+
+ // Collect stages for each instruction class for all itinerary data
+ for (unsigned j = 0; j < M; j++) {
+ Record *ItinData = ItinDataList[j];
+ int NStages = collectOneInsnClass(ProcName, ProcItinList,
+ FUNameToBitsMap, ItinData, OS);
+ if (NStages > maxStages) {
+ maxStages = NStages;
+ }
+ numInsnClasses++;
+ }
+ return numInsnClasses;
+}
+
+//
+// Run the worklist algorithm to generate the DFA.
+//
+void DFAPacketizerEmitter::run(raw_ostream &OS) {
+
+ // Collect processor iteraries.
+ std::vector<Record*> ProcItinList =
+ Records.getAllDerivedDefinitions("ProcessorItineraries");
+
+ //
+ // Collect the Functional units.
+ //
+ std::map<std::string, unsigned> FUNameToBitsMap;
+ int maxResources = 0;
+ collectAllFuncUnits(ProcItinList,
+ FUNameToBitsMap, maxResources, OS);
+
+ //
+ // Collect the Combo Functional units.
+ //
+ std::map<unsigned, unsigned> ComboBitToBitsMap;
+ std::vector<Record*> ComboFuncList =
+ Records.getAllDerivedDefinitions("ComboFuncUnits");
+ int numCombos = collectAllComboFuncs(ComboFuncList,
+ FUNameToBitsMap, ComboBitToBitsMap, OS);
+
+ //
+ // Collect the itineraries.
+ //
+ int maxStages = 0;
+ int numInsnClasses = 0;
+ for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
+ Record *Proc = ProcItinList[i];
+
+ // Get processor itinerary name.
+ const std::string &ProcName = Proc->getName();
+
+ // Skip default.
+ if (ProcName == "NoItineraries")
+ continue;
+
+ // Sanity check for at least one instruction itinerary class.
+ unsigned NItinClasses =
+ Records.getAllDerivedDefinitions("InstrItinClass").size();
+ if (NItinClasses == 0)
+ return;
+
+ // Get itinerary data list.
+ std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID");
+
+ // Collect all instruction classes
+ numInsnClasses += collectAllInsnClasses(ProcName, ProcItinList,
+ FUNameToBitsMap, ItinDataList, maxStages, OS);
+ }
+
+ //
+ // Run a worklist algorithm to generate the DFA.
+ //
+ DFA D;
+ const State *Initial = &D.newState();
+ Initial->isInitial = true;
+ Initial->stateInfo.insert(0x0);
+ SmallVector<const State*, 32> WorkList;
+// std::queue<State*> WorkList;
+ std::map<std::set<unsigned>, const State*> Visited;
+
+ WorkList.push_back(Initial);
+
+ //
+ // Worklist algorithm to create a DFA for processor resource tracking.
+ // C = {set of InsnClasses}
+ // Begin with initial node in worklist. Initial node does not have
+ // any consumed resources,
+ // ResourceState = 0x0
+ // Visited = {}
+ // While worklist != empty
+ // S = first element of worklist
+ // For every instruction class C
+ // if we can accommodate C in S:
+ // S' = state with resource states = {S Union C}
+ // Add a new transition: S x C -> S'
+ // If S' is not in Visited:
+ // Add S' to worklist
+ // Add S' to Visited
+ //
+ while (!WorkList.empty()) {
+ const State *current = WorkList.pop_back_val();
+ DEBUG({
+ dbgs() << "---------------------\n";
+ dbgs() << "Processing state: " << current->stateNum << " - ";
+ dbgsStateInfo(current->stateInfo);
+ dbgs() << "\n";
+ });
+ for (unsigned i = 0; i < allInsnClasses.size(); i++) {
+ std::vector<unsigned> InsnClass = allInsnClasses[i];
+ DEBUG({
+ dbgs() << i << " ";
+ dbgsInsnClass(InsnClass);
+ dbgs() << "\n";
+ });
+
+ std::set<unsigned> NewStateResources;
+ //
+ // If we haven't already created a transition for this input
+ // and the state can accommodate this InsnClass, create a transition.
+ //
+ if (!current->hasTransition(InsnClass) &&
+ current->canMaybeAddInsnClass(InsnClass, ComboBitToBitsMap)) {
+ const State *NewState = NULL;
+ current->AddInsnClass(InsnClass, ComboBitToBitsMap, NewStateResources);
+ if (NewStateResources.size() == 0) {
+ DEBUG(dbgs() << " Skipped - no new states generated\n");
+ continue;
+ }
+
+ DEBUG({
+ dbgs() << "\t";
+ dbgsStateInfo(NewStateResources);
+ dbgs() << "\n";
+ });
+
+ //
+ // If we have seen this state before, then do not create a new state.
+ //
+ auto VI = Visited.find(NewStateResources);
+ if (VI != Visited.end()) {
+ NewState = VI->second;
+ DEBUG({
+ dbgs() << "\tFound existing state: " << NewState->stateNum
+ << " - ";
+ dbgsStateInfo(NewState->stateInfo);
+ dbgs() << "\n";
+ });
+ } else {
+ NewState = &D.newState();
+ NewState->stateInfo = NewStateResources;
+ Visited[NewStateResources] = NewState;
+ WorkList.push_back(NewState);
+ DEBUG({
+ dbgs() << "\tAccepted new state: " << NewState->stateNum << " - ";
+ dbgsStateInfo(NewState->stateInfo);
+ dbgs() << "\n";
+ });
+ }
+
+ current->addTransition(InsnClass, NewState);
+ }
+ }
+ }
+
+ // Print out the table.
+ D.writeTableAndAPI(OS, TargetName,
+ numInsnClasses, maxResources, numCombos, maxStages);
+}
+
+namespace llvm {
+
+void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS) {
+ emitSourceFileHeader("Target DFA Packetizer Tables", OS);
+ DFAPacketizerEmitter(RK).run(OS);
+}
+
+} // End llvm namespace
OpenPOWER on IntegriCloud