new testcase for PR1286
[oota-llvm.git] / lib / CodeGen / LiveIntervalAnalysis.cpp
index bc4f6016f36825c1057254909c2550b283ae2b1c..8cfc5871dcc68708f0151b3535e1c248b7ea2e30 100644 (file)
@@ -164,13 +164,15 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
             unsigned reg = rep(mop.getReg());
             mii->getOperand(i).setReg(reg);
 
-            // If the definition instruction is re-materializable, its spill
-            // weight is zero.
             LiveInterval &RegInt = getInterval(reg);
-            if (!RegInt.remat) {
-              RegInt.weight +=
-                (mop.isUse() + mop.isDef()) * pow(10.0F, (int)loopDepth);
-            }
+            float w = (mop.isUse()+mop.isDef()) * powf(10.0F, (float)loopDepth);
+            // If the definition instruction is re-materializable, its spill
+            // weight is half of what it would have been normally unless it's
+            // a load from fixed stack slot.
+            int Dummy;
+            if (RegInt.remat && !tii_->isLoadFromStackSlot(RegInt.remat, Dummy))
+              w /= 2;
+            RegInt.weight += w;
           }
         }
         ++mii;
@@ -430,8 +432,13 @@ 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.
-    if (vi.DefInst && tii_->isReMaterializable(vi.DefInst->getOpcode()))
+    // Remember if the definition can be rematerialized. All load's from fixed
+    // stack slots are re-materializable.
+    int FrameIdx = 0;
+    if (vi.DefInst &&
+        (tii_->isReMaterializable(vi.DefInst->getOpcode()) ||
+         (tii_->isLoadFromStackSlot(vi.DefInst, FrameIdx) &&
+          mf_->getFrameInfo()->isFixedObjectIndex(FrameIdx))))
       interval.remat = vi.DefInst;
 
     // Get the Idx of the defining instructions.
@@ -509,7 +516,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
     }
 
   } else {
-    // Can't safely assume definition is rematierializable anymore.
+    // Can no longer safely assume definition is rematerializable.
     interval.remat = NULL;
 
     // If this is the second time we see a virtual register definition, it
@@ -945,7 +952,7 @@ bool LiveIntervals::JoinCopy(MachineInstr *CopyMI,
       } else {
         MachineInstr *SrcMI = getInstructionFromIndex(SrcStart);
         if (SrcMI) {
-          MachineOperand *mops = SrcMI->findRegisterDefOperand(SrcReg);
+          MachineOperand *mops = findDefOperand(SrcMI, repSrcReg);
           if (mops)
             // A dead def should have a single cycle interval.
             ++RemoveStart;
@@ -1022,7 +1029,7 @@ TryJoin:
       } else {
         MachineInstr *SrcMI = getInstructionFromIndex(SrcStart);
         if (SrcMI) {
-          MachineOperand *mops = SrcMI->findRegisterDefOperand(SrcReg);
+          MachineOperand *mops = findDefOperand(SrcMI, repSrcReg);
           if (mops)
             mops->setIsDead();
         }
@@ -1617,6 +1624,19 @@ LiveIntervals::lastRegisterUse(unsigned Reg, unsigned Start, unsigned End,
   return NULL;
 }
 
+
+/// findDefOperand - Returns the MachineOperand that is a def of the specific
+/// register. It returns NULL if the def is not found.
+MachineOperand *LiveIntervals::findDefOperand(MachineInstr *MI, unsigned Reg) {
+  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+    MachineOperand &MO = MI->getOperand(i);
+    if (MO.isReg() && MO.isDef() &&
+        mri_->regsOverlap(rep(MO.getReg()), Reg))
+      return &MO;
+  }
+  return NULL;
+}
+
 /// unsetRegisterKill - Unset IsKill property of all uses of specific register
 /// of the specific instruction.
 void LiveIntervals::unsetRegisterKill(MachineInstr *MI, unsigned Reg) {