Model Cortex-a9 load to SUB, RSB, ADD, ADC, SBC, RSC, CMN, MVN, or CMP
authorEvan Cheng <evan.cheng@apple.com>
Wed, 29 Sep 2010 22:42:35 +0000 (22:42 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Wed, 29 Sep 2010 22:42:35 +0000 (22:42 +0000)
pipeline forwarding path.

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

include/llvm/Target/TargetInstrItineraries.h
lib/CodeGen/ScheduleDAGInstrs.cpp
lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
lib/Target/ARM/ARMInstrThumb2.td
lib/Target/ARM/ARMSchedule.td
lib/Target/ARM/ARMScheduleA8.td
lib/Target/ARM/ARMScheduleA9.td
utils/TableGen/SubtargetEmitter.cpp

index fd193f7318f1318bef9cd5c9672022b05bd64355..380147c650b4ed5448001bf01838052ab65922ea 100644 (file)
@@ -111,14 +111,16 @@ class InstrItineraryData {
 public:
   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
 
   /// Ctors.
   ///
-  InstrItineraryData() : Stages(0), OperandCycles(0), Itineraries(0) {}
+  InstrItineraryData() : Stages(0), OperandCycles(0), Forwardings(0),
+                         Itineraries(0) {}
   InstrItineraryData(const InstrStage *S, const unsigned *OS,
-                     const InstrItinerary *I)
-    : Stages(S), OperandCycles(OS), Itineraries(I) {}
+                     const unsigned *F, const InstrItinerary *I)
+    : Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(I) {}
   
   /// isEmpty - Returns true if there are no itineraries.
   ///
@@ -182,6 +184,53 @@ public:
     return (int)OperandCycles[FirstIdx + OperandIdx];
   }
 
+  /// hasPipelineForwarding - Return true if there is a pipeline forwarding
+  /// between instructions of itinerary classes DefClass and UseClasses so that
+  /// value produced by an instruction of itinerary class DefClass, operand
+  /// index DefIdx can be bypassed when it's read by an instruction of
+  /// itinerary class UseClass, operand index UseIdx.
+  bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx,
+                             unsigned UseClass, unsigned UseIdx) const {
+    unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle;
+    unsigned LastDefIdx = Itineraries[DefClass].LastOperandCycle;
+    if ((FirstDefIdx + DefIdx) >= LastDefIdx)
+      return false;
+    if (Forwardings[FirstDefIdx + DefIdx] == 0)
+      return false;
+
+    unsigned FirstUseIdx = Itineraries[UseClass].FirstOperandCycle;
+    unsigned LastUseIdx = Itineraries[UseClass].LastOperandCycle;
+    if ((FirstUseIdx + UseIdx) >= LastUseIdx)
+      return false;
+
+    return Forwardings[FirstDefIdx + DefIdx] ==
+      Forwardings[FirstUseIdx + UseIdx];
+  }
+
+  /// getOperandLatency - Compute and return the use operand latency of a given
+  /// itinerary class and operand index if the value is produced by an
+  /// instruction of the specified itinerary class and def operand index.
+  int getOperandLatency(unsigned DefClass, unsigned DefIdx,
+                        unsigned UseClass, unsigned UseIdx) const {
+    if (isEmpty())
+      return -1;
+
+    int DefCycle = getOperandCycle(DefClass, DefIdx);
+    if (DefCycle == -1)
+      return -1;
+
+    int UseCycle = getOperandCycle(UseClass, UseIdx);
+    if (UseCycle == -1)
+      return -1;
+
+    UseCycle = DefCycle - UseCycle + 1;
+    if (UseCycle > 0 &&
+        hasPipelineForwarding(DefClass, DefIdx, UseClass, UseIdx))
+      // FIXME: This assumes one cycle benefit for every pipeline forwarding.
+      --UseCycle;
+    return UseCycle;
+  }
+
   /// isMicroCoded - Return true if the instructions in the given class decode
   /// to more than one micro-ops.
   bool isMicroCoded(unsigned ItinClassIndx) const {
index da0b0562e120a807e86c2d1a226d62df16ba6f3c..3d2565dd18c56b7f4e96c379b0d137fbb4c58fbb 100644 (file)
@@ -527,26 +527,23 @@ void ScheduleDAGInstrs::ComputeOperandLatency(SUnit *Def, SUnit *Use,
   MachineInstr *DefMI = Def->getInstr();
   int DefIdx = DefMI->findRegisterDefOperandIdx(Reg);
   if (DefIdx != -1) {
-    int DefCycle = InstrItins->getOperandCycle(DefMI->getDesc().getSchedClass(),
-                                               DefIdx);
-    if (DefCycle >= 0) {
-      MachineInstr *UseMI = Use->getInstr();
-      const unsigned UseClass = UseMI->getDesc().getSchedClass();
-
-      // For all uses of the register, calculate the maxmimum latency
-      int Latency = -1;
-      for (unsigned i = 0, e = UseMI->getNumOperands(); i != e; ++i) {
-        const MachineOperand &MO = UseMI->getOperand(i);
-        if (!MO.isReg() || !MO.isUse())
-          continue;
-        unsigned MOReg = MO.getReg();
-        if (MOReg != Reg)
-          continue;
-
-        int UseCycle = InstrItins->getOperandCycle(UseClass, i);
-        if (UseCycle >= 0)
-          Latency = std::max(Latency, DefCycle - UseCycle + 1);
-      }
+    unsigned DefClass = DefMI->getDesc().getSchedClass();
+    MachineInstr *UseMI = Use->getInstr();
+    unsigned UseClass = UseMI->getDesc().getSchedClass();
+
+    // For all uses of the register, calculate the maxmimum latency
+    int Latency = -1;
+    for (unsigned i = 0, e = UseMI->getNumOperands(); i != e; ++i) {
+      const MachineOperand &MO = UseMI->getOperand(i);
+      if (!MO.isReg() || !MO.isUse())
+        continue;
+      unsigned MOReg = MO.getReg();
+      if (MOReg != Reg)
+        continue;
+
+      int UseCycle = InstrItins->getOperandLatency(DefClass, DefIdx,
+                                                   UseClass, i);
+      Latency = std::max(Latency, UseCycle);
 
       // If we found a latency, then replace the existing dependence latency.
       if (Latency >= 0)
index fbf621d0bb4b6e8b568e565a39a07cf443190eaf..23ff9c5807ccc179a12bdc8fb600d86992549da7 100644 (file)
@@ -457,24 +457,24 @@ void ScheduleDAGSDNodes::ComputeOperandLatency(SDNode *Def, SDNode *Use,
     return;
 
   unsigned DefIdx = Use->getOperand(OpIdx).getResNo();
-  if (Def->isMachineOpcode()) {
-    const TargetInstrDesc &II = TII->get(Def->getMachineOpcode());
-    if (DefIdx >= II.getNumDefs())
-      return;
-    int DefCycle = InstrItins->getOperandCycle(II.getSchedClass(), DefIdx);
-    if (DefCycle < 0)
-      return;
-    int UseCycle = 1;
-    if (Use->isMachineOpcode()) {
-      const unsigned UseClass = TII->get(Use->getMachineOpcode()).getSchedClass();
-      UseCycle = InstrItins->getOperandCycle(UseClass, OpIdx);
-    }
-    if (UseCycle >= 0) {
-      int Latency = DefCycle - UseCycle + 1;
-      if (Latency >= 0)
-        dep.setLatency(Latency);
-    }
+  if (!Def->isMachineOpcode())
+    return;
+
+  const TargetInstrDesc &II = TII->get(Def->getMachineOpcode());
+  if (DefIdx >= II.getNumDefs())
+    return;
+
+  int Latency = 0;
+  if (!Use->isMachineOpcode()) {
+    Latency = InstrItins->getOperandCycle(II.getSchedClass(), DefIdx);
+  } else {
+    unsigned DefClass = II.getSchedClass();
+    unsigned UseClass = TII->get(Use->getMachineOpcode()).getSchedClass();
+    Latency = InstrItins->getOperandLatency(DefClass, DefIdx, UseClass, OpIdx);
   }
+
+  if (Latency >= 0)
+    dep.setLatency(Latency);
 }
 
 void ScheduleDAGSDNodes::dumpNode(const SUnit *SU) const {
index 5ca21aa91973b2efd47d11959440ee0c294ffdcf..25eca70d38fa09d9cfdae762dfdf42b68f0b3a23 100644 (file)
@@ -285,7 +285,7 @@ multiclass T2I_rbin_irs<bits<4> opcod, string opc, PatFrag opnode> {
      let Inst{5-4} = 0b00; // type
    }
    // shifted register
-   def rs : T2sI<(outs rGPR:$dst), (ins rGPR:$rhs, t2_so_reg:$lhs), IIC_iALUsi,
+   def rs : T2sI<(outs rGPR:$dst), (ins rGPR:$rhs, t2_so_reg:$lhs), IIC_iALUsir,
                  opc, "\t$dst, $rhs, $lhs",
                  [(set rGPR:$dst, (opnode t2_so_reg:$lhs, rGPR:$rhs))]> {
      let Inst{31-27} = 0b11101;
@@ -1698,7 +1698,7 @@ defm t2ORN  : T2I_bin_irs<0b0011, "orn",
 // Prefer over of t2EORri ra, rb, -1 because mvn has 16-bit version
 let AddedComplexity = 1 in
 defm t2MVN  : T2I_un_irs <0b0011, "mvn",
-                          IIC_iMOVi, IIC_iMOVr, IIC_iMOVsi,
+                          IIC_iMVNi, IIC_iMVNr, IIC_iMVNsi,
                           UnOpFrag<(not node:$Src)>, 1, 1>;
 
 
index 133a81b195d8267b6432860405e0418e1e89bd77..00d148b8eda1cdb29b0e5a4d72d7d851dc10a415 100644 (file)
@@ -14,6 +14,7 @@ def IIC_iALUx      : InstrItinClass;
 def IIC_iALUi      : InstrItinClass;
 def IIC_iALUr      : InstrItinClass;
 def IIC_iALUsi     : InstrItinClass;
+def IIC_iALUsir    : InstrItinClass;
 def IIC_iALUsr     : InstrItinClass;
 def IIC_iBITi      : InstrItinClass;
 def IIC_iBITr      : InstrItinClass;
index e6b2beae03802afca4aab846de2b07a4acf2c59e..8962ec93efa5a78e57b4acdf40b83a526ef5ebdc 100644 (file)
@@ -36,6 +36,7 @@ def CortexA8Itineraries : ProcessorItineraries<
   InstrItinData<IIC_iALUi ,[InstrStage<1, [A8_Pipe0, A8_Pipe1]>], [2, 2]>,
   InstrItinData<IIC_iALUr ,[InstrStage<1, [A8_Pipe0, A8_Pipe1]>], [2, 2, 2]>,
   InstrItinData<IIC_iALUsi,[InstrStage<1, [A8_Pipe0, A8_Pipe1]>], [2, 2, 1]>,
+  InstrItinData<IIC_iALUsir,[InstrStage<1,[A8_Pipe0, A8_Pipe1]>], [2, 1, 2]>,
   InstrItinData<IIC_iALUsr,[InstrStage<1, [A8_Pipe0, A8_Pipe1]>], [2, 2, 1, 1]>,
   //
   // Bitwise Instructions that produce a result
index 14197c824da874574e463ce275f5f177a039068f..1f4b8d1ab0798baf87cfb2639f6279c7aaec17d4 100644 (file)
@@ -23,10 +23,14 @@ def A9_NPipe   : FuncUnit; // NEON ALU/MUL pipe
 def A9_DRegsVFP: FuncUnit; // FP register set, VFP side
 def A9_DRegsN  : FuncUnit; // FP register set, NEON side
 
+// Bypasses
+def A9_LdBypass : Bypass;
+
 // Dual issue pipeline represented by A9_Pipe0 | A9_Pipe1
 //
 def CortexA9Itineraries : ProcessorItineraries<
-  [A9_NPipe, A9_DRegsN, A9_DRegsVFP, A9_LSPipe, A9_Pipe0, A9_Pipe1], [], [
+  [A9_NPipe, A9_DRegsN, A9_DRegsVFP, A9_LSPipe, A9_Pipe0, A9_Pipe1],
+  [A9_LdBypass], [
   // Two fully-pipelined integer ALU pipelines
 
   //
@@ -39,19 +43,30 @@ def CortexA9Itineraries : ProcessorItineraries<
                                InstrStage<1, [A9_Pipe0, A9_Pipe1]>], [2]>,
   //
   // MVN instructions
-  InstrItinData<IIC_iMVNi   , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>], [1]>,
-  InstrItinData<IIC_iMVNr   , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>], [1, 1]>,
-  InstrItinData<IIC_iMVNsi  , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>], [1, 1]>,
-  InstrItinData<IIC_iMVNsr  , [InstrStage<2, [A9_Pipe0, A9_Pipe1]>], [2, 2, 1]>,
+  InstrItinData<IIC_iMVNi   , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>],
+                              [1]>,
+  InstrItinData<IIC_iMVNr   , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>],
+                              [1, 1], [NoBypass, A9_LdBypass]>,
+  InstrItinData<IIC_iMVNsi  , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>],
+                              [1, 1]>,
+  InstrItinData<IIC_iMVNsr  , [InstrStage<2, [A9_Pipe0, A9_Pipe1]>],
+                              [2, 2, 1]>,
   //
   // No operand cycles
   InstrItinData<IIC_iALUx    , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>]>,
   //
   // Binary Instructions that produce a result
-  InstrItinData<IIC_iALUi , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>], [2, 2]>,
-  InstrItinData<IIC_iALUr , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>], [2, 2, 2]>,
-  InstrItinData<IIC_iALUsi, [InstrStage<2, [A9_Pipe0, A9_Pipe1]>], [2, 2, 1]>,
-  InstrItinData<IIC_iALUsr,[InstrStage<3, [A9_Pipe0, A9_Pipe1]>], [2, 2, 1, 1]>,
+  InstrItinData<IIC_iALUi , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>],
+                            [2, 2], [NoBypass, A9_LdBypass]>,
+  InstrItinData<IIC_iALUr , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>],
+                            [2, 2, 2], [NoBypass, A9_LdBypass, A9_LdBypass]>,
+  InstrItinData<IIC_iALUsi, [InstrStage<2, [A9_Pipe0, A9_Pipe1]>],
+                            [2, 2, 1], [NoBypass, A9_LdBypass, NoBypass]>,
+  InstrItinData<IIC_iALUsir,[InstrStage<2, [A9_Pipe0, A9_Pipe1]>],
+                            [2, 1, 2], [NoBypass, NoBypass, A9_LdBypass]>,
+  InstrItinData<IIC_iALUsr,[InstrStage<3, [A9_Pipe0, A9_Pipe1]>],
+                            [2, 2, 1, 1],
+                            [NoBypass, A9_LdBypass, NoBypass, NoBypass]>,
   //
   // Bitwise Instructions that produce a result
   InstrItinData<IIC_iBITi , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>], [2, 2]>,
@@ -69,10 +84,14 @@ def CortexA9Itineraries : ProcessorItineraries<
   InstrItinData<IIC_iEXTAsr,[InstrStage<2, [A9_Pipe0, A9_Pipe1]>],[3, 1, 1, 1]>,
   //
   // Compare instructions
-  InstrItinData<IIC_iCMPi   , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>], [2]>,
-  InstrItinData<IIC_iCMPr   , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>], [2, 2]>,
-  InstrItinData<IIC_iCMPsi  , [InstrStage<2, [A9_Pipe0, A9_Pipe1]>], [2, 1]>,
-  InstrItinData<IIC_iCMPsr  , [InstrStage<3, [A9_Pipe0, A9_Pipe1]>], [2, 1, 1]>,
+  InstrItinData<IIC_iCMPi   , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>],
+                              [2], [A9_LdBypass]>,
+  InstrItinData<IIC_iCMPr   , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>],
+                              [2, 2], [A9_LdBypass, A9_LdBypass]>,
+  InstrItinData<IIC_iCMPsi  , [InstrStage<2, [A9_Pipe0, A9_Pipe1]>],
+                              [2, 1], [A9_LdBypass, NoBypass]>,
+  InstrItinData<IIC_iCMPsr  , [InstrStage<3, [A9_Pipe0, A9_Pipe1]>],
+                              [2, 1, 1], [A9_LdBypass, NoBypass, NoBypass]>,
   //
   // Test instructions
   InstrItinData<IIC_iTSTi   , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>], [2]>,
@@ -105,31 +124,38 @@ def CortexA9Itineraries : ProcessorItineraries<
   //
   // Immediate offset
   InstrItinData<IIC_iLoadi   , [InstrStage<1, [A9_Pipe1]>,
-                                InstrStage<1, [A9_LSPipe]>], [3, 1]>,
+                                InstrStage<1, [A9_LSPipe]>],
+                               [3, 1], [A9_LdBypass]>,
   //
   // Register offset
   InstrItinData<IIC_iLoadr   , [InstrStage<1, [A9_Pipe1]>,
-                                InstrStage<1, [A9_LSPipe]>], [3, 1, 1]>,
+                                InstrStage<1, [A9_LSPipe]>],
+                               [3, 1, 1], [A9_LdBypass]>,
   //
   // Scaled register offset
   InstrItinData<IIC_iLoadsi  , [InstrStage<1, [A9_Pipe1]>,
-                                InstrStage<2, [A9_LSPipe]>], [4, 1, 1]>,
+                                InstrStage<2, [A9_LSPipe]>],
+                               [4, 1, 1], [A9_LdBypass]>,
   //
   // Immediate offset with update
   InstrItinData<IIC_iLoadiu  , [InstrStage<1, [A9_Pipe1]>,
-                                InstrStage<2, [A9_LSPipe]>], [3, 2, 1]>,
+                                InstrStage<2, [A9_LSPipe]>],
+                               [3, 2, 1], [A9_LdBypass]>,
   //
   // Register offset with update
   InstrItinData<IIC_iLoadru  , [InstrStage<1, [A9_Pipe1]>,
-                                InstrStage<2, [A9_LSPipe]>], [3, 2, 1, 1]>,
+                                InstrStage<2, [A9_LSPipe]>],
+                               [3, 2, 1, 1], [A9_LdBypass]>,
   //
   // Scaled register offset with update
   InstrItinData<IIC_iLoadsiu , [InstrStage<1, [A9_Pipe1]>,
-                                InstrStage<2, [A9_LSPipe]>], [4, 3, 1, 1]>,
+                                InstrStage<2, [A9_LSPipe]>],
+                               [4, 3, 1, 1], [A9_LdBypass]>,
   //
   // Load multiple
   InstrItinData<IIC_iLoadm   , [InstrStage<1, [A9_Pipe1]>,
-                                InstrStage<1, [A9_LSPipe]>]>,
+                                InstrStage<1, [A9_LSPipe]>],
+                               [3], [A9_LdBypass]>,
 
   //
   // Load multiple plus branch
@@ -141,7 +167,8 @@ def CortexA9Itineraries : ProcessorItineraries<
   // iLoadi + iALUr for t2LDRpci_pic.
   InstrItinData<IIC_iLoadiALU, [InstrStage<1, [A9_Pipe1]>,
                                 InstrStage<1, [A9_LSPipe]>,
-                                InstrStage<1, [A9_Pipe0, A9_Pipe1]>], [4, 1]>,
+                                InstrStage<1, [A9_Pipe0, A9_Pipe1]>],
+                               [2, 1]>,
 
   // Integer store pipeline
   ///
index 03a813d939d00a38df62762727533f2e648ae818..754635b3fb7814989f459231680cf364c4679881 100644 (file)
@@ -269,14 +269,14 @@ void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
   const std::vector<Record*> &BypassList =
     ItinData->getValueAsListOfDefs("Bypasses");
   unsigned N = BypassList.size();
-  for (unsigned i = 0; i < N;) {
+  unsigned i = 0;
+  for (; i < N;) {
     ItinString += Name + "Bypass::" + BypassList[i]->getName();
-    if (++i < N) ItinString += ", ";
+    if (++i < NOperandCycles) ItinString += ", ";
   }
-
-  for (; N < NOperandCycles;) {
+  for (; i < NOperandCycles;) {
     ItinString += " 0";
-    if (++N < NOperandCycles) ItinString += ", ";
+    if (++i < NOperandCycles) ItinString += ", ";
   }
 }
 
@@ -316,14 +316,17 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
     OS << "}\n";
 
     std::vector<Record*> BPs = Proc->getValueAsListOfDefs("BP");
-    OS << "\n// Pipeline bypasses for itineraries \"" << Name << "\"\n"
-       << "namespace " << Name << "Bypass {\n";
+    if (BPs.size()) {
+      OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
+         << "\"\n" << "namespace " << Name << "Bypass {\n";
 
-    for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
-      OS << "  const unsigned " << BPs[j]->getName()
-         << " = 1 << " << j << ";\n";
+      OS << "  const unsigned NoBypass = 0;\n";
+      for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
+        OS << "  const unsigned " << BPs[j]->getName()
+           << " = 1 << " << j << ";\n";
 
-    OS << "}\n";
+      OS << "}\n";
+    }
   }
 
   // Begin stages table
@@ -335,12 +338,12 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
   OperandCycleTable += "  0, // No itinerary\n";
 
   // Begin pipeline bypass table
-  std::string BypassTable = "static const unsigned Bypasses[] = {\n";
+  std::string BypassTable = "static const unsigned ForwardingPathes[] = {\n";
   BypassTable += "  0, // No itinerary\n";
         
   unsigned StageCount = 1, OperandCycleCount = 1;
   unsigned ItinStageEnum = 1, ItinOperandCycleEnum = 1;
-  std::map<std::string, unsigned> ItinStageMap, ItinOperandCycleMap;
+  std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
   for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
     // Next record
     Record *Proc = ProcItinList[i];
@@ -395,13 +398,14 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
       // Check to see if operand cycle already exists and create if it doesn't
       unsigned FindOperandCycle = 0;
       if (NOperandCycles > 0) {
-        FindOperandCycle = ItinOperandCycleMap[ItinOperandCycleString];
+        std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
+        FindOperandCycle = ItinOperandMap[ItinOperandString];
         if (FindOperandCycle == 0) {
           // Emit as  cycle, // index
           OperandCycleTable += ItinOperandCycleString + ", // " + 
             itostr(ItinOperandCycleEnum) + "\n";
           // Record Itin class number.
-          ItinOperandCycleMap[ItinOperandCycleString] = 
+          ItinOperandMap[ItinOperandCycleString] = 
             FindOperandCycle = OperandCycleCount;
 
           // Emit as bypass, // index
@@ -622,7 +626,8 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) {
     OS << "\n"
        << "  InstrItinerary *Itinerary = (InstrItinerary *)"
        <<              "Features.getInfo(ProcItinKV, ProcItinKVSize);\n"
-       << "  InstrItins = InstrItineraryData(Stages, OperandCycles, Itinerary);\n";
+       << "  InstrItins = InstrItineraryData(Stages, OperandCycles, "
+       << "ForwardingPathes, Itinerary);\n";
   }
 
   OS << "  return Features.getCPU();\n"