Allow itineraries to be passed through the Target Machine.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24139 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h
index 7b9cda2..8659ef9 100644
--- a/include/llvm/Target/TargetInstrInfo.h
+++ b/include/llvm/Target/TargetInstrInfo.h
@@ -146,7 +146,6 @@
     return get(Opcode).numOperands;
   }
 
-
   InstrSchedClass getSchedClass(MachineOpCode Opcode) const {
     return get(Opcode).schedClass;
   }
diff --git a/include/llvm/Target/TargetInstrItineraries.h b/include/llvm/Target/TargetInstrItineraries.h
index 3a622c7..3be5b95 100644
--- a/include/llvm/Target/TargetInstrItineraries.h
+++ b/include/llvm/Target/TargetInstrItineraries.h
@@ -16,6 +16,8 @@
 #ifndef LLVM_TARGET_TARGETINSTRITINERARIES_H
 #define LLVM_TARGET_TARGETINSTRITINERARIES_H
 
+#include "llvm/Support/Debug.h"
+
 namespace llvm {
 
 //===----------------------------------------------------------------------===//
@@ -41,6 +43,56 @@
 };
 
 
+
+//===----------------------------------------------------------------------===//
+// Instruction itinerary Data - Itinerary data supplied by a subtarget to be
+// used by a target.
+//
+class InstrItineraryData {
+  InstrStage     *Stages;         // Array of stages selected
+  unsigned        NStages;        // Number of stages
+  InstrItinerary *Itineratries;   // Array of itineraries selected
+  unsigned        NItineraries;   // Number of itineraries (actually classes)
+
+public:
+
+  //
+  // Ctors.
+  //
+  InstrItineraryData()
+  : Stages(NULL), NStages(0), Itineratries(NULL), NItineraries(0)
+  {}
+  InstrItineraryData(InstrStage *S, unsigned NS, InstrItinerary *I, unsigned NI)
+  : Stages(S), NStages(NS), Itineratries(I), NItineraries(NI)
+  {}
+  
+  //
+  // isEmpty - Returns true if there are no itineraries.
+  //
+  inline bool isEmpty() const { return NItineraries == 0; }
+  
+  //
+  // begin - Return the first stage of the itinerary.
+  // 
+  inline InstrStage *begin(unsigned ItinClassIndx) const {
+    assert(ItinClassIndx < NItineraries && "Itinerary index out of range");
+    unsigned StageIdx = Itineratries[ItinClassIndx].First;
+    assert(StageIdx < NStages && "Stage index out of range");
+    return Stages + StageIdx;
+  }
+
+  //
+  // end - Return the last+1 stage of the itinerary.
+  // 
+  inline InstrStage *end(unsigned ItinClassIndx) const {
+    assert(ItinClassIndx < NItineraries && "Itinerary index out of range");
+    unsigned StageIdx = Itineratries[ItinClassIndx].Last;
+    assert(StageIdx < NStages && "Stage index out of range");
+    return Stages + StageIdx;
+  }
+};
+
+
 } // End llvm namespace
 
 #endif
diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h
index 9c026cc4..aae7d90 100644
--- a/include/llvm/Target/TargetMachine.h
+++ b/include/llvm/Target/TargetMachine.h
@@ -15,6 +15,7 @@
 #define LLVM_TARGET_TARGETMACHINE_H
 
 #include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetInstrItineraries.h"
 #include <cassert>
 
 namespace llvm {
@@ -122,6 +123,13 @@
   /// otherwise return null.
   ///
   virtual TargetJITInfo *getJITInfo() { return 0; }
+  
+  /// getInstrItineraryData - Returns instruction itinerary data for the target
+  /// or specific subtarget.
+  ///
+  virtual const InstrItineraryData getInstrItineraryData() const {  
+    return InstrItineraryData();
+  }
 
   // These are deprecated interfaces.
   virtual const TargetSchedInfo        *getSchedInfo() const { return 0; }
diff --git a/lib/Target/PowerPC/PPCSubtarget.cpp b/lib/Target/PowerPC/PPCSubtarget.cpp
index 94af54c..442017d 100644
--- a/lib/Target/PowerPC/PPCSubtarget.cpp
+++ b/lib/Target/PowerPC/PPCSubtarget.cpp
@@ -71,6 +71,7 @@
 
 PPCSubtarget::PPCSubtarget(const Module &M, const std::string &FS)
   : StackAlignment(16)
+  , InstrItins()
   , IsGigaProcessor(false)
   , Is64Bit(false)
   , Has64BitRegs(false)
diff --git a/lib/Target/PowerPC/PPCSubtarget.h b/lib/Target/PowerPC/PPCSubtarget.h
index a457751..3f1454c 100644
--- a/lib/Target/PowerPC/PPCSubtarget.h
+++ b/lib/Target/PowerPC/PPCSubtarget.h
@@ -14,6 +14,7 @@
 #ifndef POWERPCSUBTARGET_H
 #define POWERPCSUBTARGET_H
 
+#include "llvm/Target/TargetInstrItineraries.h"
 #include "llvm/Target/TargetSubtarget.h"
 
 #include <string>
@@ -26,6 +27,9 @@
   /// stackAlignment - The minimum alignment known to hold of the stack frame on
   /// entry to the function and which must be maintained by every function.
   unsigned StackAlignment;
+  
+  /// Selected instruction itineraries (one entry per itinerary class.)
+  InstrItineraryData InstrItins;
 
   /// Used by the ISel to turn in optimizations for POWER4-derived architectures
   bool IsGigaProcessor;
@@ -49,6 +53,11 @@
   /// stack frame on entry to the function and which must be maintained by every
   /// function for this subtarget.
   unsigned getStackAlignment() const { return StackAlignment; }
+  
+  /// getInstrItins - Return the instruction itineraies based on subtarget 
+  /// selection.
+  const InstrItineraryData getInstrItineraryData() const { return InstrItins; }
+  
 
   bool hasFSQRT() const { return HasFSQRT; }
   bool has64BitRegs() const { return Has64BitRegs; }
diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp
index bd31e97..9a88750 100644
--- a/lib/Target/PowerPC/PPCTargetMachine.cpp
+++ b/lib/Target/PowerPC/PPCTargetMachine.cpp
@@ -64,7 +64,8 @@
 PPCTargetMachine::PPCTargetMachine(const Module &M, IntrinsicLowering *IL,
                                    const std::string &FS)
 : TargetMachine("PowerPC", IL, false, 4, 4, 4, 4, 4, 4, 2, 1, 1),
-  Subtarget(M, FS), FrameInfo(*this, false), JITInfo(*this) {
+  Subtarget(M, FS), FrameInfo(*this, false), JITInfo(*this),
+  InstrItins(Subtarget.getInstrItineraryData()) {
   if (TargetDefault == PPCTarget) {
     if (Subtarget.isAIX()) PPCTarget = TargetAIX;
     if (Subtarget.isDarwin()) PPCTarget = TargetDarwin;
diff --git a/lib/Target/PowerPC/PPCTargetMachine.h b/lib/Target/PowerPC/PPCTargetMachine.h
index 5ba4f32..1295a59 100644
--- a/lib/Target/PowerPC/PPCTargetMachine.h
+++ b/lib/Target/PowerPC/PPCTargetMachine.h
@@ -27,10 +27,11 @@
 class IntrinsicLowering;
 
 class PPCTargetMachine : public TargetMachine {
-  PPCInstrInfo    InstrInfo;
-  PPCSubtarget    Subtarget;
-  PPCFrameInfo    FrameInfo;
-  PPCJITInfo      JITInfo;
+  PPCInstrInfo           InstrInfo;
+  PPCSubtarget           Subtarget;
+  PPCFrameInfo           FrameInfo;
+  PPCJITInfo             JITInfo;
+  InstrItineraryData     InstrItins;
 public:
   PPCTargetMachine(const Module &M, IntrinsicLowering *IL,
                    const std::string &FS);
@@ -42,6 +43,10 @@
   virtual const MRegisterInfo    *getRegisterInfo() const {
     return &InstrInfo.getRegisterInfo();
   }
+  virtual const InstrItineraryData getInstrItineraryData() const {  
+    return InstrItins;
+  }
+  
 
   static unsigned getJITMatchQuality();
 
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index c911ad3..3f7d5db 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -247,7 +247,7 @@
 
   for (unsigned i = 0, N = DefList.size(); i < N; i++) {
     Record *Def = DefList[i];
-    ItinClassMap[Def->getName()] = i + 1;
+    ItinClassMap[Def->getName()] = i;
   }
 }  
   
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index 9eb1f67..0ec7803 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -178,8 +178,8 @@
 // CollectAllItinClasses - Gathers and enumerates all the itinerary classes.
 // Returns itinerary class count.
 //
-unsigned SubtargetEmitter::CollectAllItinClasses(std::map<std::string, unsigned>
-                                                              &ItinClassesMap) {
+unsigned SubtargetEmitter::CollectAllItinClasses(std::ostream &OS,
+                              std::map<std::string, unsigned> &ItinClassesMap) {
   // Gather and sort all itinerary classes
   std::vector<Record*> ItinClassList =
                             Records.getAllDerivedDefinitions("InstrItinClass");
@@ -196,6 +196,11 @@
     ItinClassesMap[Name] = i;
   }
   
+  // Emit size of table
+  OS<<"\nenum {\n";
+  OS<<"  ItinClassesSize = " << N << "\n";
+  OS<<"};\n";
+
   // Return itinerary class count
   return N;
 }
@@ -313,6 +318,11 @@
   
   // End stages table
   OS << "};\n";
+  
+  // Emit size of table
+  OS<<"\nenum {\n";
+  OS<<"  StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage)\n";
+  OS<<"};\n";
 }
 
 //
@@ -421,13 +431,18 @@
   std::vector<std::vector<InstrItinerary> > ProcList;
   
   // Enumerate all the itinerary classes
-  unsigned NItinClasses = CollectAllItinClasses(ItinClassesMap);
-  // Emit the stage data
-  EmitStageData(OS, NItinClasses, ItinClassesMap, ProcList);
-  // Emit the processor itinerary data
-  EmitProcessorData(OS, ProcList);
-  // Emit the processor lookup data
-  EmitProcessorLookup(OS);
+  unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap);
+  // Make sure the rest is worth the effort
+  HasItineraries = NItinClasses != 0;
+  
+  if (HasItineraries) {
+    // Emit the stage data
+    EmitStageData(OS, NItinClasses, ItinClassesMap, ProcList);
+    // Emit the processor itinerary data
+    EmitProcessorData(OS, ProcList);
+    // Emit the processor lookup data
+    EmitProcessorLookup(OS);
+  }
 }
 
 //
@@ -460,9 +475,15 @@
     
     OS << "  " << Attribute << " = (Bits & " << Instance << ") != 0;\n";
   }
-  OS << "\n"
-     << "  InstrItinerary *Itin = (InstrItinerary *)"
-                        "Features.getInfo(SubTypeInfoKV, SubTypeInfoKVSize);\n";
+  
+  if (HasItineraries) {
+    OS << "\n"
+       << "  InstrItinerary *Itinerary = (InstrItinerary *)"
+                        "Features.getInfo(SubTypeInfoKV, SubTypeInfoKVSize);\n"
+          "  InstrItins = InstrItineraryData(Stages, StagesSize, "
+                                             "Itinerary, ItinClassesSize);\n";
+  }
+  
   OS << "}\n";
 }
 
diff --git a/utils/TableGen/SubtargetEmitter.h b/utils/TableGen/SubtargetEmitter.h
index f882f1d..69feeb2 100644
--- a/utils/TableGen/SubtargetEmitter.h
+++ b/utils/TableGen/SubtargetEmitter.h
@@ -27,12 +27,13 @@
   
   RecordKeeper &Records;
   std::string Target;
+  bool HasItineraries;
   
   void Enumeration(std::ostream &OS, const char *ClassName, bool isBits);
   void FeatureKeyValues(std::ostream &OS);
   void CPUKeyValues(std::ostream &OS);
-  unsigned CollectAllItinClasses(std::map<std::string, unsigned>
-                                                               &ItinClassesMap);
+  unsigned CollectAllItinClasses(std::ostream &OS,
+                               std::map<std::string, unsigned> &ItinClassesMap);
   void FormItineraryString(Record *ItinData, std::string &ItinString,
                            unsigned &NStages);
   void EmitStageData(std::ostream &OS, unsigned NItinClasses,
@@ -45,7 +46,7 @@
   void ParseFeaturesFunction(std::ostream &OS);
   
 public:
-  SubtargetEmitter(RecordKeeper &R) : Records(R) {}
+  SubtargetEmitter(RecordKeeper &R) : Records(R), HasItineraries(false) {}
 
   // run - Output the subtarget enumerations, returning true on failure.
   void run(std::ostream &o);