Re-implement trivial rematerialization. This allows def MIs whose live intervals...
[oota-llvm.git] / lib / CodeGen / LiveIntervalAnalysis.cpp
index ebf3c57230ec7f7c53966e817ac7481a84455a2b..bd8137730b299cdc5a168767972384f6c4636583 100644 (file)
@@ -30,7 +30,6 @@
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
-#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/STLExtras.h"
 #include <algorithm>
@@ -60,6 +59,8 @@ void LiveIntervals::releaseMemory() {
   mi2iMap_.clear();
   i2miMap_.clear();
   r2iMap_.clear();
+  for (unsigned i = 0, e = ClonedMIs.size(); i != e; ++i)
+    delete ClonedMIs[i];
 }
 
 /// runOnMachineFunction - Register allocate the whole function
@@ -74,13 +75,12 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
 
   // Number MachineInstrs and MachineBasicBlocks.
   // Initialize MBB indexes to a sentinal.
-  MBB2IdxMap.resize(mf_->getNumBlockIDs(), ~0U);
+  MBB2IdxMap.resize(mf_->getNumBlockIDs(), std::make_pair(~0U,~0U));
   
   unsigned MIIndex = 0;
   for (MachineFunction::iterator MBB = mf_->begin(), E = mf_->end();
        MBB != E; ++MBB) {
-    // Set the MBB2IdxMap entry for this MBB.
-    MBB2IdxMap[MBB->getNumber()] = MIIndex;
+    unsigned StartIdx = MIIndex;
 
     for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end();
          I != E; ++I) {
@@ -89,6 +89,9 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
       i2miMap_.push_back(I);
       MIIndex += InstrSlots::NUM;
     }
+
+    // Set the MBB2IdxMap entry for this MBB.
+    MBB2IdxMap[MBB->getNumber()] = std::make_pair(StartIdx, MIIndex - 1);
   }
 
   computeIntervals();
@@ -175,8 +178,76 @@ LiveIntervals::CreateNewLiveInterval(const LiveInterval *LI,
   return NewLI;
 }
 
+/// isReDefinedByTwoAddr - Returns true if the Reg re-definition is due to
+/// two addr elimination.
+static bool isReDefinedByTwoAddr(MachineInstr *MI, unsigned Reg,
+                                const TargetInstrInfo *TII) {
+  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+    MachineOperand &MO1 = MI->getOperand(i);
+    if (MO1.isRegister() && MO1.isDef() && MO1.getReg() == Reg) {
+      for (unsigned j = i+1; j < e; ++j) {
+        MachineOperand &MO2 = MI->getOperand(j);
+        if (MO2.isRegister() && MO2.isUse() && MO2.getReg() == Reg &&
+            MI->getInstrDescriptor()->
+            getOperandConstraint(j, TOI::TIED_TO) == (int)i)
+          return true;
+      }
+    }
+  }
+  return false;
+}
+
+/// isReMaterializable - Returns true if the definition MI of the specified
+/// val# of the specified interval is re-materializable.
+bool LiveIntervals::isReMaterializable(const LiveInterval &li, unsigned ValNum,
+                                       MachineInstr *MI) {
+  if (tii_->isTriviallyReMaterializable(MI))
+    return true;
+
+  int FrameIdx = 0;
+  if (!tii_->isLoadFromStackSlot(MI, FrameIdx) ||
+      !mf_->getFrameInfo()->isFixedObjectIndex(FrameIdx))
+    return false;
+
+  // This is a load from fixed stack slot. It can be rematerialized unless it's
+  // re-defined by a two-address instruction.
+  for (unsigned i = 0, e = li.getNumValNums(); i != e; ++i) {
+    if (i == ValNum)
+      continue;
+    unsigned DefIdx = li.getDefForValNum(i);
+    if (DefIdx == ~1U)
+      continue; // Dead val#.
+    MachineInstr *DefMI = (DefIdx == ~0u)
+      ? NULL : getInstructionFromIndex(DefIdx);
+    if (DefMI && isReDefinedByTwoAddr(DefMI, li.reg, tii_))
+      return false;
+  }
+  return true;
+}
+
+bool LiveIntervals::tryFoldMemoryOperand(MachineInstr* &MI, VirtRegMap &vrm,
+                                         unsigned index, unsigned i,
+                                         int slot, unsigned reg) {
+  MachineInstr *fmi = mri_->foldMemoryOperand(MI, i, slot);
+  if (fmi) {
+    // Attempt to fold the memory reference into the instruction. If
+    // we can do this, we don't need to insert spill code.
+    if (lv_)
+      lv_->instructionChanged(MI, fmi);
+    MachineBasicBlock &MBB = *MI->getParent();
+    vrm.virtFolded(reg, MI, i, fmi);
+    mi2iMap_.erase(MI);
+    i2miMap_[index/InstrSlots::NUM] = fmi;
+    mi2iMap_[fmi] = index;
+    MI = MBB.insert(MBB.erase(MI), fmi);
+    ++numFolded;
+    return true;
+  }
+  return false;
+}
+
 std::vector<LiveInterval*> LiveIntervals::
-addIntervalsForSpills(const LiveInterval &li, VirtRegMap &vrm, int slot) {
+addIntervalsForSpills(const LiveInterval &li, VirtRegMap &vrm, unsigned reg) {
   // since this is called after the analysis is done we don't know if
   // LiveVariables is available
   lv_ = getAnalysisToUpdate<LiveVariables>();
@@ -192,10 +263,72 @@ addIntervalsForSpills(const LiveInterval &li, VirtRegMap &vrm, int slot) {
 
   const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(li.reg);
 
+  unsigned NumValNums = li.getNumValNums();
+  SmallVector<MachineInstr*, 4> ReMatDefs;
+  ReMatDefs.resize(NumValNums, NULL);
+  SmallVector<MachineInstr*, 4> ReMatOrigDefs;
+  ReMatOrigDefs.resize(NumValNums, NULL);
+  SmallVector<int, 4> ReMatIds;
+  ReMatIds.resize(NumValNums, VirtRegMap::MAX_STACK_SLOT);
+  BitVector ReMatDelete(NumValNums);
+  unsigned slot = VirtRegMap::MAX_STACK_SLOT;
+
+  bool NeedStackSlot = false;
+  for (unsigned i = 0; i != NumValNums; ++i) {
+    unsigned DefIdx = li.getDefForValNum(i);
+    if (DefIdx == ~1U)
+      continue; // Dead val#.
+    // Is the def for the val# rematerializable?
+    MachineInstr *DefMI = (DefIdx == ~0u)
+      ? NULL : getInstructionFromIndex(DefIdx);
+    if (DefMI && isReMaterializable(li, i, DefMI)) {
+      // Remember how to remat the def of this val#.
+      ReMatOrigDefs[i] = DefMI;
+      // Original def may be modified so we have to make a copy here. vrm must
+      // delete these!
+      ReMatDefs[i] = DefMI = DefMI->clone();
+      vrm.setVirtIsReMaterialized(reg, DefMI);
+
+      bool CanDelete = true;
+      const SmallVector<unsigned, 4> &kills = li.getKillsForValNum(i);
+      for (unsigned j = 0, ee = kills.size(); j != ee; ++j) {
+        unsigned KillIdx = kills[j];
+        MachineInstr *KillMI = (KillIdx & 1)
+          ? NULL : getInstructionFromIndex(KillIdx);
+        // Kill is a phi node, not all of its uses can be rematerialized.
+        // It must not be deleted.
+        if (!KillMI) {
+          CanDelete = false;
+          // Need a stack slot if there is any live range where uses cannot be
+          // rematerialized.
+          NeedStackSlot = true;
+          break;
+        }
+      }
+
+      if (CanDelete)
+        ReMatDelete.set(i);
+    } else {
+      // Need a stack slot if there is any live range where uses cannot be
+      // rematerialized.
+      NeedStackSlot = true;
+    }
+  }
+
+  // One stack slot per live interval.
+  if (NeedStackSlot)
+    slot = vrm.assignVirt2StackSlot(reg);
+
   for (LiveInterval::Ranges::const_iterator
-         i = li.ranges.begin(), e = li.ranges.end(); i != e; ++i) {
-    unsigned index = getBaseIndex(i->start);
-    unsigned end = getBaseIndex(i->end-1) + InstrSlots::NUM;
+         I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) {
+    MachineInstr *DefMI = ReMatDefs[I->ValId];
+    MachineInstr *OrigDefMI = ReMatOrigDefs[I->ValId];
+    bool DefIsReMat = DefMI != NULL;
+    bool CanDelete = ReMatDelete[I->ValId];
+    int LdSlot = 0;
+    bool isLoadSS = DefIsReMat && tii_->isLoadFromStackSlot(DefMI, LdSlot);
+    unsigned index = getBaseIndex(I->start);
+    unsigned end = getBaseIndex(I->end-1) + InstrSlots::NUM;
     for (; index != end; index += InstrSlots::NUM) {
       // skip deleted instructions
       while (index != end && !getInstructionFromIndex(index))
@@ -208,87 +341,109 @@ addIntervalsForSpills(const LiveInterval &li, VirtRegMap &vrm, int slot) {
       for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
         MachineOperand& mop = MI->getOperand(i);
         if (mop.isRegister() && mop.getReg() == li.reg) {
-          MachineInstr *fmi = li.remat ? NULL
-            : mri_->foldMemoryOperand(MI, i, slot);
-          if (fmi) {
-            // Attempt to fold the memory reference into the instruction.  If we
-            // can do this, we don't need to insert spill code.
-            if (lv_)
-              lv_->instructionChanged(MI, fmi);
-            MachineBasicBlock &MBB = *MI->getParent();
-            vrm.virtFolded(li.reg, MI, i, fmi);
-            mi2iMap_.erase(MI);
-            i2miMap_[index/InstrSlots::NUM] = fmi;
-            mi2iMap_[fmi] = index;
-            MI = MBB.insert(MBB.erase(MI), fmi);
-            ++numFolded;
-            // Folding the load/store can completely change the instruction in
-            // unpredictable ways, rescan it from the beginning.
-            goto RestartInstruction;
+          if (DefIsReMat) {
+            // If this is the rematerializable definition MI itself and
+            // all of its uses are rematerialized, simply delete it.
+            if (MI == OrigDefMI) {
+              if (CanDelete) {
+                RemoveMachineInstrFromMaps(MI);
+                MI->eraseFromParent();
+                break;
+              } else if (tryFoldMemoryOperand(MI, vrm, index, i, slot, li.reg))
+                // Folding the load/store can completely change the instruction
+                // in unpredictable ways, rescan it from the beginning.
+                goto RestartInstruction;
+            } else if (isLoadSS &&
+                       tryFoldMemoryOperand(MI, vrm, index, i, LdSlot, li.reg)){
+              // FIXME: Other rematerializable loads can be folded as well.
+              // Folding the load/store can completely change the
+              // instruction in unpredictable ways, rescan it from
+              // the beginning.
+              goto RestartInstruction;
+            }
           } else {
-            // Create a new virtual register for the spill interval.
-            unsigned NewVReg = mf_->getSSARegMap()->createVirtualRegister(rc);
+            if (tryFoldMemoryOperand(MI, vrm, index, i, slot, li.reg))
+              // Folding the load/store can completely change the instruction in
+              // unpredictable ways, rescan it from the beginning.
+              goto RestartInstruction;
+          }
+
+          // Create a new virtual register for the spill interval.
+          unsigned NewVReg = mf_->getSSARegMap()->createVirtualRegister(rc);
             
-            // Scan all of the operands of this instruction rewriting operands
-            // to use NewVReg instead of li.reg as appropriate.  We do this for
-            // two reasons:
-            //
-            //   1. If the instr reads the same spilled vreg multiple times, we
-            //      want to reuse the NewVReg.
-            //   2. If the instr is a two-addr instruction, we are required to
-            //      keep the src/dst regs pinned.
-            //
-            // Keep track of whether we replace a use and/or def so that we can
-            // create the spill interval with the appropriate range. 
-            mop.setReg(NewVReg);
+          // Scan all of the operands of this instruction rewriting operands
+          // to use NewVReg instead of li.reg as appropriate.  We do this for
+          // two reasons:
+          //
+          //   1. If the instr reads the same spilled vreg multiple times, we
+          //      want to reuse the NewVReg.
+          //   2. If the instr is a two-addr instruction, we are required to
+          //      keep the src/dst regs pinned.
+          //
+          // Keep track of whether we replace a use and/or def so that we can
+          // create the spill interval with the appropriate range. 
+          mop.setReg(NewVReg);
             
-            bool HasUse = mop.isUse();
-            bool HasDef = mop.isDef();
-            for (unsigned j = i+1, e = MI->getNumOperands(); j != e; ++j) {
-              if (MI->getOperand(j).isReg() &&
-                  MI->getOperand(j).getReg() == li.reg) {
-                MI->getOperand(j).setReg(NewVReg);
-                HasUse |= MI->getOperand(j).isUse();
-                HasDef |= MI->getOperand(j).isDef();
-              }
+          bool HasUse = mop.isUse();
+          bool HasDef = mop.isDef();
+          for (unsigned j = i+1, e = MI->getNumOperands(); j != e; ++j) {
+            if (MI->getOperand(j).isReg() &&
+                MI->getOperand(j).getReg() == li.reg) {
+              MI->getOperand(j).setReg(NewVReg);
+              HasUse |= MI->getOperand(j).isUse();
+              HasDef |= MI->getOperand(j).isDef();
             }
+          }
 
-            // create a new register for this spill
-            vrm.grow();
-            if (li.remat)
-              vrm.setVirtIsReMaterialized(NewVReg, li.remat);
-            vrm.assignVirt2StackSlot(NewVReg, slot);
-            LiveInterval &nI = getOrCreateInterval(NewVReg);
-            nI.remat = li.remat;
-            assert(nI.empty());
-
-            // the spill weight is now infinity as it
-            // cannot be spilled again
-            nI.weight = HUGE_VALF;
-
-            if (HasUse) {
-              LiveRange LR(getLoadIndex(index), getUseIndex(index),
-                           nI.getNextValue(~0U, 0));
-              DOUT << " +" << LR;
-              nI.addRange(LR);
+          vrm.grow();
+          if (DefIsReMat) {
+            vrm.setVirtIsReMaterialized(NewVReg, DefMI/*, CanDelete*/);
+            if (ReMatIds[I->ValId] == VirtRegMap::MAX_STACK_SLOT) {
+              // Each valnum may have its own remat id.
+              ReMatIds[I->ValId] = vrm.assignVirtReMatId(NewVReg);
+            } else {
+              vrm.assignVirtReMatId(NewVReg, ReMatIds[I->ValId]);
             }
-            if (HasDef) {
-              LiveRange LR(getDefIndex(index), getStoreIndex(index),
-                           nI.getNextValue(~0U, 0));
-              DOUT << " +" << LR;
-              nI.addRange(LR);
+            if (!CanDelete || (HasUse && HasDef)) {
+              // If this is a two-addr instruction then its use operands are
+              // rematerializable but its def is not. It should be assigned a
+              // stack slot.
+              vrm.assignVirt2StackSlot(NewVReg, slot);
             }
+          } else {
+            vrm.assignVirt2StackSlot(NewVReg, slot);
+          }
+
+          // create a new register interval for this spill / remat.
+          LiveInterval &nI = getOrCreateInterval(NewVReg);
+          assert(nI.empty());
+
+          // the spill weight is now infinity as it
+          // cannot be spilled again
+          nI.weight = HUGE_VALF;
+
+          if (HasUse) {
+            LiveRange LR(getLoadIndex(index), getUseIndex(index),
+                         nI.getNextValue(~0U, 0));
+            DOUT << " +" << LR;
+            nI.addRange(LR);
+          }
+          if (HasDef) {
+            LiveRange LR(getDefIndex(index), getStoreIndex(index),
+                         nI.getNextValue(~0U, 0));
+            DOUT << " +" << LR;
+            nI.addRange(LR);
+          }
             
-            added.push_back(&nI);
+          added.push_back(&nI);
 
-            // update live variables if it is available
-            if (lv_)
-              lv_->addVirtualRegisterKilled(NewVReg, MI);
+          // update live variables if it is available
+          if (lv_)
+            lv_->addVirtualRegisterKilled(NewVReg, MI);
             
-            DOUT << "\t\t\t\tadded new interval: ";
-            nI.print(DOUT, mri_);
-            DOUT << '\n';
-          }
+          DOUT << "\t\t\t\tadded new interval: ";
+          nI.print(DOUT, mri_);
+          DOUT << '\n';
         }
       }
     }
@@ -304,25 +459,6 @@ void LiveIntervals::printRegName(unsigned reg) const {
     cerr << "%reg" << reg;
 }
 
-/// isReDefinedByTwoAddr - Returns true if the Reg re-definition is due to
-/// two addr elimination.
-static bool isReDefinedByTwoAddr(MachineInstr *MI, unsigned Reg,
-                                const TargetInstrInfo *TII) {
-  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
-    MachineOperand &MO1 = MI->getOperand(i);
-    if (MO1.isRegister() && MO1.isDef() && MO1.getReg() == Reg) {
-      for (unsigned j = i+1; j < e; ++j) {
-        MachineOperand &MO2 = MI->getOperand(j);
-        if (MO2.isRegister() && MO2.isUse() && MO2.getReg() == Reg &&
-            MI->getInstrDescriptor()->
-            getOperandConstraint(j, TOI::TIED_TO) == (int)i)
-          return true;
-      }
-    }
-  }
-  return false;
-}
-
 void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
                                              MachineBasicBlock::iterator mi,
                                              unsigned MIIdx,
@@ -335,16 +471,6 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
   // done once for the vreg.  We use an empty interval to detect the first
   // time we see a vreg.
   if (interval.empty()) {
-    // Remember if the definition can be rematerialized. All load's from fixed
-    // stack slots are re-materializable. The target may permit other
-    // instructions to be re-materialized as well.
-    int FrameIdx = 0;
-    if (vi.DefInst &&
-        (tii_->isTriviallyReMaterializable(vi.DefInst) ||
-         (tii_->isLoadFromStackSlot(vi.DefInst, FrameIdx) &&
-          mf_->getFrameInfo()->isFixedObjectIndex(FrameIdx))))
-      interval.remat = vi.DefInst;
-
     // Get the Idx of the defining instructions.
     unsigned defIndex = getDefIndex(MIIdx);
     unsigned ValNum;
@@ -421,9 +547,6 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
     }
 
   } else {
-    // Can no longer safely assume definition is rematerializable.
-    interval.remat = NULL;
-
     // If this is the second time we see a virtual register definition, it
     // must be due to phi elimination or two addr elimination.  If this is
     // the result of two address elimination, then the vreg is one of the
@@ -487,7 +610,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
         DOUT << " Removing [" << Start << "," << End << "] from: ";
         interval.print(DOUT, mri_); DOUT << "\n";
         interval.removeRange(Start, End);
-        interval.addKillForValNum(0, Start);
+        interval.addKillForValNum(0, Start-1); // odd # means phi node
         DOUT << " RESULT: "; interval.print(DOUT, mri_);
 
         // Replace the interval with one of a NEW value number.  Note that this
@@ -514,7 +637,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
       unsigned killIndex = getInstructionIndex(&mbb->back()) + InstrSlots::NUM;
       LiveRange LR(defIndex, killIndex, ValNum);
       interval.addRange(LR);
-      interval.addKillForValNum(ValNum, killIndex);
+      interval.addKillForValNum(ValNum, killIndex-1); // odd # means phi node
       DOUT << " +" << LR;
     }
   }