]> granicus.if.org Git - llvm/commitdiff
[DFAPacketizer] Allow namespacing of automata per-itinerary
authorJames Molloy <jmolloy@google.com>
Fri, 30 Aug 2019 19:50:49 +0000 (19:50 +0000)
committerJames Molloy <jmolloy@google.com>
Fri, 30 Aug 2019 19:50:49 +0000 (19:50 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@370508 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetItinerary.td
utils/TableGen/DFAPacketizerEmitter.cpp

index b68ed045520ca8693ba40f8079e4e57680d82dc6..89e5abd947d07602c86975fa363cfd94348493e5 100644 (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
index 0d6bcfe428c9c11a50457dca17b352d01f3878ef..19a6580c1d4d3c05e5fb07a4e3e1e24d3597f47b 100644 (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 {