When promoting the result of fp_to_uint/fp_to_sint,
[oota-llvm.git] / lib / CodeGen / SimpleRegisterCoalescing.cpp
index 05e0505f0ba5669c53f9aa7e8fe5e7cb2d4439ec..a60939c301057c2d0f0498c316c866cb949eec6c 100644 (file)
@@ -25,6 +25,7 @@
 #include "llvm/CodeGen/RegisterCoalescer.h"
 #include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/ADT/SmallSet.h"
@@ -72,7 +73,10 @@ void SimpleRegisterCoalescing::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.addRequired<MachineLoopInfo>();
   AU.addPreserved<MachineLoopInfo>();
   AU.addPreservedID(MachineDominatorsID);
-  AU.addPreservedID(PHIEliminationID);
+  if (StrongPHIElim)
+    AU.addPreservedID(StrongPHIEliminationID);
+  else
+    AU.addPreservedID(PHIEliminationID);
   AU.addPreservedID(TwoAddressInstructionPassID);
   MachineFunctionPass::getAnalysisUsage(AU);
 }
@@ -456,17 +460,28 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt,
   unsigned DefIdx = li_->getDefIndex(CopyIdx);
   const LiveRange *DLR= li_->getInterval(DstReg).getLiveRangeContaining(DefIdx);
   DLR->valno->copy = NULL;
+  // Don't forget to update sub-register intervals.
+  if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
+    for (const unsigned* SR = tri_->getSubRegisters(DstReg); *SR; ++SR) {
+      if (!li_->hasInterval(*SR))
+        continue;
+      DLR = li_->getInterval(*SR).getLiveRangeContaining(DefIdx);
+      if (DLR && DLR->valno->copy == CopyMI)
+        DLR->valno->copy = NULL;
+    }
+  }
 
-  MachineBasicBlock::iterator MII = CopyMI;
   MachineBasicBlock *MBB = CopyMI->getParent();
+  MachineBasicBlock::iterator MII = next(MachineBasicBlock::iterator(CopyMI));
+  CopyMI->removeFromParent();
   tii_->reMaterialize(*MBB, MII, DstReg, DefMI);
   MachineInstr *NewMI = prior(MII);
-  // CopyMI may have implicit instructions, transfer them over to the newly
+  // CopyMI may have implicit operands, transfer them over to the newly
   // rematerialized instruction. And update implicit def interval valnos.
   for (unsigned i = CopyMI->getDesc().getNumOperands(),
          e = CopyMI->getNumOperands(); i != e; ++i) {
     MachineOperand &MO = CopyMI->getOperand(i);
-    if (MO.isRegister() && MO.isImplicit())
+    if (MO.isReg() && MO.isImplicit())
       NewMI->addOperand(MO);
     if (MO.isDef() && li_->hasInterval(MO.getReg())) {
       unsigned Reg = MO.getReg();
@@ -477,7 +492,7 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt,
   }
 
   li_->ReplaceMachineInstrInMaps(CopyMI, NewMI);
-  CopyMI->eraseFromParent();
+  MBB->getParent()->DeleteMachineInstr(CopyMI);
   ReMatCopies.insert(CopyMI);
   ReMatDefs.insert(DefMI);
   ++NumReMats;
@@ -692,6 +707,18 @@ bool SimpleRegisterCoalescing::ShortenDeadCopyLiveRange(LiveInterval &li,
   return false;
 }
 
+/// RemoveDeadDef - If a def of a live interval is now determined dead, remove
+/// the val# it defines. If the live interval becomes empty, remove it as well.
+bool SimpleRegisterCoalescing::RemoveDeadDef(LiveInterval &li,
+                                             MachineInstr *DefMI) {
+  unsigned DefIdx = li_->getDefIndex(li_->getInstructionIndex(DefMI));
+  LiveInterval::iterator MLR = li.FindLiveRangeContaining(DefIdx);
+  if (DefIdx != MLR->valno->def)
+    return false;
+  li.removeValNo(MLR->valno);
+  return removeIntervalIfEmpty(li, li_, tri_);
+}
+
 /// PropagateDeadness - Propagate the dead marker to the instruction which
 /// defines the val#.
 static void PropagateDeadness(LiveInterval &li, MachineInstr *CopyMI,
@@ -875,7 +902,7 @@ void SimpleRegisterCoalescing::RemoveCopiesFromValNo(LiveInterval &li,
       // Each use MI may have multiple uses of this register. Change them all.
       for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
         MachineOperand &MO = MI->getOperand(i);
-        if (MO.isRegister() && MO.getReg() == li.reg)
+        if (MO.isReg() && MO.getReg() == li.reg)
           MO.setReg(DstReg);
       }
       JoinedCopies.insert(MI);
@@ -1206,14 +1233,6 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
   DOUT << " and "; DstInt.print(DOUT, tri_);
   DOUT << ": ";
 
-  // If one interval is earlyclobber and the other is overlaps-earlyclobber,
-  // we cannot coalesce them.
-  if ((SrcInt.isEarlyClobber && DstInt.overlapsEarlyClobber) ||
-      (DstInt.isEarlyClobber && SrcInt.overlapsEarlyClobber)) {
-    DOUT << "\t\tCannot join due to earlyclobber.";
-    return false;
-  }
-
   // Check if it is necessary to propagate "isDead" property.
   if (!isExtSubReg && !isInsSubReg) {
     MachineOperand *mopd = CopyMI->findRegisterDefOperand(DstReg, false);
@@ -1374,10 +1393,6 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
   if (TargetRegisterInfo::isVirtualRegister(DstReg))
     RemoveUnnecessaryKills(DstReg, *ResDstInt);
 
-  // Merge the earlyclobber bits.
-  ResDstInt->isEarlyClobber |= ResSrcInt->isEarlyClobber;
-  ResDstInt->overlapsEarlyClobber |= ResSrcInt->overlapsEarlyClobber;
-
   if (isInsSubReg)
     // Avoid:
     // r1024 = op
@@ -2172,7 +2187,7 @@ SimpleRegisterCoalescing::lastRegisterUse(unsigned Start, unsigned End,
     if (!(tii_->isMoveInstr(*MI, SrcReg, DstReg) && SrcReg == DstReg))
       for (unsigned i = 0, NumOps = MI->getNumOperands(); i != NumOps; ++i) {
         MachineOperand &Use = MI->getOperand(i);
-        if (Use.isRegister() && Use.isUse() && Use.getReg() &&
+        if (Use.isReg() && Use.isUse() && Use.getReg() &&
             tri_->regsOverlap(Use.getReg(), Reg)) {
           UseIdx = e;
           return &Use;
@@ -2277,6 +2292,7 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
 
   // Perform a final pass over the instructions and compute spill weights
   // and remove identity moves.
+  SmallVector<unsigned, 4> DeadDefs;
   for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end();
        mbbi != mbbe; ++mbbi) {
     MachineBasicBlock* mbb = mbbi;
@@ -2310,9 +2326,13 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
         bool isDead = true;
         for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
           const MachineOperand &MO = MI->getOperand(i);
-          if (!MO.isRegister() || MO.isDead())
+          if (!MO.isReg())
             continue;
           unsigned Reg = MO.getReg();
+          if (TargetRegisterInfo::isVirtualRegister(Reg))
+            DeadDefs.push_back(Reg);
+          if (MO.isDead())
+            continue;
           if (TargetRegisterInfo::isPhysicalRegister(Reg) ||
               !mri_->use_empty(Reg)) {
             isDead = false;
@@ -2320,10 +2340,16 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
           }
         }
         if (isDead) {
+          while (!DeadDefs.empty()) {
+            unsigned DeadDef = DeadDefs.back();
+            DeadDefs.pop_back();
+            RemoveDeadDef(li_->getInterval(DeadDef), MI);
+          }
           li_->RemoveMachineInstrFromMaps(mii);
           mii = mbbi->erase(mii);
           continue;
-        }
+        } else
+          DeadDefs.clear();
       }
 
       // If the move will be an identity move delete it
@@ -2345,7 +2371,7 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
         SmallSet<unsigned, 4> UniqueUses;
         for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
           const MachineOperand &mop = MI->getOperand(i);
-          if (mop.isRegister() && mop.getReg() &&
+          if (mop.isReg() && mop.getReg() &&
               TargetRegisterInfo::isVirtualRegister(mop.getReg())) {
             unsigned reg = mop.getReg();
             // Multiple uses of reg by the same instruction. It should not
@@ -2373,7 +2399,8 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
         LI.weight = HUGE_VALF;
       else {
         bool isLoad = false;
-        if (li_->isReMaterializable(LI, isLoad)) {
+        SmallVector<LiveInterval*, 4> SpillIs;
+        if (li_->isReMaterializable(LI, SpillIs, isLoad)) {
           // If all of the definitions of the interval are re-materializable,
           // it is a preferred candidate for spilling. If non of the defs are
           // loads, then it's potentially very cheap to re-materialize.