[llvm] r370508 - [DFAPacketizer] Allow namespacing of automata per-itinerary

James Molloy via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 30 12:50:50 PDT 2019


Author: jamesm
Date: Fri Aug 30 12:50:49 2019
New Revision: 370508

URL: http://llvm.org/viewvc/llvm-project?rev=370508&view=rev
Log:
[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

Modified:
    llvm/trunk/include/llvm/Target/TargetItinerary.td
    llvm/trunk/utils/TableGen/DFAPacketizerEmitter.cpp

Modified: llvm/trunk/include/llvm/Target/TargetItinerary.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetItinerary.td?rev=370508&r1=370507&r2=370508&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetItinerary.td (original)
+++ llvm/trunk/include/llvm/Target/TargetItinerary.td Fri Aug 30 12:50:49 2019
@@ -127,6 +127,17 @@ class ProcessorItineraries<list<FuncUnit
   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

Modified: llvm/trunk/utils/TableGen/DFAPacketizerEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/DFAPacketizerEmitter.cpp?rev=370508&r1=370507&r2=370508&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/DFAPacketizerEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/DFAPacketizerEmitter.cpp Fri Aug 30 12:50:49 2019
@@ -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 &
   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 &
   // 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::collectAllInsn
 // 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_ostre
   }
 
   // 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 {




More information about the llvm-commits mailing list