Thumb2: When optimizing for size, do not if-convert branches involving comparisons...
authorPeter Collingbourne <peter@pcc.me.uk>
Thu, 23 Apr 2015 20:31:30 +0000 (20:31 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Thu, 23 Apr 2015 20:31:30 +0000 (20:31 +0000)
This allows the constant island pass to lower these branches to cbn?z
instructions, resulting in a shorter instruction sequence.

Differential Revision: http://reviews.llvm.org/D9183

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

lib/Target/ARM/ARMBaseInstrInfo.cpp
test/CodeGen/Thumb2/2011-06-07-TwoAddrEarlyClobber.ll
test/CodeGen/Thumb2/ifcvt-compare.ll [new file with mode: 0644]
test/CodeGen/Thumb2/v8_IT_3.ll

index 7ee3cb0a3d107d0f205572fe6ae91000cdd215ed..93742dd6c725edfb95dde9aade8c77339b522548 100644 (file)
@@ -1685,6 +1685,33 @@ isProfitableToIfCvt(MachineBasicBlock &MBB,
   if (!NumCycles)
     return false;
 
+  // If we are optimizing for size, see if the branch in the predecessor can be
+  // lowered to cbn?z by the constant island lowering pass, and return false if
+  // so. This results in a shorter instruction sequence.
+  const Function *F = MBB.getParent()->getFunction();
+  if (F->hasFnAttribute(Attribute::OptimizeForSize) ||
+      F->hasFnAttribute(Attribute::MinSize)) {
+    MachineBasicBlock *Pred = *MBB.pred_begin();
+    if (!Pred->empty()) {
+      MachineInstr *LastMI = &*Pred->rbegin();
+      if (LastMI->getOpcode() == ARM::t2Bcc) {
+        MachineBasicBlock::iterator CmpMI = LastMI;
+        if (CmpMI != Pred->begin()) {
+          --CmpMI;
+          if (CmpMI->getOpcode() == ARM::tCMPi8 ||
+              CmpMI->getOpcode() == ARM::t2CMPri) {
+            unsigned Reg = CmpMI->getOperand(0).getReg();
+            unsigned PredReg = 0;
+            ARMCC::CondCodes P = getInstrPredicate(CmpMI, PredReg);
+            if (P == ARMCC::AL && CmpMI->getOperand(1).getImm() == 0 &&
+                isARMLowRegister(Reg))
+              return false;
+          }
+        }
+      }
+    }
+  }
+
   // Attempt to estimate the relative costs of predication versus branching.
   unsigned UnpredCost = Probability.getNumerator() * NumCycles;
   UnpredCost /= Probability.getDenominator();
index fc7d0e1504af38e2a2f10610337ad3b40bcddf7f..b9bfdcbec4e498e60e88e0977bf2e982e257bb1f 100644 (file)
@@ -3,9 +3,9 @@
 %struct.op = type { %struct.op*, %struct.op*, %struct.op* ()*, i32, i16, i16, i8, i8 }
 
 ; CHECK: Perl_ck_sort
-; CHECK: ldreq
-; CHECK: moveq [[REGISTER:(r[0-9]+)|(lr)]]
-; CHECK: streq {{(r[0-9])|(lr)}}, {{\[}}[[REGISTER]]{{\]}}, #24
+; CHECK: ldr
+; CHECK: mov [[REGISTER:(r[0-9]+)|(lr)]]
+; CHECK: str {{(r[0-9])|(lr)}}, {{\[}}[[REGISTER]]{{\]}}, #24
 
 define void @Perl_ck_sort() nounwind optsize {
 entry:
diff --git a/test/CodeGen/Thumb2/ifcvt-compare.ll b/test/CodeGen/Thumb2/ifcvt-compare.ll
new file mode 100644 (file)
index 0000000..8af139a
--- /dev/null
@@ -0,0 +1,47 @@
+; RUN: llc -mtriple=thumbv7-unknown-linux %s -o - | FileCheck %s
+
+declare void @x()
+
+define void @f0(i32 %x) optsize {
+  ; CHECK-LABEL: f0:
+  ; CHECK: cbnz
+  %p = icmp eq i32 %x, 0
+  br i1 %p, label %t, label %f
+
+t:
+  call void @x()
+  br label %f
+
+f:
+  ret void
+}
+
+define void @f1(i32 %x) optsize {
+  ; CHECK-LABEL: f1:
+  ; CHECK: cmp r0, #1
+  ; CHECK: it eq
+  %p = icmp eq i32 %x, 1
+  br i1 %p, label %t, label %f
+
+t:
+  call void @x()
+  br label %f
+
+f:
+  ret void
+}
+
+define void @f2(i32 %x) {
+  ; CHECK-LABEL: f2:
+  ; CHECK: cmp r0, #0
+  ; CHECK: it eq
+  %p = icmp eq i32 %x, 0
+  br i1 %p, label %t, label %f
+
+t:
+  call void @x()
+  br label %f
+
+f:
+  ret void
+}
index 589a20c73d5ca8042456e3901ba93010e6567f28..3ccee5fbb8cab7b4b8126630c520da507467186b 100644 (file)
@@ -24,14 +24,14 @@ entry:
   %tmp = load i32, i32* @G, align 4
   %tmp1 = call i32 @bar(i32 0, i32 0, i32 %tmp) nounwind
   switch i32 %tmp1, label %bb8 [
-    i32 0, label %bb
+    i32 1, label %bb
     i32 536870913, label %bb4
     i32 536870914, label %bb6
   ]
 
 bb:
   %tmp2 = load i32, i32* @G, align 4
-  %tmp4 = icmp eq i32 %tmp2, 0
+  %tmp4 = icmp eq i32 %tmp2, 1
   br i1 %tmp4, label %bb1, label %bb8
 
 bb1: