Extend the instruction itinerary model to include the ability to indicate the def and use cycle for each operand. This additional information is optional, so existing itineraries do not need to be changed.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79247 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index 4a0bacd..9760b17 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -199,12 +199,13 @@
 }
 
 //
-// 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 @@
 }
 
 //
-// 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 @@
   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 @@
       Record *ItinData = ItinDataList[j];
       
       // Get string and stage count
-      std::string ItinString;
+      std::string ItinStageString;
       unsigned NStages;
-      FormItineraryString(ItinData, ItinString, NStages);
+      FormItineraryStageString(ItinData, ItinStageString, NStages);
 
-      // Check to see if it already exists
-      unsigned Find = ItinMap[ItinString];
+      // 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 @@
   }
   
   // 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 @@
     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 @@
   
   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 @@
     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"