Extend the instruction itinerary model to include the ability to indicate the def...
authorDavid Goodwin <david_goodwin@apple.com>
Mon, 17 Aug 2009 16:02:57 +0000 (16:02 +0000)
committerDavid Goodwin <david_goodwin@apple.com>
Mon, 17 Aug 2009 16:02:57 +0000 (16:02 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79247 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetInstrItineraries.h
include/llvm/Target/TargetSchedule.td
lib/CodeGen/ExactHazardRecognizer.cpp
utils/TableGen/SubtargetEmitter.cpp
utils/TableGen/SubtargetEmitter.h

index 237ca4ef2a6308563d6c014bb42ca071f3f31593..9ba9cb61c5b971029bdb39cf3d1eaaabb5aa83e4 100644 (file)
@@ -7,9 +7,9 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file describes the structures used for instruction itineraries and
-// stages.  This is used by schedulers to determine instruction stages and
-// latencies.
+// This file describes the structures used for instruction
+// itineraries, stages, and operand reads/writes.  This is used by
+// schedulers to determine instruction stages and latencies.
 //
 //===----------------------------------------------------------------------===//
 
@@ -71,46 +71,50 @@ struct InstrStage {
 
 
 //===----------------------------------------------------------------------===//
-/// Instruction itinerary - An itinerary represents a sequential series of steps
-/// required to complete an instruction.  Itineraries are represented as
-/// sequences of instruction stages.
+/// Instruction itinerary - An itinerary represents the scheduling
+/// information for an instruction. This includes a set of stages
+/// occupies by the instruction, and the pipeline cycle in which
+/// operands are read and written.
 ///
 struct InstrItinerary {
-  unsigned First;    ///< Index of first stage in itinerary
-  unsigned Last;     ///< Index of last + 1 stage in itinerary
+  unsigned FirstStage;         ///< Index of first stage in itinerary
+  unsigned LastStage;          ///< Index of last + 1 stage in itinerary
+  unsigned FirstOperandCycle;  ///< Index of first operand rd/wr
+  unsigned LastOperandCycle;   ///< Index of last + 1 operand rd/wr
 };
 
 
-
 //===----------------------------------------------------------------------===//
 /// Instruction itinerary Data - Itinerary data supplied by a subtarget to be
 /// used by a target.
 ///
 struct InstrItineraryData {
   const InstrStage     *Stages;         ///< Array of stages selected
+  const unsigned       *OperandCycles;  ///< Array of operand cycles selected
   const InstrItinerary *Itineratries;   ///< Array of itineraries selected
 
   /// Ctors.
   ///
-  InstrItineraryData() : Stages(0), Itineratries(0) {}
-  InstrItineraryData(const InstrStage *S, const InstrItinerary *I)
-    : Stages(S), Itineratries(I) {}
+  InstrItineraryData() : Stages(0), OperandCycles(0), Itineratries(0) {}
+  InstrItineraryData(const InstrStage *S, const unsigned *OS,
+                     const InstrItinerary *I)
+    : Stages(S), OperandCycles(OS), Itineratries(I) {}
   
   /// isEmpty - Returns true if there are no itineraries.
   ///
   bool isEmpty() const { return Itineratries == 0; }
   
-  /// begin - Return the first stage of the itinerary.
+  /// beginStage - Return the first stage of the itinerary.
   /// 
-  const InstrStage *begin(unsigned ItinClassIndx) const {
-    unsigned StageIdx = Itineratries[ItinClassIndx].First;
+  const InstrStage *beginStage(unsigned ItinClassIndx) const {
+    unsigned StageIdx = Itineratries[ItinClassIndx].FirstStage;
     return Stages + StageIdx;
   }
 
-  /// end - Return the last+1 stage of the itinerary.
+  /// endStage - Return the last+1 stage of the itinerary.
   /// 
-  const InstrStage *end(unsigned ItinClassIndx) const {
-    unsigned StageIdx = Itineratries[ItinClassIndx].Last;
+  const InstrStage *endStage(unsigned ItinClassIndx) const {
+    unsigned StageIdx = Itineratries[ItinClassIndx].LastStage;
     return Stages + StageIdx;
   }
 
@@ -129,8 +133,8 @@ struct InstrItineraryData {
     // first stage and that all outputs are produced at the end of the
     // latest completing last stage.
     unsigned Latency = 0, StartCycle = 0;
-    for (const InstrStage *IS = begin(ItinClassIndx), *E = end(ItinClassIndx);
-         IS != E; ++IS) {
+    for (const InstrStage *IS = beginStage(ItinClassIndx),
+           *E = endStage(ItinClassIndx); IS != E; ++IS) {
       Latency = std::max(Latency, StartCycle + IS->getCycles());
       StartCycle += IS->getNextCycles();
     }
index 4940e8b82bd9ddd59a0dddaa54d18941c2cbd58f..b3f566a3c310653384bb87c0aaa42837d2b30ca9 100644 (file)
@@ -62,9 +62,11 @@ def NoItinerary : InstrItinClass;
 // Instruction itinerary data - These values provide a runtime map of an 
 // instruction itinerary class (name) to it's itinerary data.
 //
-class InstrItinData<InstrItinClass Class, list<InstrStage> stages> {
+class InstrItinData<InstrItinClass Class, list<InstrStage> stages,
+                    list<int> operandcycles = []> {
   InstrItinClass TheClass = Class;
   list<InstrStage> Stages = stages;
+  list<int> OperandCycles = operandcycles;
 }
 
 //===----------------------------------------------------------------------===//
index 8bac08a4a05667be51715160e4f6167f1a921849..33ee233dac0e190e2c00cf2fe7e2b602e26bc92b 100644 (file)
@@ -33,7 +33,8 @@ ExactHazardRecognizer::ExactHazardRecognizer(const InstrItineraryData &LItinData
     for (unsigned idx = 0; ; ++idx) {
       // If the begin stage of an itinerary has 0 cycles and units,
       // then we have reached the end of the itineraries.
-      const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx);
+      const InstrStage *IS = ItinData.beginStage(idx);
+      const InstrStage *E = ItinData.endStage(idx);
       if ((IS->getCycles() == 0) && (IS->getUnits() == 0))
         break;
 
@@ -87,8 +88,8 @@ ExactHazardRecognizer::HazardType ExactHazardRecognizer::getHazardType(SUnit *SU
   // Use the itinerary for the underlying instruction to check for
   // free FU's in the scoreboard at the appropriate future cycles.
   unsigned idx = SU->getInstr()->getDesc().getSchedClass();
-  for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx);
-       IS != E; ++IS) {
+  for (const InstrStage *IS = ItinData.beginStage(idx),
+         *E = ItinData.endStage(idx); IS != E; ++IS) {
     // We must find one of the stage's units free for every cycle the
     // stage is occupied. FIXME it would be more accurate to find the
     // same unit free in all the cycles.
@@ -119,8 +120,8 @@ void ExactHazardRecognizer::EmitInstruction(SUnit *SU) {
   // Use the itinerary for the underlying instruction to reserve FU's
   // in the scoreboard at the appropriate future cycles.
   unsigned idx = SU->getInstr()->getDesc().getSchedClass();
-  for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx);
-       IS != E; ++IS) {
+  for (const InstrStage *IS = ItinData.beginStage(idx), 
+         *E = ItinData.endStage(idx); IS != E; ++IS) {
     // We must reserve one of the stage's units for every cycle the
     // stage is occupied. FIXME it would be more accurate to reserve
     // the same unit free in all the cycles.
index 4a0bacd19cf9f307f3a53bdfab922c0bd10f9ca4..9760b171dda1e0d51be40af9e9ccc1a32e310d4e 100644 (file)
@@ -199,12 +199,13 @@ unsigned SubtargetEmitter::CollectAllItinClasses(raw_ostream &OS,
 }
 
 //
-// FormItineraryString - Compose a string containing the data initialization
-// for the specified itinerary.  N is the number of stages.
+// FormItineraryStageString - Compose a string containing the stage
+// data initialization for the specified itinerary.  N is the number
+// of stages.
 //
-void SubtargetEmitter::FormItineraryString(Record *ItinData,
-                                           std::string &ItinString,
-                                           unsigned &NStages) {
+void SubtargetEmitter::FormItineraryStageString(Record *ItinData,
+                                                std::string &ItinString,
+                                                unsigned &NStages) {
   // Get states list
   const std::vector<Record*> &StageList =
     ItinData->getValueAsListOfDefs("Stages");
@@ -239,10 +240,32 @@ void SubtargetEmitter::FormItineraryString(Record *ItinData,
 }
 
 //
-// EmitStageData - Generate unique itinerary stages.  Record itineraries for 
-// processors.
+// FormItineraryOperandCycleString - Compose a string containing the
+// operand cycle initialization for the specified itinerary.  N is the
+// number of operands that has cycles specified.
 //
-void SubtargetEmitter::EmitStageData(raw_ostream &OS,
+void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
+                         std::string &ItinString, unsigned &NOperandCycles) {
+  // Get operand cycle list
+  const std::vector<int64_t> &OperandCycleList =
+    ItinData->getValueAsListOfInts("OperandCycles");
+
+  // For each operand cycle
+  unsigned N = NOperandCycles = OperandCycleList.size();
+  for (unsigned i = 0; i < N;) {
+    // Next operand cycle
+    const int OCycle = OperandCycleList[i];
+  
+    ItinString += "  " + itostr(OCycle);
+    if (++i < N) ItinString += ", ";
+  }
+}
+
+//
+// EmitStageAndOperandCycleData - Generate unique itinerary stages and
+// operand cycle tables.  Record itineraries for processors.
+//
+void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
        unsigned NItinClasses,
        std::map<std::string, unsigned> &ItinClassesMap, 
        std::vector<std::vector<InstrItinerary> > &ProcList) {
@@ -254,12 +277,16 @@ void SubtargetEmitter::EmitStageData(raw_ostream &OS,
   if (ProcItinList.size() < 2) return;
 
   // Begin stages table
-  OS << "static const llvm::InstrStage Stages[] = {\n"
-        "  { 0, 0, 0 }, // No itinerary\n";
+  std::string StageTable = "static const llvm::InstrStage Stages[] = {\n";
+  StageTable += "  { 0, 0, 0 }, // No itinerary\n";
         
-  unsigned StageCount = 1;
-  unsigned ItinEnum = 1;
-  std::map<std::string, unsigned> ItinMap;
+  // Begin operand cycle table
+  std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n";
+  OperandCycleTable += "  0, // No itinerary\n";
+        
+  unsigned StageCount = 1, OperandCycleCount = 1;
+  unsigned ItinStageEnum = 1, ItinOperandCycleEnum = 1;
+  std::map<std::string, unsigned> ItinStageMap, ItinOperandCycleMap;
   for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
     // Next record
     Record *Proc = ProcItinList[i];
@@ -283,29 +310,53 @@ void SubtargetEmitter::EmitStageData(raw_ostream &OS,
       Record *ItinData = ItinDataList[j];
       
       // Get string and stage count
-      std::string ItinString;
+      std::string ItinStageString;
       unsigned NStages;
-      FormItineraryString(ItinData, ItinString, NStages);
-
-      // Check to see if it already exists
-      unsigned Find = ItinMap[ItinString];
+      FormItineraryStageString(ItinData, ItinStageString, NStages);
+
+      // Get string and operand cycle count
+      std::string ItinOperandCycleString;
+      unsigned NOperandCycles;
+      FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
+                                      NOperandCycles);
+
+      // Check to see if stage already exists and create if it doesn't
+      unsigned FindStage = 0;
+      if (NStages > 0) {
+        FindStage = ItinStageMap[ItinStageString];
+        if (FindStage == 0) {
+          // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // index
+          StageTable += ItinStageString + ", // " + itostr(ItinStageEnum) + "\n";
+          // Record Itin class number.
+          ItinStageMap[ItinStageString] = FindStage = StageCount;
+          StageCount += NStages;
+          ItinStageEnum++;
+        }
+      }
       
-      // If new itinerary
-      if (Find == 0) {
-        // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // index
-        OS << ItinString << ", // " << ItinEnum << "\n";
-        // Record Itin class number.
-        ItinMap[ItinString] = Find = StageCount;
-        StageCount += NStages;
-        ItinEnum++;
+      // Check to see if operand cycle already exists and create if it doesn't
+      unsigned FindOperandCycle = 0;
+      if (NOperandCycles > 0) {
+        FindOperandCycle = ItinOperandCycleMap[ItinOperandCycleString];
+        if (FindOperandCycle == 0) {
+          // Emit as  cycle, // index
+          OperandCycleTable += ItinOperandCycleString + ", // " + 
+            itostr(ItinOperandCycleEnum) + "\n";
+          // Record Itin class number.
+          ItinOperandCycleMap[ItinOperandCycleString] = 
+            FindOperandCycle = OperandCycleCount;
+          OperandCycleCount += NOperandCycles;
+          ItinOperandCycleEnum++;
+        }
       }
       
       // Set up itinerary as location and location + stage count
-      InstrItinerary Intinerary = { Find, Find + NStages };
+      InstrItinerary Intinerary = { FindStage, FindStage + NStages,
+                                    FindOperandCycle, FindOperandCycle + NOperandCycles};
 
       // Locate where to inject into processor itinerary table
       const std::string &Name = ItinData->getValueAsDef("TheClass")->getName();
-      Find = ItinClassesMap[Name];
+      unsigned Find = ItinClassesMap[Name];
       
       // Inject - empty slots will be 0, 0
       ItinList[Find] = Intinerary;
@@ -316,13 +367,21 @@ void SubtargetEmitter::EmitStageData(raw_ostream &OS,
   }
   
   // Closing stage
-  OS << "  { 0, 0, 0 } // End itinerary\n";
-  // End stages table
-  OS << "};\n";
+  StageTable += "  { 0, 0, 0 } // End itinerary\n";
+  StageTable += "};\n";
+
+  // Closing operand cycles
+  OperandCycleTable += "  0 // End itinerary\n";
+  OperandCycleTable += "};\n";
+
+  // Emit tables.
+  OS << StageTable;
+  OS << OperandCycleTable;
   
-  // Emit size of table
+  // Emit size of tables
   OS<<"\nenum {\n";
-  OS<<"  StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage)\n";
+  OS<<"  StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage),\n";
+  OS<<"  OperandCyclesSize = sizeof(OperandCycles)/sizeof(unsigned)\n";
   OS<<"};\n";
 }
 
@@ -357,11 +416,15 @@ void SubtargetEmitter::EmitProcessorData(raw_ostream &OS,
     for (unsigned j = 0, M = ItinList.size(); j < M;) {
       InstrItinerary &Intinerary = ItinList[j];
       
-      // Emit in the form of { first, last } // index
-      if (Intinerary.First == 0) {
-        OS << "  { 0, 0 }";
+      // Emit in the form of 
+      // { firstStage, lastStage, firstCycle, lastCycle } // index
+      if (Intinerary.FirstStage == 0) {
+        OS << "  { 0, 0, 0, 0 }";
       } else {
-        OS << "  { " << Intinerary.First << ", " << Intinerary.Last << " }";
+        OS << "  { " << Intinerary.FirstStage << ", " << 
+          Intinerary.LastStage << ", " << 
+          Intinerary.FirstOperandCycle << ", " << 
+          Intinerary.LastOperandCycle << " }";
       }
       
       // If more in list add comma
@@ -435,7 +498,7 @@ void SubtargetEmitter::EmitData(raw_ostream &OS) {
   
   if (HasItineraries) {
     // Emit the stage data
-    EmitStageData(OS, NItinClasses, ItinClassesMap, ProcList);
+    EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, ProcList);
     // Emit the processor itinerary data
     EmitProcessorData(OS, ProcList);
     // Emit the processor lookup data
@@ -482,7 +545,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) {
     OS << "\n"
        << "  InstrItinerary *Itinerary = (InstrItinerary *)"
        <<              "Features.getInfo(ProcItinKV, ProcItinKVSize);\n"
-       << "  InstrItins = InstrItineraryData(Stages, Itinerary);\n";
+       << "  InstrItins = InstrItineraryData(Stages, OperandCycles, Itinerary);\n";
   }
 
   OS << "  return Features.getCPU();\n"
index f44278cc15fe74a18e5a7ae75a3a2c401fd17f5f..1d7088fd390235c8d712c99536d11acf53038254 100644 (file)
@@ -34,9 +34,11 @@ class SubtargetEmitter : public TableGenBackend {
   void CPUKeyValues(raw_ostream &OS);
   unsigned CollectAllItinClasses(raw_ostream &OS,
                                std::map<std::string, unsigned> &ItinClassesMap);
-  void FormItineraryString(Record *ItinData, std::string &ItinString,
-                           unsigned &NStages);
-  void EmitStageData(raw_ostream &OS, unsigned NItinClasses,
+  void FormItineraryStageString(Record *ItinData, std::string &ItinString,
+                                unsigned &NStages);
+  void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
+                                       unsigned &NOperandCycles);
+  void EmitStageAndOperandCycleData(raw_ostream &OS, unsigned NItinClasses,
                      std::map<std::string, unsigned> &ItinClassesMap,
                      std::vector<std::vector<InstrItinerary> > &ProcList);
   void EmitProcessorData(raw_ostream &OS,