Fix a bug that David Greene found in the DAGCombiner's logic
[oota-llvm.git] / lib / CodeGen / LiveIntervalAnalysis.cpp
index 18ee27be206ac3ad5816f6d448c7162ff9a5007e..985a3fa16342366955d42912ea4109318b998041 100644 (file)
@@ -298,8 +298,8 @@ bool LiveIntervals::conflictsWithPhysRegDef(const LiveInterval &li,
       if (index == end) break;
 
       MachineInstr *MI = getInstructionFromIndex(index);
-      unsigned SrcReg, DstReg;
-      if (tii_->isMoveInstr(*MI, SrcReg, DstReg))
+      unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
+      if (tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg))
         if (SrcReg == li.reg || DstReg == li.reg)
           continue;
       for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
@@ -323,6 +323,47 @@ bool LiveIntervals::conflictsWithPhysRegDef(const LiveInterval &li,
   return false;
 }
 
+/// conflictsWithPhysRegRef - Similar to conflictsWithPhysRegRef except
+/// it can check use as well.
+bool LiveIntervals::conflictsWithPhysRegRef(LiveInterval &li,
+                                            unsigned Reg, bool CheckUse,
+                                  SmallPtrSet<MachineInstr*,32> &JoinedCopies) {
+  for (LiveInterval::Ranges::const_iterator
+         I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) {
+    for (unsigned index = getBaseIndex(I->start),
+           end = getBaseIndex(I->end-1) + InstrSlots::NUM; index != end;
+         index += InstrSlots::NUM) {
+      // Skip deleted instructions.
+      MachineInstr *MI = 0;
+      while (index != end) {
+        MI = getInstructionFromIndex(index);
+        if (MI)
+          break;
+        index += InstrSlots::NUM;
+      }
+      if (index == end) break;
+
+      if (JoinedCopies.count(MI))
+        continue;
+      for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+        MachineOperand& MO = MI->getOperand(i);
+        if (!MO.isReg())
+          continue;
+        if (MO.isUse() && !CheckUse)
+          continue;
+        unsigned PhysReg = MO.getReg();
+        if (PhysReg == 0 || TargetRegisterInfo::isVirtualRegister(PhysReg))
+          continue;
+        if (tri_->isSubRegister(Reg, PhysReg))
+          return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+
 void LiveIntervals::printRegName(unsigned reg) const {
   if (TargetRegisterInfo::isPhysicalRegister(reg))
     cerr << tri_->getName(reg);
@@ -355,11 +396,12 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
       defIndex = getUseIndex(MIIdx);
     VNInfo *ValNo;
     MachineInstr *CopyMI = NULL;
-    unsigned SrcReg, DstReg;
+    unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
     if (mi->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG ||
         mi->getOpcode() == TargetInstrInfo::INSERT_SUBREG ||
-        tii_->isMoveInstr(*mi, SrcReg, DstReg))
+        tii_->isMoveInstr(*mi, SrcReg, DstReg, SrcSubReg, DstSubReg))
       CopyMI = mi;
+    // Earlyclobbers move back one.
     ValNo = interval.getNextValue(defIndex, CopyMI, VNInfoAllocator);
 
     assert(ValNo->id == 0 && "First value in interval is not 0?");
@@ -435,9 +477,8 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
       assert(interval.containsOneValue());
       unsigned DefIndex = getDefIndex(interval.getValNumInfo(0)->def);
       unsigned RedefIndex = getDefIndex(MIIdx);
-      // Earlyclobbers move back one.
-      if (MO.isEarlyClobber())
-        RedefIndex = getUseIndex(MIIdx);
+      // It cannot be an early clobber MO.
+      assert(!MO.isEarlyClobber() && "Unexpected early clobber!");
 
       const LiveRange *OldLR = interval.getLiveRangeContaining(RedefIndex-1);
       VNInfo *OldValNo = OldLR->valno;
@@ -505,16 +546,15 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
       // live until the end of the block.  We've already taken care of the
       // rest of the live range.
       unsigned defIndex = getDefIndex(MIIdx);
-      // Earlyclobbers move back one.
-      if (MO.isEarlyClobber())
-        defIndex = getUseIndex(MIIdx);
+      // It cannot be an early clobber MO.
+      assert(!MO.isEarlyClobber() && "Unexpected early clobber!");
       
       VNInfo *ValNo;
       MachineInstr *CopyMI = NULL;
-      unsigned SrcReg, DstReg;
+      unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
       if (mi->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG ||
           mi->getOpcode() == TargetInstrInfo::INSERT_SUBREG ||
-          tii_->isMoveInstr(*mi, SrcReg, DstReg))
+          tii_->isMoveInstr(*mi, SrcReg, DstReg, SrcSubReg, DstSubReg))
         CopyMI = mi;
       ValNo = interval.getNextValue(defIndex, CopyMI, VNInfoAllocator);
       
@@ -592,8 +632,11 @@ exit:
 
   // Already exists? Extend old live interval.
   LiveInterval::iterator OldLR = interval.FindLiveRangeContaining(start);
-  VNInfo *ValNo = (OldLR != interval.end())
+  bool Extend = OldLR != interval.end();
+  VNInfo *ValNo = Extend
     ? OldLR->valno : interval.getNextValue(start, CopyMI, VNInfoAllocator);
+  if (MO.isEarlyClobber() && Extend)
+    ValNo->redefByEC = true;
   LiveRange LR(start, end, ValNo);
   interval.addRange(LR);
   interval.addKill(LR.valno, end);
@@ -610,10 +653,10 @@ void LiveIntervals::handleRegisterDef(MachineBasicBlock *MBB,
                              getOrCreateInterval(MO.getReg()));
   else if (allocatableRegs_[MO.getReg()]) {
     MachineInstr *CopyMI = NULL;
-    unsigned SrcReg, DstReg;
+    unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
     if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG ||
         MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG ||
-        tii_->isMoveInstr(*MI, SrcReg, DstReg))
+        tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg))
       CopyMI = MI;
     handlePhysicalRegisterDef(MBB, MI, MIIdx, MO, 
                               getOrCreateInterval(MO.getReg()), CopyMI);
@@ -781,23 +824,35 @@ bool LiveIntervals::findReachableMBBs(unsigned Start, unsigned End,
 }
 
 LiveInterval* LiveIntervals::createInterval(unsigned reg) {
-  float Weight = TargetRegisterInfo::isPhysicalRegister(reg) ?
-                       HUGE_VALF : 0.0F;
+  float Weight = TargetRegisterInfo::isPhysicalRegister(reg) ? HUGE_VALF : 0.0F;
   return new LiveInterval(reg, Weight);
 }
 
+/// dupInterval - Duplicate a live interval. The caller is responsible for
+/// managing the allocated memory.
+LiveInterval* LiveIntervals::dupInterval(LiveInterval *li) {
+  LiveInterval *NewLI = createInterval(li->reg);
+  NewLI->Copy(*li, getVNInfoAllocator());
+  return NewLI;
+}
+
 /// getVNInfoSourceReg - Helper function that parses the specified VNInfo
 /// copy field and returns the source register that defines it.
 unsigned LiveIntervals::getVNInfoSourceReg(const VNInfo *VNI) const {
   if (!VNI->copy)
     return 0;
 
-  if (VNI->copy->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG)
-    return VNI->copy->getOperand(1).getReg();
-  if (VNI->copy->getOpcode() == TargetInstrInfo::INSERT_SUBREG)
+  if (VNI->copy->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) {
+    // If it's extracting out of a physical register, return the sub-register.
+    unsigned Reg = VNI->copy->getOperand(1).getReg();
+    if (TargetRegisterInfo::isPhysicalRegister(Reg))
+      Reg = tri_->getSubReg(Reg, VNI->copy->getOperand(2).getImm());
+    return Reg;
+  } else if (VNI->copy->getOpcode() == TargetInstrInfo::INSERT_SUBREG)
     return VNI->copy->getOperand(2).getReg();
-  unsigned SrcReg, DstReg;
-  if (tii_->isMoveInstr(*VNI->copy, SrcReg, DstReg))
+
+  unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
+  if (tii_->isMoveInstr(*VNI->copy, SrcReg, DstReg, SrcSubReg, DstSubReg))
     return SrcReg;
   assert(0 && "Unrecognized copy instruction!");
   return 0;
@@ -918,7 +973,7 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li,
         MachineRegisterInfo::def_iterator I = mri_->def_begin(Reg),
                                           E = mri_->def_end();
 
-        // For the def, it should be the only def.
+        // For the def, it should be the only def of that register.
         if (MO.isDef() && (next(I) != E || IsLiveIn))
           return false;
 
@@ -931,7 +986,7 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li,
             else if (Reg != ImpUse)
               return false;
           }
-          // For uses, there should be only one associate def.
+          // For the use, there should be only one associated def.
           if (I != E && (next(I) != E || IsLiveIn))
             return false;
         }
@@ -1800,7 +1855,7 @@ addIntervalsForSpills(const LiveInterval &li,
   // Spill slot weight.
   SSWeight = 0.0f;
 
-  // Each bit specify whether it a spill is required in the MBB.
+  // Each bit specify whether a spill is required in the MBB.
   BitVector SpillMBBs(mf_->getNumBlockIDs());
   DenseMap<unsigned, std::vector<SRInfo> > SpillIdxes;
   BitVector RestoreMBBs(mf_->getNumBlockIDs());
@@ -2059,15 +2114,17 @@ addIntervalsForSpills(const LiveInterval &li,
           if (isLoadSS || ReMatDefMI->getDesc().canFoldAsLoad())
             Folded = tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index,
                                           Ops, isLoadSS, LdSlot, VReg);
-          unsigned ImpUse = getReMatImplicitUse(li, ReMatDefMI);
-          if (ImpUse) {
-            // Re-matting an instruction with virtual register use. Add the
-            // register as an implicit use on the use MI and update the register
-            // interval's spill weight to HUGE_VALF to prevent it from being
-            // spilled.
-            LiveInterval &ImpLi = getInterval(ImpUse);
-            ImpLi.weight = HUGE_VALF;
-            MI->addOperand(MachineOperand::CreateReg(ImpUse, false, true));
+          if (!Folded) {
+            unsigned ImpUse = getReMatImplicitUse(li, ReMatDefMI);
+            if (ImpUse) {
+              // Re-matting an instruction with virtual register use. Add the
+              // register as an implicit use on the use MI and update the register
+              // interval's spill weight to HUGE_VALF to prevent it from being
+              // spilled.
+              LiveInterval &ImpLi = getInterval(ImpUse);
+              ImpLi.weight = HUGE_VALF;
+              MI->addOperand(MachineOperand::CreateReg(ImpUse, false, true));
+            }
           }
         }
       }
@@ -2178,7 +2235,19 @@ void LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li,
     unsigned Index = getInstructionIndex(MI);
     if (pli.liveAt(Index)) {
       vrm.addEmergencySpill(SpillReg, MI);
-      pli.removeRange(getLoadIndex(Index), getStoreIndex(Index)+1);
+      unsigned StartIdx = getLoadIndex(Index);
+      unsigned EndIdx = getStoreIndex(Index)+1;
+      if (pli.isInOneLiveRange(StartIdx, EndIdx))
+        pli.removeRange(StartIdx, EndIdx);
+      else {
+        cerr << "Ran out of registers during register allocation!\n";
+        if (MI->getOpcode() == TargetInstrInfo::INLINEASM) {
+          cerr << "Please check your inline asm statement for invalid "
+               << "constraints:\n";
+          MI->print(cerr.stream(), tm_);
+        }
+        exit(1);
+      }
       for (const unsigned* AS = tri_->getSubRegisters(SpillReg); *AS; ++AS) {
         if (!hasInterval(*AS))
           continue;