Continue factoring computeOperandLatency. Use it for ARM hasHighOperandLatency.
authorAndrew Trick <atrick@apple.com>
Thu, 7 Jun 2012 19:42:04 +0000 (19:42 +0000)
committerAndrew Trick <atrick@apple.com>
Thu, 7 Jun 2012 19:42:04 +0000 (19:42 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158164 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetInstrInfo.h
lib/Target/ARM/ARMBaseInstrInfo.cpp
lib/Target/TargetInstrInfo.cpp

index 67b61ec77e3e855540f5d181e2fb30048f8bea38..ab848b0432b9d58dd5b1f529005b998ba232732b 100644 (file)
@@ -677,6 +677,15 @@ public:
                                 const MachineInstr *UseMI,
                                 unsigned UseIdx) const;
 
+  /// computeOperandLatency - Compute and return the latency of the given data
+  /// dependent def and use when the operand indices are already known.
+  ///
+  /// FindMin may be set to get the minimum vs. expected latency.
+  unsigned computeOperandLatency(const InstrItineraryData *ItinData,
+                                 const MachineInstr *DefMI, unsigned DefIdx,
+                                 const MachineInstr *UseMI, unsigned UseIdx,
+                                 bool FindMin = false) const;
+
   /// computeOperandLatency - Compute and return the latency of the given data
   /// dependent def and use. DefMI must be a valid def. UseMI may be NULL for
   /// an unknown use. If the subtarget allows, this may or may not need to call
index a9f12b7994b0f95c1e3b1359eb1035334d431183..6bed1371feb802231d77386e989b5084c0217b83 100644 (file)
@@ -3084,7 +3084,8 @@ hasHighOperandLatency(const InstrItineraryData *ItinData,
     return true;
 
   // Hoist VFP / NEON instructions with 4 or higher latency.
-  int Latency = getOperandLatency(ItinData, DefMI, DefIdx, UseMI, UseIdx);
+  int Latency = computeOperandLatency(ItinData, DefMI, DefIdx, UseMI, UseIdx,
+                                      /*FindMin=*/false);
   if (Latency < 0)
     Latency = getInstrLatency(ItinData, DefMI);
   if (Latency <= 3)
index ae38732065c780b128a49299827826c992e155ec..613efea73182484ef0d38ad83232df6a2f66de4b 100644 (file)
@@ -83,28 +83,15 @@ TargetInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
   return ItinData->getOperandLatency(DefClass, DefIdx, UseClass, UseIdx);
 }
 
-/// computeOperandLatency - Compute and return the latency of the given data
-/// dependent def and use. DefMI must be a valid def. UseMI may be NULL for an
-/// unknown use. Depending on the subtarget's itinerary properties, this may or
-/// may not need to call getOperandLatency().
-///
-/// FindMin may be set to get the minimum vs. expected latency. Minimum
-/// latency is used for scheduling groups, while expected latency is for
-/// instruction cost and critical path.
-///
-/// For most subtargets, we don't need DefIdx or UseIdx to compute min latency.
-/// DefMI must be a valid definition, but UseMI may be NULL for an unknown use.
-unsigned TargetInstrInfo::
-computeOperandLatency(const InstrItineraryData *ItinData,
-                      const TargetRegisterInfo *TRI,
-                      const MachineInstr *DefMI, const MachineInstr *UseMI,
-                      unsigned Reg, bool FindMin) const {
+/// If we can determine the operand latency from the def only, without itinerary
+/// lookup, do so. Otherwise return -1.
+static int computeDefOperandLatency(
+  const TargetInstrInfo *TII, const InstrItineraryData *ItinData,
+  const MachineInstr *DefMI, bool FindMin) {
 
-  // Default to one cycle for missing itinerary. Empty itineraries still have
-  // a properties. We have one hard-coded exception for loads, to preserve
-  // existing behavior.
+  // Let the target hook getInstrLatency handle missing itineraries.
   if (!ItinData)
-    return DefMI->mayLoad() ? 2 : 1;
+    return TII->getInstrLatency(ItinData, DefMI);
 
   // Return a latency based on the itinerary properties and defining instruction
   // if possible. Some common subtargets don't require per-operand latency,
@@ -113,7 +100,7 @@ computeOperandLatency(const InstrItineraryData *ItinData,
     // If MinLatency is valid, call getInstrLatency. This uses Stage latency if
     // it exists before defaulting to MinLatency.
     if (ItinData->Props.MinLatency >= 0)
-      return getInstrLatency(ItinData, DefMI);
+      return TII->getInstrLatency(ItinData, DefMI);
 
     // If MinLatency is invalid, OperandLatency is interpreted as MinLatency.
     // For empty itineraries, short-cirtuit the check and default to one cycle.
@@ -121,9 +108,63 @@ computeOperandLatency(const InstrItineraryData *ItinData,
       return 1;
   }
   else if(ItinData->isEmpty())
-    return defaultDefLatency(ItinData, DefMI);
+    return TII->defaultDefLatency(ItinData, DefMI);
 
   // ...operand lookup required
+return -1;
+}
+
+/// computeOperandLatency - Compute and return the latency of the given data
+/// dependent def and use when the operand indices are already known.
+///
+/// FindMin may be set to get the minimum vs. expected latency.
+unsigned TargetInstrInfo::
+computeOperandLatency(const InstrItineraryData *ItinData,
+                      const MachineInstr *DefMI, unsigned DefIdx,
+                      const MachineInstr *UseMI, unsigned UseIdx,
+                      bool FindMin) const {
+
+  int DefLatency = computeDefOperandLatency(this, ItinData, DefMI, FindMin);
+  if (DefLatency >= 0)
+    return DefLatency;
+
+  assert(ItinData && !ItinData->isEmpty() && "computeDefOperandLatency fail");
+
+  int OperLatency = getOperandLatency(ItinData, DefMI, DefIdx, UseMI, UseIdx);
+  if (OperLatency >= 0)
+    return OperLatency;
+
+  // No operand latency was found.
+  unsigned InstrLatency = getInstrLatency(ItinData, DefMI);
+
+  // Expected latency is the max of the stage latency and itinerary props.
+  if (!FindMin)
+    InstrLatency = std::max(InstrLatency, defaultDefLatency(ItinData, DefMI));
+  return InstrLatency;
+}
+
+/// computeOperandLatency - Compute and return the latency of the given data
+/// dependent def and use. DefMI must be a valid def. UseMI may be NULL for an
+/// unknown use. Depending on the subtarget's itinerary properties, this may or
+/// may not need to call getOperandLatency().
+///
+/// FindMin may be set to get the minimum vs. expected latency. Minimum
+/// latency is used for scheduling groups, while expected latency is for
+/// instruction cost and critical path.
+///
+/// For most subtargets, we don't need DefIdx or UseIdx to compute min latency.
+/// DefMI must be a valid definition, but UseMI may be NULL for an unknown use.
+unsigned TargetInstrInfo::
+computeOperandLatency(const InstrItineraryData *ItinData,
+                      const TargetRegisterInfo *TRI,
+                      const MachineInstr *DefMI, const MachineInstr *UseMI,
+                      unsigned Reg, bool FindMin) const {
+
+  int DefLatency = computeDefOperandLatency(this, ItinData, DefMI, FindMin);
+  if (DefLatency >= 0)
+    return DefLatency;
+
+  assert(ItinData && !ItinData->isEmpty() && "computeDefOperandLatency fail");
 
   // Find the definition of the register in the defining instruction.
   int DefIdx = DefMI->findRegisterDefOperandIdx(Reg);
@@ -168,6 +209,7 @@ computeOperandLatency(const InstrItineraryData *ItinData,
   }
   // No operand latency was found.
   unsigned InstrLatency = getInstrLatency(ItinData, DefMI);
+
   // Expected latency is the max of the stage latency and itinerary props.
   if (!FindMin)
     InstrLatency = std::max(InstrLatency, defaultDefLatency(ItinData, DefMI));
@@ -180,7 +222,7 @@ unsigned TargetInstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
   // Default to one cycle for no itinerary. However, an "empty" itinerary may
   // still have a MinLatency property, which getStageLatency checks.
   if (!ItinData)
-    return 1;
+    return MI->mayLoad() ? 2 : 1;
 
   return ItinData->getStageLatency(MI->getDesc().getSchedClass());
 }