Make tBX_RET and tBX_RET_vararg predicable.
authorJim Grosbach <grosbach@apple.com>
Fri, 8 Jul 2011 21:50:04 +0000 (21:50 +0000)
committerJim Grosbach <grosbach@apple.com>
Fri, 8 Jul 2011 21:50:04 +0000 (21:50 +0000)
The normal tBX instruction is predicable, so there's no reason the
pseudos for using it as a return shouldn't be. Gives us some nice code-gen
improvements as can be seen by the test changes. In particular, several
tests now have to disable if-conversion because it works too well and defeats
the test.

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

lib/Target/ARM/ARMConstantIslandPass.cpp
lib/Target/ARM/ARMInstrThumb.td
lib/Target/ARM/Thumb1FrameLowering.cpp
test/CodeGen/Thumb2/machine-licm.ll
test/CodeGen/Thumb2/thumb2-bcc.ll
test/CodeGen/Thumb2/thumb2-branch.ll
test/CodeGen/Thumb2/thumb2-ifcvt1.ll

index 309caee42b95a2cfcaf76c60cd68478870ae9f07..f45ebdc53500248d171e086dd6dda3183d794a4e 100644 (file)
@@ -1538,7 +1538,10 @@ bool ARMConstantIslands::UndoLRSpillRestore() {
     if (MI->getOpcode() == ARM::tPOP_RET &&
         MI->getOperand(2).getReg() == ARM::PC &&
         MI->getNumExplicitOperands() == 3) {
-      BuildMI(MI->getParent(), MI->getDebugLoc(), TII->get(ARM::tBX_RET));
+      // Create the new insn and copy the predicate from the old.
+      BuildMI(MI->getParent(), MI->getDebugLoc(), TII->get(ARM::tBX_RET))
+        .addOperand(MI->getOperand(0))
+        .addOperand(MI->getOperand(1));
       MI->eraseFromParent();
       MadeChange = true;
     }
index 9a96dc7fdaeab8192bdc0d2ed8d3f12b800392bf..bba0ab6450c3adc91a8393af3f493cd2a9d6a4a1 100644 (file)
@@ -385,13 +385,13 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
 }
 
 let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
-  def tBX_RET : tPseudoExpand<(outs), (ins), Size2Bytes, IIC_Br,
-                   [(ARMretflag)], (tBX LR, (ops 14, zero_reg))>;
+  def tBX_RET : tPseudoExpand<(outs), (ins pred:$p), Size2Bytes, IIC_Br,
+                   [(ARMretflag)], (tBX LR, pred:$p)>;
 
   // Alternative return instruction used by vararg functions.
-  def tBX_RET_vararg : tPseudoExpand<(outs), (ins tGPR:$Rm),
+  def tBX_RET_vararg : tPseudoExpand<(outs), (ins tGPR:$Rm, pred:$p),
                    Size2Bytes, IIC_Br, [],
-                   (tBX GPR:$Rm, (ops 14, zero_reg))>;
+                   (tBX GPR:$Rm, pred:$p)>;
 }
 
 // All calls clobber the non-callee saved registers. SP is marked as a use to
index 48211d852f82d43a402e432ac3c1769c60e5eec3..c258870e48a58025a5984d98d874eff769e8dbbe 100644 (file)
@@ -273,8 +273,8 @@ void Thumb1FrameLowering::emitEpilogue(MachineFunction &MF,
 
     emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, VARegSaveSize);
 
-    BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg))
-      .addReg(ARM::R3, RegState::Kill);
+    AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg))
+      .addReg(ARM::R3, RegState::Kill));
     // erase the old tBX_RET instruction
     MBB.erase(MBBI);
   }
index ebe58e599fccdb6e54e142e0163d50c8add3b654..b199d699811402da006364df62a9950c864105d3 100644 (file)
@@ -8,26 +8,25 @@
 define void @t1(i32* nocapture %vals, i32 %c) nounwind {
 entry:
 ; CHECK: t1:
-; CHECK: cbz
+; CHECK: bxeq lr
+
   %0 = icmp eq i32 %c, 0                          ; <i1> [#uses=1]
   br i1 %0, label %return, label %bb.nph
 
 bb.nph:                                           ; preds = %entry
-; CHECK: BB#1
 ; CHECK: movw r[[R2:[0-9]+]], :lower16:L_GV$non_lazy_ptr
 ; CHECK: movt r[[R2]], :upper16:L_GV$non_lazy_ptr
 ; CHECK: ldr{{(.w)?}} r[[R2b:[0-9]+]], [r[[R2]]
 ; CHECK: ldr{{.*}}, [r[[R2b]]
-; CHECK: LBB0_2
+; CHECK: LBB0_
 ; CHECK-NOT: LCPI0_0:
 
-; PIC: BB#1
 ; PIC: movw r[[R2:[0-9]+]], :lower16:(L_GV$non_lazy_ptr-(LPC0_0+4))
 ; PIC: movt r[[R2]], :upper16:(L_GV$non_lazy_ptr-(LPC0_0+4))
 ; PIC: add r[[R2]], pc
 ; PIC: ldr{{(.w)?}} r[[R2b:[0-9]+]], [r[[R2]]
 ; PIC: ldr{{.*}}, [r[[R2b]]
-; PIC: LBB0_2
+; PIC: LBB0_
 ; PIC-NOT: LCPI0_0:
 ; PIC: .section
   %.pre = load i32* @GV, align 4                  ; <i32> [#uses=1]
index aae9f5c0af714e0f13e59a330032dcb25e479e89..5e07b7c6dcf4ac9ce0ef3b42a9b1f04c47245688 100644 (file)
@@ -1,5 +1,7 @@
-; RUN: llc < %s -march=thumb -mattr=+thumb2 | FileCheck %s
-; RUN: llc < %s -march=thumb -mattr=+thumb2 | not grep it
+; RUN: llc < %s -ifcvt-limit=0 -march=thumb -mattr=+thumb2 | FileCheck %s
+; RUN: llc < %s -ifcvt-limit=0 -march=thumb -mattr=+thumb2 | not grep it
+; If-conversion defeats the purpose of this test, which is to check CBZ
+; generation, so turn it off.
 
 define i32 @t1(i32 %a, i32 %b, i32 %c) {
 ; CHECK: t1:
index 1d2af7a547456fd6674be5fa7a1c6b367e5c59b4..9c6f68b343190f4ce34c638cb7a80b5a05c0c5ba 100644 (file)
@@ -1,4 +1,6 @@
-; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mattr=+thumb2 | FileCheck %s
+; RUN: llc < %s -ifcvt-limit=0 -mtriple=thumbv7-apple-darwin -mattr=+thumb2 | FileCheck %s
+; If-conversion defeats the purpose of this test, which is to check conditional
+; branch generation, so turn it off.
 
 define i32 @f1(i32 %a, i32 %b, i32* %v) {
 entry:
index 1533040671f70f5ea6ca03d569da92a3f79292b5..a4035bb8ed491eb7df7dc5116e622d273b970a7e 100644 (file)
@@ -2,8 +2,10 @@
 
 define i32 @t1(i32 %a, i32 %b, i32 %c, i32 %d) nounwind {
 ; CHECK: t1:
-; CHECK: it ne
+; CHECK: ittt ne
 ; CHECK: cmpne
+; CHECK: addne
+; CHECK: bxne lr
        switch i32 %c, label %cond_next [
                 i32 1, label %cond_true
                 i32 7, label %cond_true