Remove unused variable.
[oota-llvm.git] / lib / CodeGen / MachineCopyPropagation.cpp
index 861025ca0b580832fb2889b4c90e894d31d4378d..0e9d3a4f8b189a61888d625e8cee8a737fdeefec 100644 (file)
@@ -33,7 +33,7 @@ namespace {
   class MachineCopyPropagation : public MachineFunctionPass {
     const TargetRegisterInfo *TRI;
     BitVector ReservedRegs;
-    
+
   public:
     static char ID; // Pass identification, replacement for typeid
     MachineCopyPropagation() : MachineFunctionPass(ID) {
@@ -50,14 +50,11 @@ namespace {
   };
 }
 char MachineCopyPropagation::ID = 0;
+char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID;
 
 INITIALIZE_PASS(MachineCopyPropagation, "machine-cp",
                 "Machine Copy Propagation Pass", false, false)
 
-FunctionPass *llvm::createMachineCopyPropagationPass() {
-  return new MachineCopyPropagation();
-}
-
 void
 MachineCopyPropagation::SourceNoLongerAvailable(unsigned Reg,
                               DenseMap<unsigned, unsigned> &SrcMap,
@@ -83,6 +80,25 @@ MachineCopyPropagation::SourceNoLongerAvailable(unsigned Reg,
   }
 }
 
+static bool NoInterveningSideEffect(const MachineInstr *CopyMI,
+                                    const MachineInstr *MI) {
+  const MachineBasicBlock *MBB = CopyMI->getParent();
+  if (MI->getParent() != MBB)
+    return false;
+  MachineBasicBlock::const_iterator I = CopyMI;
+  MachineBasicBlock::const_iterator E = MBB->end();
+  MachineBasicBlock::const_iterator E2 = MI;
+
+  ++I;
+  while (I != E && I != E2) {
+    if (I->hasUnmodeledSideEffects() || I->isCall() ||
+        I->isTerminator())
+      return false;
+    ++I;
+  }
+  return true;
+}
+
 bool MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
   SmallSetVector<MachineInstr*, 8> MaybeDeadCopies; // Candidates for deletion
   DenseMap<unsigned, MachineInstr*> AvailCopyMap;   // Def -> available copies map
@@ -108,6 +124,7 @@ bool MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
         MachineInstr *CopyMI = CI->second;
         unsigned SrcSrc = CopyMI->getOperand(1).getReg();
         if (!ReservedRegs.test(Def) &&
+            (!ReservedRegs.test(Src) || NoInterveningSideEffect(CopyMI, MI)) &&
             (SrcSrc == Def || TRI->isSubRegister(SrcSrc, Def))) {
           // The two copies cancel out and the source of the first copy
           // hasn't been overridden, eliminate the second one. e.g.
@@ -116,7 +133,18 @@ bool MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
           //  %EAX<def> = COPY %ECX
           // =>
           //  %ECX<def> = COPY %EAX
-          CopyMI->getOperand(1).setIsKill(false);
+          //
+          // Also avoid eliminating a copy from reserved registers unless the
+          // definition is proven not clobbered. e.g.
+          // %RSP<def> = COPY %RAX
+          // CALL
+          // %RAX<def> = COPY %RSP
+
+          // Clear any kills of Def between CopyMI and MI. This extends the
+          // live range.
+          for (MachineBasicBlock::iterator I = CopyMI, E = MI; I != E; ++I)
+            I->clearRegisterKills(Def, TRI);
+
           MI->eraseFromParent();
           Changed = true;
           ++NumDeletes;
@@ -163,8 +191,11 @@ bool MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
 
     // Not a copy.
     SmallVector<unsigned, 2> Defs;
+    int RegMaskOpNum = -1;
     for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
       MachineOperand &MO = MI->getOperand(i);
+      if (MO.isRegMask())
+        RegMaskOpNum = i;
       if (!MO.isReg())
         continue;
       unsigned Reg = MO.getReg();
@@ -192,6 +223,32 @@ bool MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
       }
     }
 
+    // The instruction has a register mask operand which means that it clobbers
+    // a large set of registers.  It is possible to use the register mask to
+    // prune the available copies, but treat it like a basic block boundary for
+    // now.
+    if (RegMaskOpNum >= 0) {
+      // Erase any MaybeDeadCopies whose destination register is clobbered.
+      const MachineOperand &MaskMO = MI->getOperand(RegMaskOpNum);
+      for (SmallSetVector<MachineInstr*, 8>::iterator
+           DI = MaybeDeadCopies.begin(), DE = MaybeDeadCopies.end();
+           DI != DE; ++DI) {
+        unsigned Reg = (*DI)->getOperand(0).getReg();
+        if (ReservedRegs.test(Reg) || !MaskMO.clobbersPhysReg(Reg))
+          continue;
+        (*DI)->eraseFromParent();
+        Changed = true;
+        ++NumDeletes;
+      }
+
+      // Clear all data structures as if we were beginning a new basic block.
+      MaybeDeadCopies.clear();
+      AvailCopyMap.clear();
+      CopyMap.clear();
+      SrcMap.clear();
+      continue;
+    }
+
     for (unsigned i = 0, e = Defs.size(); i != e; ++i) {
       unsigned Reg = Defs[i];