ARM: Fix optimizeCompare to correctly check safe condition.
authorManman Ren <mren@apple.com>
Wed, 11 Jul 2012 22:51:44 +0000 (22:51 +0000)
committerManman Ren <mren@apple.com>
Wed, 11 Jul 2012 22:51:44 +0000 (22:51 +0000)
It is safe if CPSR is killed or re-defined.
When we are done with the basic block, check whether CPSR is live-out.
Do not optimize away cmp if CPSR is live-out.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160090 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMBaseInstrInfo.cpp
test/CodeGen/ARM/sub-cmp-peephole.ll

index 57c20ae6a44c4a154b144dab1efb313f2cf9043f..3393f0975aa695b18240abc21b84f7669cca3e93 100644 (file)
@@ -1974,10 +1974,10 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2,
   case ARM::t2EORri: {
     // Scan forward for the use of CPSR
     // When checking against MI: if it's a conditional code requires
-    // checking of V bit, then this is not safe to do. If we can't find the
-    // CPSR use (i.e. used in another block), then it's not safe to perform
-    // the optimization.
-    // When checking against Sub, we handle the condition codes GE, LT, GT, LE.
+    // checking of V bit, then this is not safe to do.
+    // It is safe to remove CmpInstr if CPSR is redefined or killed.
+    // If we are done with the basic block, we need to check whether CPSR is
+    // live-out.
     SmallVector<std::pair<MachineOperand*, ARMCC::CondCodes>, 4>
         OperandsToUpdate;
     bool isSafe = false;
@@ -2017,7 +2017,7 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2,
         else
           switch (CC) {
           default:
-            isSafe = true;
+            // CPSR can be used mutliple times, we should continue.
             break;
           case ARMCC::VS:
           case ARMCC::VC:
@@ -2030,10 +2030,15 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2,
       }
     }
 
-    // If the candidate is Sub, we may exit the loop at end of the basic block.
-    // In that case, it is still safe to remove CmpInstr.
-    if (!isSafe && !Sub)
-      return false;
+    // If CPSR is not killed nor re-defined, we should check whether it is
+    // live-out. If it is live-out, do not optimize.
+    if (!isSafe) {
+      MachineBasicBlock *MBB = CmpInstr->getParent();
+      for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
+               SE = MBB->succ_end(); SI != SE; ++SI)
+        if ((*SI)->isLiveIn(ARM::CPSR))
+          return false;
+    }
 
     // Toggle the optional operand to CPSR.
     MI->getOperand(5).setReg(ARM::CPSR);
index c46c891603d4777e542c65f568baa89bb98a80b3..6fcbdee30d340a19f336b39ae3e6dd14f19b8bf2 100644 (file)
@@ -44,3 +44,22 @@ entry:
   %sub. = select i1 %cmp, i32 %sub, i32 0
   ret i32 %sub.
 }
+; If CPSR is live-out, we can't remove cmp if there exists
+; a swapped sub.
+define i32 @j(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: j:
+; CHECK: sub
+; CHECK: cmp
+  %cmp = icmp eq i32 %b, %a
+  %sub = sub nsw i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  %cmp2 = icmp sgt i32 %b, %a
+  %sel = select i1 %cmp2, i32 %sub, i32 %a
+  ret i32 %sel
+
+if.else:
+  ret i32 %sub
+}