[llvm-commits] [llvm] r70279 - in /llvm/trunk: lib/CodeGen/TwoAddressInstructionPass.cpp test/CodeGen/X86/2009-04-27-LiveIntervalsAssert2.ll

Evan Cheng evan.cheng at apple.com
Mon Apr 27 19:12:36 PDT 2009


Author: evancheng
Date: Mon Apr 27 21:12:36 2009
New Revision: 70279

URL: http://llvm.org/viewvc/llvm-project?rev=70279&view=rev
Log:
Fix for PR4051. When 2address pass delete an instruction, update kill info when necessary.

Added:
    llvm/trunk/test/CodeGen/X86/2009-04-27-LiveIntervalsAssert2.ll
Modified:
    llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp

Modified: llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp?rev=70279&r1=70278&r2=70279&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp (original)
+++ llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp Mon Apr 27 21:12:36 2009
@@ -88,6 +88,9 @@
     bool NoUseAfterLastDef(unsigned Reg, MachineBasicBlock *MBB, unsigned Dist,
                            unsigned &LastDef);
 
+    MachineInstr *FindLastUseInMBB(unsigned Reg, MachineBasicBlock *MBB,
+                                   unsigned Dist);
+
     bool isProfitableToCommute(unsigned regB, unsigned regC,
                                MachineInstr *MI, MachineBasicBlock *MBB,
                                unsigned Dist);
@@ -310,6 +313,28 @@
   return !(LastUse > LastDef && LastUse < Dist);
 }
 
+MachineInstr *TwoAddressInstructionPass::FindLastUseInMBB(unsigned Reg,
+                                                         MachineBasicBlock *MBB,
+                                                         unsigned Dist) {
+  unsigned LastUseDist = Dist;
+  MachineInstr *LastUse = 0;
+  for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Reg),
+         E = MRI->reg_end(); I != E; ++I) {
+    MachineOperand &MO = I.getOperand();
+    MachineInstr *MI = MO.getParent();
+    if (MI->getParent() != MBB)
+      continue;
+    DenseMap<MachineInstr*, unsigned>::iterator DI = DistanceMap.find(MI);
+    if (DI == DistanceMap.end())
+      continue;
+    if (MO.isUse() && DI->second < LastUseDist) {
+      LastUse = DI->first;
+      LastUseDist = DI->second;
+    }
+  }
+  return LastUse;
+}
+
 /// isCopyToReg - Return true if the specified MI is a copy instruction or
 /// a extract_subreg instruction. It also returns the source and destination
 /// registers and whether they are physical registers by reference.
@@ -684,7 +709,9 @@
 
 /// isSafeToDelete - If the specified instruction does not produce any side
 /// effects and all of its defs are dead, then it's safe to delete.
-static bool isSafeToDelete(MachineInstr *MI, const TargetInstrInfo *TII) {
+static bool isSafeToDelete(MachineInstr *MI, unsigned Reg,
+                           const TargetInstrInfo *TII,
+                           SmallVector<unsigned, 4> &Kills) {
   const TargetInstrDesc &TID = MI->getDesc();
   if (TID.mayStore() || TID.isCall())
     return false;
@@ -693,10 +720,12 @@
 
   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
     MachineOperand &MO = MI->getOperand(i);
-    if (!MO.isReg() || !MO.isDef())
+    if (!MO.isReg())
       continue;
-    if (!MO.isDead())
+    if (MO.isDef() && !MO.isDead())
       return false;
+    if (MO.isUse() && MO.getReg() != Reg && MO.isKill())
+      Kills.push_back(MO.getReg());
   }
 
   return true;
@@ -787,11 +816,53 @@
           if (!isKilled(*mi, regB, MRI, TII)) {
             // If regA is dead and the instruction can be deleted, just delete
             // it so it doesn't clobber regB.
-            if (mi->getOperand(ti).isDead() && isSafeToDelete(mi, TII)) {
-              mbbi->erase(mi); // Nuke the old inst.
-              mi = nmi;
-              ++NumDeletes;
-              break; // Done with this instruction.
+            SmallVector<unsigned, 4> Kills;
+            if (mi->getOperand(ti).isDead() &&
+                isSafeToDelete(mi, regB, TII, Kills)) {
+              SmallVector<std::pair<std::pair<unsigned, bool>
+                ,MachineInstr*>, 4> NewKills;
+              bool ReallySafe = true;
+              // If this instruction kills some virtual registers, we need
+              // update the kill information. If it's not possible to do so,
+              // then bail out.
+              while (!Kills.empty()) {
+                unsigned Kill = Kills.back();
+                Kills.pop_back();
+                if (TargetRegisterInfo::isPhysicalRegister(Kill)) {
+                  ReallySafe = false;
+                  break;
+                }
+                MachineInstr *LastKill = FindLastUseInMBB(Kill, &*mbbi, Dist);
+                if (LastKill) {
+                  bool isModRef = LastKill->modifiesRegister(Kill);
+                  NewKills.push_back(std::make_pair(std::make_pair(Kill,isModRef),
+                                                    LastKill));
+                } else {
+                  ReallySafe = false;
+                  break;
+                }
+              }
+
+              if (ReallySafe) {
+                if (LV) {
+                  while (!NewKills.empty()) {
+                    MachineInstr *NewKill = NewKills.back().second;
+                    unsigned Kill = NewKills.back().first.first;
+                    bool isDead = NewKills.back().first.second;
+                    NewKills.pop_back();
+                    if (LV->removeVirtualRegisterKilled(Kill,  mi)) {
+                      if (isDead)
+                        LV->addVirtualRegisterDead(Kill, NewKill);
+                      else
+                        LV->addVirtualRegisterKilled(Kill, NewKill);
+                    }
+                  }
+                }
+                mbbi->erase(mi); // Nuke the old inst.
+                mi = nmi;
+                ++NumDeletes;
+                break; // Done with this instruction.
+              }
             }
 
             // If this instruction is commutative, check to see if C dies.  If

Added: llvm/trunk/test/CodeGen/X86/2009-04-27-LiveIntervalsAssert2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-04-27-LiveIntervalsAssert2.ll?rev=70279&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/X86/2009-04-27-LiveIntervalsAssert2.ll (added)
+++ llvm/trunk/test/CodeGen/X86/2009-04-27-LiveIntervalsAssert2.ll Mon Apr 27 21:12:36 2009
@@ -0,0 +1,23 @@
+; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9
+; PR4051
+
+define void @int163(i32 %p_4, i32 %p_5) nounwind {
+entry:
+	%0 = tail call i32 @foo(i32 1) nounwind		; <i32> [#uses=2]
+	%1 = icmp eq i32 %0, 0		; <i1> [#uses=1]
+	br i1 %1, label %bb.i, label %bar.exit
+
+bb.i:		; preds = %entry
+	%2 = lshr i32 1, %0		; <i32> [#uses=1]
+	%3 = icmp eq i32 %2, 0		; <i1> [#uses=1]
+	%retval.i = select i1 %3, i32 1, i32 %p_5		; <i32> [#uses=1]
+	br label %bar.exit
+
+bar.exit:		; preds = %bb.i, %entry
+	%4 = phi i32 [ %retval.i, %bb.i ], [ %p_5, %entry ]		; <i32> [#uses=1]
+	%5 = icmp eq i32 %4, 0		; <i1> [#uses=0]
+	%6 = tail call i32 @foo(i32 %p_5) nounwind		; <i32> [#uses=0]
+	ret void
+}
+
+declare i32 @foo(i32)





More information about the llvm-commits mailing list