Teach MachineCSE how to do simple cross-block CSE involving physregs. This allows...
authorEli Friedman <eli.friedman@gmail.com>
Wed, 4 May 2011 19:54:24 +0000 (19:54 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Wed, 4 May 2011 19:54:24 +0000 (19:54 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130862 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/MachineCSE.cpp
test/CodeGen/Thumb2/thumb2-cbnz.ll
test/CodeGen/X86/cmp-redundant.ll [new file with mode: 0644]

index f97ccf65790f6d412d3ee9bf4612440cd1a7cd26..ff7062da30e66e321327304411b82b5e83d8bfda 100644 (file)
@@ -82,7 +82,8 @@ namespace {
                                 MachineBasicBlock::const_iterator E) const ;
     bool hasLivePhysRegDefUses(const MachineInstr *MI,
                                const MachineBasicBlock *MBB,
-                               SmallSet<unsigned,8> &PhysRefs) const;
+                               SmallSet<unsigned,8> &PhysRefs,
+                               SmallVector<unsigned,8> &PhysDefs) const;
     bool PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
                           SmallSet<unsigned,8> &PhysRefs) const;
     bool isCSECandidate(MachineInstr *MI);
@@ -189,7 +190,8 @@ MachineCSE::isPhysDefTriviallyDead(unsigned Reg,
 /// instruction does not uses a physical register.
 bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
                                        const MachineBasicBlock *MBB,
-                                       SmallSet<unsigned,8> &PhysRefs) const {
+                                       SmallSet<unsigned,8> &PhysRefs,
+                                       SmallVector<unsigned,8> &PhysDefs) const{
   MachineBasicBlock::const_iterator I = MI; I = llvm::next(I);
   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
     const MachineOperand &MO = MI->getOperand(i);
@@ -206,6 +208,7 @@ bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
     if (MO.isDef() &&
         (MO.isDead() || isPhysDefTriviallyDead(Reg, I, MBB->end())))
       continue;
+    PhysDefs.push_back(Reg);
     PhysRefs.insert(Reg);
     for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias)
       PhysRefs.insert(*Alias);
@@ -216,35 +219,40 @@ bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
 
 bool MachineCSE::PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
                                   SmallSet<unsigned,8> &PhysRefs) const {
-  // For now conservatively returns false if the common subexpression is
-  // not in the same basic block as the given instruction.
-  MachineBasicBlock *MBB = MI->getParent();
-  if (CSMI->getParent() != MBB)
-    return false;
-  MachineBasicBlock::const_iterator I = CSMI; I = llvm::next(I);
-  MachineBasicBlock::const_iterator E = MI;
+  // Look backward from MI to find CSMI.
   unsigned LookAheadLeft = LookAheadLimit;
+  MachineBasicBlock::const_reverse_iterator I(MI);
+  MachineBasicBlock::const_reverse_iterator E(MI->getParent()->rend());
   while (LookAheadLeft) {
-    // Skip over dbg_value's.
-    while (I != E && I->isDebugValue())
-      ++I;
+    while (LookAheadLeft && I != E) {
+      // Skip over dbg_value's.
+      while (I != E && I->isDebugValue())
+        ++I;
 
-    if (I == E)
-      return true;
+      if (&*I == CSMI)
+        return true;
 
-    for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
-      const MachineOperand &MO = I->getOperand(i);
-      if (!MO.isReg() || !MO.isDef())
-        continue;
-      unsigned MOReg = MO.getReg();
-      if (TargetRegisterInfo::isVirtualRegister(MOReg))
-        continue;
-      if (PhysRefs.count(MOReg))
-        return false;
-    }
+      for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
+        const MachineOperand &MO = I->getOperand(i);
+        if (!MO.isReg() || !MO.isDef())
+          continue;
+        unsigned MOReg = MO.getReg();
+        if (TargetRegisterInfo::isVirtualRegister(MOReg))
+          continue;
+        if (PhysRefs.count(MOReg))
+          return false;
+      }
 
-    --LookAheadLeft;
-    ++I;
+      --LookAheadLeft;
+      ++I;
+    }
+    // Go back another BB; for now, only go back at most one BB.
+    MachineBasicBlock *CSBB = CSMI->getParent();
+    MachineBasicBlock *BB = MI->getParent();
+    if (!CSBB->isSuccessor(BB) || BB->pred_size() != 1)
+      return false;
+    I = CSBB->rbegin();
+    E = CSBB->rend();
   }
 
   return false;
@@ -395,7 +403,8 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) {
     // used, then it's not safe to replace it with a common subexpression.
     // It's also not safe if the instruction uses physical registers.
     SmallSet<unsigned,8> PhysRefs;
-    if (FoundCSE && hasLivePhysRegDefUses(MI, MBB, PhysRefs)) {
+    SmallVector<unsigned,8> DirectPhysRefs;
+    if (FoundCSE && hasLivePhysRegDefUses(MI, MBB, PhysRefs, DirectPhysRefs)) {
       FoundCSE = false;
 
       // ... Unless the CS is local and it also defines the physical register
@@ -448,6 +457,13 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) {
         MRI->clearKillFlags(CSEPairs[i].second);
       }
       MI->eraseFromParent();
+      if (!DirectPhysRefs.empty() && CSMI->getParent() != MBB) {
+        assert(CSMI->getParent()->isSuccessor(MBB));
+        SmallVector<unsigned,8>::iterator PI = DirectPhysRefs.begin(),
+                                          PE = DirectPhysRefs.end();
+        for (; PI != PE; ++PI)
+          MBB->addLiveIn(*PI);
+      }
       ++NumCSEs;
       if (!PhysRefs.empty())
         ++NumPhysCSEs;
index 10a4985d17364063fc2484eabe52cdfe55c94e19..0ca97647d54507cfd871336743cdfa9596f8b91b 100644 (file)
@@ -21,8 +21,8 @@ bb7:                                              ; preds = %bb3
 
 bb9:                                              ; preds = %bb7
 ; CHECK:      cmp r0, #0
-; CHECK:      cmp r0, #0
-; CHECK-NEXT: cbnz
+; CHECK-NOT: cmp
+; CHECK: cbnz
   %0 = tail call  double @floor(double %b) nounwind readnone ; <double> [#uses=0]
   br label %bb11
 
diff --git a/test/CodeGen/X86/cmp-redundant.ll b/test/CodeGen/X86/cmp-redundant.ll
new file mode 100644 (file)
index 0000000..d30ea3e
--- /dev/null
@@ -0,0 +1,22 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin10 | FileCheck %s
+
+define i32 @cmp(i32* %aa, i32* %bb) nounwind readnone ssp {
+entry:
+  %a = load i32* %aa
+  %b = load i32* %bb
+  %cmp = icmp sgt i32 %a, %b
+  br i1 %cmp, label %return, label %if.end
+; CHECK: cmp:
+; CHECK: cmpl
+; CHECK: jg
+if.end:                                           ; preds = %entry
+; CHECK-NOT: cmpl
+; CHECK: cmov
+  %cmp4 = icmp slt i32 %a, %b
+  %. = select i1 %cmp4, i32 2, i32 111
+  br label %return
+
+return:                                           ; preds = %if.end, %entry
+  %retval.0 = phi i32 [ 1, %entry ], [ %., %if.end ]
+  ret i32 %retval.0
+}