misched: Added MultiIssueItineraries.
authorAndrew Trick <atrick@apple.com>
Tue, 5 Jun 2012 03:44:40 +0000 (03:44 +0000)
committerAndrew Trick <atrick@apple.com>
Tue, 5 Jun 2012 03:44:40 +0000 (03:44 +0000)
This allows a subtarget to explicitly specify the issue width and
other properties without providing pipeline stage details for every
instruction.

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

12 files changed:
include/llvm/MC/MCInstrItineraries.h
include/llvm/Target/TargetSchedule.td
lib/CodeGen/ScoreboardHazardRecognizer.cpp
lib/CodeGen/SelectionDAG/ResourcePriorityQueue.cpp
lib/MC/MCSubtargetInfo.cpp
lib/Target/ARM/ARMSubtarget.cpp
lib/Target/Hexagon/HexagonSchedule.td
lib/Target/Hexagon/HexagonScheduleV4.td
lib/Target/Hexagon/HexagonSubtarget.cpp
lib/Target/MBlaze/MBlazeSubtarget.cpp
utils/TableGen/SubtargetEmitter.cpp
utils/TableGen/SubtargetEmitter.h

index e942892da13e4083b8f0c0cf9df6033251c60636..199489599e4d4a0643d6d0d048eff685e3c284df 100644 (file)
@@ -103,27 +103,86 @@ struct InstrItinerary {
 };
 
 
+//===----------------------------------------------------------------------===//
+/// Instruction itinerary properties - These properties provide general
+/// information about the microarchitecture to the scheduler.
+///
+struct InstrItineraryProps {
+  // IssueWidth is the maximum number of instructions that may be scheduled in
+  // the same per-cycle group.
+  unsigned IssueWidth;
+
+  // MinLatency is the minimum latency between a register write
+  // followed by a data dependent read. This determines which
+  // instructions may be scheduled in the same per-cycle group. This
+  // is distinct from *expected* latency, which determines the likely
+  // critical path but does not guarantee a pipeline
+  // hazard. MinLatency can always be overridden by the number of
+  // InstrStage cycles.
+  //
+  // (-1) Standard in-order processor.
+  //      Use InstrItinerary OperandCycles as MinLatency.
+  //      If no OperandCycles exist, then use the cycle of the last InstrStage.
+  //
+  //  (0) Out-of-order processor, or in-order with bundled dependencies.
+  //      RAW dependencies may be dispatched in the same cycle.
+  //      Optional InstrItinerary OperandCycles provides expected latency.
+  //
+  // (>0) In-order processor with variable latencies.
+  //      Use the greater of this value or the cycle of the last InstrStage.
+  //      Optional InstrItinerary OperandCycles provides expected latency.
+  //      TODO: can't yet specify both min and expected latency per operand.
+  int MinLatency;
+
+  // LoadLatency is the expected latency of load instructions.
+  //
+  // If MinLatency >= 0, this may be overriden for individual load opcodes by
+  // InstrItinerary OperandCycles.
+  unsigned LoadLatency;
+
+  // HighLatency is the expected latency of "very high latency" operations.
+  // See TargetInstrInfo::isHighLatencyDef().
+  // By default, this is set to an arbitrarily high number of cycles
+  // likely to have some impact on scheduling heuristics.
+  // If MinLatency >= 0, this may be overriden by InstrItinData OperandCycles.
+  unsigned HighLatency;
+
+  InstrItineraryProps(): IssueWidth(1), MinLatency(-1), LoadLatency(4),
+                         HighLatency(10) {}
+
+  InstrItineraryProps(unsigned iw, int ml, unsigned ll, unsigned hl):
+    IssueWidth(iw), MinLatency(ml), LoadLatency(ll), HighLatency(hl) {}
+};
+
+//===----------------------------------------------------------------------===//
+/// Encapsulate all subtarget specific information for scheduling for use with
+/// SubtargetInfoKV.
+struct InstrItinerarySubtargetValue {
+  const InstrItineraryProps *Props;
+  const InstrItinerary *Itineraries;
+};
+
 //===----------------------------------------------------------------------===//
 /// Instruction itinerary Data - Itinerary data supplied by a subtarget to be
 /// used by a target.
 ///
 class InstrItineraryData {
 public:
+  InstrItineraryProps Props;
   const InstrStage     *Stages;         ///< Array of stages selected
   const unsigned       *OperandCycles;  ///< Array of operand cycles selected
   const unsigned       *Forwardings;    ///< Array of pipeline forwarding pathes
   const InstrItinerary *Itineraries;    ///< Array of itineraries selected
-  unsigned              IssueWidth;     ///< Max issue per cycle. 0=Unknown.
 
   /// Ctors.
   ///
   InstrItineraryData() : Stages(0), OperandCycles(0), Forwardings(0),
-                         Itineraries(0), IssueWidth(0) {}
+                         Itineraries(0) {}
 
-  InstrItineraryData(const InstrStage *S, const unsigned *OS,
-                     const unsigned *F, const InstrItinerary *I)
-    : Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(I),
-      IssueWidth(0) {}
+  InstrItineraryData(const InstrItineraryProps *P, const InstrStage *S,
+                     const unsigned *OS, const unsigned *F,
+                     const InstrItinerary *I)
+    : Props(*P), Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(I) {}
 
   /// isEmpty - Returns true if there are no itineraries.
   ///
@@ -160,7 +219,7 @@ public:
     // non-zero default value for all instructions.  Some target's provide a
     // dummy (Generic) itinerary which should be handled as if it's itinerary is
     // empty. We identify this by looking for a reference to stage zero (invalid
-    // stage). This is different from beginStage == endState != 0, which could
+    // stage). This is different from beginStage == endStage != 0, which could
     // be used for zero-latency pseudo ops.
     if (isEmpty() || Itineraries[ItinClassIndx].FirstStage == 0)
       return 1;
index 307fe2d6a04b292b2d7ecc935db4a6d89c36a82e..31e8b17f25823b28c97165dd5ba514cf78ff0f39 100644 (file)
@@ -117,9 +117,16 @@ class InstrItinData<InstrItinClass Class, list<InstrStage> stages,
 // Processor itineraries - These values represent the set of all itinerary
 // classes for a given chip set.
 //
+// Set property values to -1 to use the default.
+// See InstrItineraryProps for comments and defaults.
 class ProcessorItineraries<list<FuncUnit> fu, list<Bypass> bp,
                            list<InstrItinData> iid> {
-  int IssueWidth = 1;
+  int IssueWidth = -1; // Max instructions that may be scheduled per cycle.
+  int MinLatency = -1; // Determines which instrucions are allowed in a group.
+                       // (-1) inorder (0) ooo, (1): inorder +var latencies.
+  int LoadLatency = -1; // Cycles for loads to access the cache.
+  int HighLatency = -1; // Approximation of cycles for "high latency" ops.
+
   list<FuncUnit> FU = fu;
   list<Bypass> BP = bp;
   list<InstrItinData> IID = iid;
@@ -129,3 +136,15 @@ class ProcessorItineraries<list<FuncUnit> fu, list<Bypass> bp,
 // info.
 def NoItineraries : ProcessorItineraries<[], [], []>;
 
+// Processor itineraries with non-unit issue width. This allows issue
+// width to be explicity specified at the beginning of the itinerary.
+class MultiIssueItineraries<int issuewidth, int minlatency,
+                            int loadlatency, int highlatency,
+                            list<FuncUnit> fu, list<Bypass> bp,
+                            list<InstrItinData> iid>
+  : ProcessorItineraries<fu, bp, iid> {
+  let IssueWidth = issuewidth;
+  let MinLatency = minlatency;
+  let LoadLatency = loadlatency;
+  let HighLatency = highlatency;
+}
index ac62d7ef0d47eb3703f2c29ec62f140df8a23b47..7110b7566aba0e32c3e6afd81f7e444cf79e4ad5 100644 (file)
@@ -44,8 +44,6 @@ ScoreboardHazardRecognizer(const InstrItineraryData *II,
   // avoid dealing with the boundary condition.
   unsigned ScoreboardDepth = 1;
   if (ItinData && !ItinData->isEmpty()) {
-    IssueWidth = ItinData->IssueWidth;
-
     for (unsigned idx = 0; ; ++idx) {
       if (ItinData->isEndMarker(idx))
         break;
@@ -74,11 +72,13 @@ ScoreboardHazardRecognizer(const InstrItineraryData *II,
   ReservedScoreboard.reset(ScoreboardDepth);
   RequiredScoreboard.reset(ScoreboardDepth);
 
-  if (!MaxLookAhead)
+  if (!isEnabled())
     DEBUG(dbgs() << "Disabled scoreboard hazard recognizer\n");
-  else
+  else {
+    IssueWidth = ItinData->Props.IssueWidth;
     DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = "
           << ScoreboardDepth << '\n');
+  }
 }
 
 void ScoreboardHazardRecognizer::Reset() {
index 2695163aae56add4ef69af4feeb9b6be0cb76471..01622cb2951c8c4d29b53faa82acc540bc2e2fc3 100644 (file)
@@ -318,7 +318,7 @@ void ResourcePriorityQueue::reserveResources(SUnit *SU) {
 
   // If packet is now full, reset the state so in the next cycle
   // we start fresh.
-  if (Packet.size() >= InstrItins->IssueWidth) {
+  if (Packet.size() >= InstrItins->Props.IssueWidth) {
     ResourcesModel->clearResources();
     Packet.clear();
   }
index 86dc1083cee967e09c46b3aaa652da57b2016454..cb56a54064402a702c5c33ccadfd0b3f39127861 100644 (file)
@@ -91,6 +91,8 @@ MCSubtargetInfo::getInstrItineraryForCPU(StringRef CPU) const {
     return InstrItineraryData();
   }
 
-  return InstrItineraryData(Stages, OperandCycles, ForwardingPathes,
-                            (InstrItinerary *)Found->Value);
+  InstrItinerarySubtargetValue *V =
+    (InstrItinerarySubtargetValue *)Found->Value;
+  return InstrItineraryData(V->Props, Stages, OperandCycles, ForwardingPathes,
+                            V->Itineraries);
 }
index ac568b1a08a0f0c6447f042925a97f81eb9432f4..0bea9e4b2b97e51c751e9c45f8c8c3e075e8235a 100644 (file)
@@ -200,13 +200,14 @@ void ARMSubtarget::computeIssueWidth() {
     const InstrStage *IS = InstrItins.Stages + itin->FirstStage;
     allStage1Units |= IS->getUnits();
   }
-  InstrItins.IssueWidth = 0;
+  InstrItins.Props.IssueWidth = 0;
   while (allStage1Units) {
-    ++InstrItins.IssueWidth;
+    ++InstrItins.Props.IssueWidth;
     // clear the lowest bit
     allStage1Units ^= allStage1Units & ~(allStage1Units - 1);
   }
-  assert(InstrItins.IssueWidth <= 2 && "itinerary bug, too many stage 1 units");
+  assert(InstrItins.Props.IssueWidth <= 2 &&
+         "itinerary bug, too many stage 1 units");
 }
 
 bool ARMSubtarget::enablePostRAScheduler(
index c4887963895caf2b1c702697cc55eb25a3947c9a..b4df6784e7da1296142f3ac0f2d0ce81d72cd7be 100644 (file)
@@ -41,7 +41,10 @@ def HexagonItineraries :
         InstrItinData<SYS    , [InstrStage<1, [LSUNIT]>]>,
         InstrItinData<MARKER , [InstrStage<1, [LUNIT, LSUNIT, MUNIT, SUNIT]>]>,
         InstrItinData<PSEUDO , [InstrStage<1, [LUNIT, LSUNIT, MUNIT, SUNIT]>]>
-      ]>;
+      ]> {
+  // Max issue per cycle == bundle width.
+  let IssueWidth = 4;
+}
 
 //===----------------------------------------------------------------------===//
 // V4 Machine Info +
index 1d82dbb90e91090afb438037672195685c0b3e4e..8d6f7b2b7a941341bb21947d28809c91cf0b7e2f 100644 (file)
@@ -52,7 +52,11 @@ def HexagonItinerariesV4 :
         InstrItinData<MARKER , [InstrStage<1, [SLOT0, SLOT1, SLOT2, SLOT3]>]>,
         InstrItinData<PREFIX , [InstrStage<1, [SLOT0, SLOT1, SLOT2, SLOT3]>]>,
         InstrItinData<PSEUDO , [InstrStage<1, [SLOT0, SLOT1, SLOT2, SLOT3]>]>
-      ]>;
+      ]> {
+  // Max issue per cycle == bundle width.
+  let IssueWidth = 4;
+}
+
 
 //===----------------------------------------------------------------------===//
 // Hexagon V4 Resource Definitions -
index 8744b7b32c258879e01b3a1bbf199018dd2c9643..ce81a78bf94ed0f9e4a7c41cc5604f7884d2b90d 100644 (file)
@@ -61,9 +61,6 @@ HexagonSubtarget::HexagonSubtarget(StringRef TT, StringRef CPU, StringRef FS):
   // Initialize scheduling itinerary for the specified CPU.
   InstrItins = getInstrItineraryForCPU(CPUString);
 
-  // Max issue per cycle == bundle width.
-  InstrItins.IssueWidth = 4;
-
   if (EnableMemOps)
     UseMemOps = true;
   else
index d12d14245ea3c54919b5366fd787f8acf77bb952..dc2ad29be2a260b42deb274269e787eb1bd5f1bd 100644 (file)
@@ -43,13 +43,6 @@ MBlazeSubtarget::MBlazeSubtarget(const std::string &TT,
 
   // Initialize scheduling itinerary for the specified CPU.
   InstrItins = getInstrItineraryForCPU(CPUName);
-
-  // Compute the issue width of the MBlaze itineraries
-  computeIssueWidth();
-}
-
-void MBlazeSubtarget::computeIssueWidth() {
-  InstrItins.IssueWidth = 1;
 }
 
 bool MBlazeSubtarget::
index 986c50f878652b6ba1b72a25df9b10038856bb11..764fc88c2e50c1e6f1b0a31d31b64ec4d9040163 100644 (file)
@@ -478,6 +478,17 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
   OS << BypassTable;
 }
 
+void SubtargetEmitter::EmitItineraryProp(raw_ostream &OS, const Record *R,
+                                         const char *Name, char Separator) {
+  OS << "  ";
+  int V = R->getValueAsInt(Name);
+  if (V >= 0)
+    OS << V << Separator << " // " << Name;
+  else
+    OS << "DefaultItineraryProps." << Name << Separator;
+  OS << '\n';
+}
+
 //
 // EmitProcessorData - Generate data for processor itineraries.
 //
@@ -485,6 +496,8 @@ void SubtargetEmitter::
 EmitProcessorData(raw_ostream &OS,
                   std::vector<Record*> &ItinClassList,
                   std::vector<std::vector<InstrItinerary> > &ProcList) {
+  OS << "static const llvm::InstrItineraryProps " << "DefaultItineraryProps;";
+
   // Get an iterator for processor itinerary stages
   std::vector<std::vector<InstrItinerary> >::iterator
       ProcListIter = ProcList.begin();
@@ -502,9 +515,19 @@ EmitProcessorData(raw_ostream &OS,
     // Skip default
     if (Name == "NoItineraries") continue;
 
+    // Begin processor itinerary properties
+    OS << "\n";
+    OS << "static const llvm::InstrItineraryProps " << Name << "Props(\n";
+    EmitItineraryProp(OS, Itin, "IssueWidth", ',');
+    EmitItineraryProp(OS, Itin, "MinLatency", ',');
+    EmitItineraryProp(OS, Itin, "LoadLatency", ',');
+    EmitItineraryProp(OS, Itin, "HighLatency", ' ');
+    OS << ");\n";
+
     // Begin processor itinerary table
     OS << "\n";
-    OS << "static const llvm::InstrItinerary " << Name << "[] = {\n";
+    OS << "static const llvm::InstrItinerary " << Name << "Entries"
+       << "[] = {\n";
 
     // For each itinerary class
     std::vector<InstrItinerary> &ItinList = *ProcListIter++;
@@ -531,6 +554,13 @@ EmitProcessorData(raw_ostream &OS,
     // End processor itinerary table
     OS << "  { 1, ~0U, ~0U, ~0U, ~0U } // end marker\n";
     OS << "};\n";
+
+    OS << '\n';
+    OS << "static const llvm::InstrItinerarySubtargetValue "
+       << Name << " = {\n";
+    OS << "  &" << Name << "Props,\n";
+    OS << "  " << Name << "Entries\n";
+    OS << "};\n";
   }
 }
 
index ff01274bd1a7f33e897034885b9f7eb29414a0f7..b153cde6d5e70d69acea227af558c9ce91224752 100644 (file)
@@ -47,6 +47,8 @@ class SubtargetEmitter : public TableGenBackend {
                      std::map<std::string, unsigned> &ItinClassesMap,
                      std::vector<Record*> &ItinClassList,
                      std::vector<std::vector<InstrItinerary> > &ProcList);
+  void EmitItineraryProp(raw_ostream &OS, const Record *R, const char *Name,
+                         char Separator);
   void EmitProcessorData(raw_ostream &OS,
                          std::vector<Record*> &ItinClassList,
                          std::vector<std::vector<InstrItinerary> > &ProcList);