Re-enable register pressure aware machine licm with fixes. Hoist() may have
[oota-llvm.git] / lib / CodeGen / MachineLICM.cpp
index 3e25e917c9e96ed1c7ab3e7a1218739d53b048f9..1f0412498b66ebc021488c3e572123af73ea4b93 100644 (file)
 
 using namespace llvm;
 
-static cl::opt<bool>
-TrackRegPressure("rp-aware-machine-licm",
-                 cl::desc("Register pressure aware machine LICM"),
-                 cl::init(false), cl::Hidden);
-
 STATISTIC(NumHoisted,
           "Number of machine instructions hoisted out of loops");
 STATISTIC(NumLowRP,
@@ -128,6 +123,7 @@ namespace {
       RegSeen.clear();
       RegPressure.clear();
       RegLimit.clear();
+      BackTrace.clear();
       for (DenseMap<unsigned,std::vector<const MachineInstr*> >::iterator
              CI = CSEMap.begin(), CE = CSEMap.end(); CI != CE; ++CI)
         CI->second.clear();
@@ -175,9 +171,10 @@ namespace {
     /// 
     bool IsLoopInvariantInst(MachineInstr &I);
 
-    /// ComputeOperandLatency - Compute operand latency between a def of 'Reg'
-    /// and an use in the current loop.
-    int ComputeOperandLatency(MachineInstr &MI, unsigned DefIdx, unsigned Reg);
+    /// HasHighOperandLatency - Compute operand latency between a def of 'Reg'
+    /// and an use in the current loop, return true if the target considered
+    /// it 'high'.
+    bool HasHighOperandLatency(MachineInstr &MI, unsigned DefIdx, unsigned Reg);
 
     /// IncreaseHighRegPressure - Visit BBs from preheader to current BB, check
     /// if hoisting an instruction of the given cost matrix can cause high
@@ -203,8 +200,9 @@ namespace {
 
     /// UpdateRegPressureBefore / UpdateRegPressureAfter - Update estimate of
     /// register pressure before and after executing a specifi instruction.
-    void UpdateRegPressureBefore(const MachineInstr *MI);
-    void UpdateRegPressureAfter(const MachineInstr *MI);
+    void UpdateRegPressureBefore(const MachineInstr *MI,
+                                 SmallVector<unsigned, 4> &Defs);
+    void UpdateRegPressureAfter(SmallVector<unsigned, 4> &Defs);
 
     /// isLoadFromConstantMemory - Return true if the given instruction is a
     /// load from constant memory.
@@ -560,28 +558,26 @@ void MachineLICM::HoistRegion(MachineDomTreeNode *N, bool IsHeader) {
   if (!Preheader)
     return;
 
-  if (TrackRegPressure) {
-    if (IsHeader) {
-      // Compute registers which are liveout of preheader.
-      RegSeen.clear();
-      BackTrace.clear();
-      InitRegPressure(Preheader);
-    }
-
-    // Remember livein register pressure.
-    BackTrace.push_back(RegPressure);
+  if (IsHeader) {
+    // Compute registers which are liveout of preheader.
+    RegSeen.clear();
+    BackTrace.clear();
+    InitRegPressure(Preheader);
   }
 
+  // Remember livein register pressure.
+  BackTrace.push_back(RegPressure);
+
+  SmallVector<unsigned, 4> Defs;
   for (MachineBasicBlock::iterator
          MII = BB->begin(), E = BB->end(); MII != E; ) {
     MachineBasicBlock::iterator NextMII = MII; ++NextMII;
     MachineInstr *MI = &*MII;
 
-    if (TrackRegPressure)
-      UpdateRegPressureBefore(MI);
+    assert(Defs.empty());
+    UpdateRegPressureBefore(MI, Defs);
     Hoist(MI, Preheader);
-    if (TrackRegPressure)
-      UpdateRegPressureAfter(MI);
+    UpdateRegPressureAfter(Defs);
 
     MII = NextMII;
   }
@@ -595,8 +591,7 @@ void MachineLICM::HoistRegion(MachineDomTreeNode *N, bool IsHeader) {
       HoistRegion(Children[I]);
   }
 
-  if (TrackRegPressure)
-    BackTrace.pop_back();
+  BackTrace.pop_back();
 }
 
 /// InitRegPressure - Find all virtual register references that are liveout of
@@ -635,12 +630,13 @@ void MachineLICM::InitRegPressure(MachineBasicBlock *BB) {
 
 /// UpdateRegPressureBefore / UpdateRegPressureAfter - Update estimate of
 /// register pressure before and after executing a specifi instruction.
-void MachineLICM::UpdateRegPressureBefore(const MachineInstr *MI) {
+void MachineLICM::UpdateRegPressureBefore(const MachineInstr *MI,
+                                          SmallVector<unsigned, 4> &Defs) {
   bool NoImpact = MI->isImplicitDef() || MI->isPHI();
 
   for (unsigned i = 0, e = MI->getDesc().getNumOperands(); i != e; ++i) {
     const MachineOperand &MO = MI->getOperand(i);
-    if (!MO.isReg() || MO.isImplicit() || !MO.isUse())
+    if (!MO.isReg() || MO.isImplicit())
       continue;
     unsigned Reg = MO.getReg();
     if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg))
@@ -650,33 +646,26 @@ void MachineLICM::UpdateRegPressureBefore(const MachineInstr *MI) {
     if (NoImpact)
       continue;
 
-    if (!isNew && MO.isKill()) {
-      const TargetRegisterClass *RC = MRI->getRegClass(Reg);
-      EVT VT = *RC->vt_begin();
-      unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
-      unsigned RCCost = TLI->getRepRegClassCostFor(VT);
+    if (MO.isDef())
+      Defs.push_back(Reg);
+    else {
+      if (!isNew && MO.isKill()) {
+        const TargetRegisterClass *RC = MRI->getRegClass(Reg);
+        EVT VT = *RC->vt_begin();
+        unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
+        unsigned RCCost = TLI->getRepRegClassCostFor(VT);
 
-      assert(RCCost <= RegPressure[RCId]);
-      RegPressure[RCId] -= RCCost;
+        assert(RCCost <= RegPressure[RCId]);
+        RegPressure[RCId] -= RCCost;
+      }
     }
   }
 }
 
-void MachineLICM::UpdateRegPressureAfter(const MachineInstr *MI) {
-  bool NoImpact = MI->isImplicitDef() || MI->isPHI();
-
-  for (unsigned i = 0, e = MI->getDesc().getNumOperands(); i != e; ++i) {
-    const MachineOperand &MO = MI->getOperand(i);
-    if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
-      continue;
-    unsigned Reg = MO.getReg();
-    if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg))
-      continue;
-
+void MachineLICM::UpdateRegPressureAfter(SmallVector<unsigned, 4> &Defs) {
+  while (!Defs.empty()) {
+    unsigned Reg = Defs.pop_back_val();
     RegSeen.insert(Reg);
-    if (NoImpact)
-      continue;
-
     const TargetRegisterClass *RC = MRI->getRegClass(Reg);
     EVT VT = *RC->vt_begin();
     unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
@@ -792,15 +781,14 @@ bool MachineLICM::isLoadFromConstantMemory(MachineInstr *MI) {
   }
 }
 
-/// ComputeOperandLatency - Compute operand latency between a def of 'Reg'
-/// and an use in the current loop.
-int MachineLICM::ComputeOperandLatency(MachineInstr &MI,
-                                       unsigned DefIdx, unsigned Reg) {
+/// HasHighOperandLatency - Compute operand latency between a def of 'Reg'
+/// and an use in the current loop, return true if the target considered
+/// it 'high'.
+bool MachineLICM::HasHighOperandLatency(MachineInstr &MI,
+                                        unsigned DefIdx, unsigned Reg) {
   if (MRI->use_nodbg_empty(Reg))
-    // No use? Return arbitrary large number!
-    return 300;
+    return false;
 
-  int Latency = -1;
   for (MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(Reg),
          E = MRI->use_nodbg_end(); I != E; ++I) {
     MachineInstr *UseMI = &*I;
@@ -814,18 +802,15 @@ int MachineLICM::ComputeOperandLatency(MachineInstr &MI,
       if (MOReg != Reg)
         continue;
 
-      int UseCycle = TII->getOperandLatency(InstrItins, &MI, DefIdx, UseMI, i);
-      Latency = std::max(Latency, UseCycle);
+      if (TII->hasHighOperandLatency(InstrItins, MRI, &MI, DefIdx, UseMI, i))
+        return true;
     }
 
-    if (Latency != -1)
-      break;
+    // Only look at the first in loop use.
+    break;
   }
 
-  if (Latency == -1)
-    Latency = InstrItins->getOperandCycle(MI.getDesc().getSchedClass(), DefIdx);
-
-  return Latency;
+  return false;
 }
 
 /// IncreaseHighRegPressure - Visit BBs from preheader to current BB, check
@@ -859,19 +844,19 @@ bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) {
   if (MI.isImplicitDef())
     return true;
 
-  // FIXME: For now, only hoist re-materilizable instructions. LICM will
-  // increase register pressure. We want to make sure it doesn't increase
-  // spilling.
+  // If the instruction is cheap, only hoist if it is re-materilizable. LICM
+  // will increase register pressure. It's probably not worth it if the
+  // instruction is cheap.
   // Also hoist loads from constant memory, e.g. load from stubs, GOT. Hoisting
   // these tend to help performance in low register pressure situation. The
   // trade off is it may cause spill in high pressure situation. It will end up
   // adding a store in the loop preheader. But the reload is no more expensive.
   // The side benefit is these loads are frequently CSE'ed.
-  if (!TrackRegPressure || MI.getDesc().isAsCheapAsAMove()) {
-    if (!TII->isTriviallyReMaterializable(&MI, AA) &&
-        !isLoadFromConstantMemory(&MI))
+  if (MI.getDesc().isAsCheapAsAMove()) {
+    if (!TII->isTriviallyReMaterializable(&MI, AA))
       return false;
   } else {
+    // Estimate register pressure to determine whether to LICM the instruction.
     // In low register pressure situation, we can be more aggressive about 
     // hoisting. Also, favors hoisting long latency instructions even in
     // moderately high pressure situation.
@@ -884,13 +869,9 @@ bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) {
       if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg))
         continue;
       if (MO.isDef()) {
-        if (InstrItins && !InstrItins->isEmpty()) {
-          int Cycle = ComputeOperandLatency(MI, i, Reg);
-          if (Cycle > 3) {
-            // FIXME: Target specific high latency limit?
-            ++NumHighLatency;
-            return true;
-          }
+        if (HasHighOperandLatency(MI, i, Reg)) {
+          ++NumHighLatency;
+          return true;
         }
 
         const TargetRegisterClass *RC = MRI->getRegClass(Reg);