1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 11:13:28 +01:00

[DFAPacketizer] Allow namespacing of automata per-itinerary

The Hexagon itineraries are cunningly crafted such that functional units between
itineraries do not clash. Because all itineraries are bundled into the same DFA,
a functional unit index clash would cause an incorrect DFA to be generated.

A workaround for this is to ensure all itineraries declare the universe of all
possible functional units, but this isn't ideal for three reasons:
  1) We only have a limited number of FUs we can encode in the packetizer, and
     using the universe causes us to hit the limit without care.
  2) Silent codegen faults are bad, and careful triage of the FU list shouldn't
     be required.
  3) Smooshing all itineraries into the same automaton allows combinations of
     instruction classes that cannot exist, which bloats the table.

A simple solution is to allow "namespacing" packetizers.

Differential Revision: https://reviews.llvm.org/D66940

llvm-svn: 370508
This commit is contained in:
James Molloy 2019-08-30 19:50:49 +00:00
parent 699fc8965e
commit 74fb57df4f
2 changed files with 52 additions and 24 deletions

View File

@ -127,6 +127,17 @@ class ProcessorItineraries<list<FuncUnit> fu, list<Bypass> bp,
list<FuncUnit> FU = fu;
list<Bypass> BP = bp;
list<InstrItinData> IID = iid;
// The packetizer automaton to use for this itinerary. By default all
// itineraries for a target are bundled up into the same automaton. This only
// works correctly when there are no conflicts in functional unit IDs between
// itineraries. For example, given two itineraries A<[SLOT_A]>, B<[SLOT_B]>,
// SLOT_A and SLOT_B will be assigned the same functional unit index, and
// the generated packetizer will confuse instructions referencing these slots.
//
// To avoid this, setting PacketizerNamespace to non-"" will cause this
// itinerary to be generated in a different automaton. The subtarget will need
// to declare a method "create##Namespace##DFAPacketizer()".
string PacketizerNamespace = "";
}
// NoItineraries - A marker that can be used by processors without schedule

View File

@ -29,6 +29,7 @@
#include <map>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>
using namespace llvm;
@ -154,6 +155,11 @@ public:
int &maxStages,
raw_ostream &OS);
// Emit code for a subset of itineraries.
void emitForItineraries(raw_ostream &OS,
std::vector<Record *> &ProcItinList,
std::string DFAName);
void run(raw_ostream &OS);
};
@ -545,14 +551,6 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName,
LLVM_DEBUG(dbgs() << "writeTableAndAPI\n");
LLVM_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";
@ -626,21 +624,7 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName,
// Print out the index to the sentinel entry in StateInputTable
OS << ValidTransitions << ", ";
OS << " // states " << (lastState+1) << ":" << numStates << "\n";
OS << "};\n";
OS << "} // end namespace llvm\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 namespace llvm\n";
}
//
@ -837,10 +821,32 @@ int DFAPacketizerEmitter::collectAllInsnClasses(const std::string &ProcName,
// Run the worklist algorithm to generate the DFA.
//
void DFAPacketizerEmitter::run(raw_ostream &OS) {
OS << "\n"
<< "#include \"llvm/CodeGen/DFAPacketizer.h\"\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";
// Collect processor iteraries.
std::vector<Record*> ProcItinList =
Records.getAllDerivedDefinitions("ProcessorItineraries");
std::unordered_map<std::string, std::vector<Record*>> ItinsByNamespace;
for (Record *R : ProcItinList)
ItinsByNamespace[R->getValueAsString("PacketizerNamespace")].push_back(R);
for (auto &KV : ItinsByNamespace)
emitForItineraries(OS, KV.second, KV.first);
OS << "} // end namespace llvm\n";
}
void DFAPacketizerEmitter::emitForItineraries(
raw_ostream &OS, std::vector<Record *> &ProcItinList,
std::string DFAName) {
//
// Collect the Functional units.
//
@ -982,8 +988,19 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
}
// Print out the table.
D.writeTableAndAPI(OS, TargetName,
numInsnClasses, maxResources, numCombos, maxStages);
D.writeTableAndAPI(OS, TargetName + DFAName, numInsnClasses, maxResources,
numCombos, maxStages);
OS << "} // end namespace llvm\n";
std::string SubTargetClassName = TargetName + "GenSubtargetInfo";
OS << "namespace llvm {\n";
OS << "DFAPacketizer *" << SubTargetClassName << "::"
<< "create" << DFAName
<< "DFAPacketizer(const InstrItineraryData *IID) const {\n"
<< " return new DFAPacketizer(IID, " << TargetName << DFAName
<< "DFAStateInputTable, " << TargetName << DFAName
<< "DFAStateEntryTable);\n}\n\n";
}
namespace llvm {