Thumb2: When applying branch optimizations, visit branches in reverse order.
authorPeter Collingbourne <peter@pcc.me.uk>
Thu, 23 Apr 2015 20:31:35 +0000 (20:31 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Thu, 23 Apr 2015 20:31:35 +0000 (20:31 +0000)
The order in which branches appear in ImmBranches is approximately their
order within the function body. By visiting later branches first, we reduce
the distance between earlier forward branches and their targets, making it
more likely that the cbn?z optimization, which can only apply to forward
branches, will succeed for those earlier branches.

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

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

lib/Target/ARM/ARMConstantIslandPass.cpp
test/CodeGen/Thumb2/cbnz.ll [new file with mode: 0644]

index 00c92fcddde756cceddd2d10fd8176fa2b9a4b1f..e6d4b14a2628ef83237647637d5565fb53e8e4f1 100644 (file)
@@ -1745,8 +1745,13 @@ bool ARMConstantIslands::optimizeThumb2Instructions() {
 bool ARMConstantIslands::optimizeThumb2Branches() {
   bool MadeChange = false;
 
-  for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i) {
-    ImmBranch &Br = ImmBranches[i];
+  // The order in which branches appear in ImmBranches is approximately their
+  // order within the function body. By visiting later branches first, we reduce
+  // the distance between earlier forward branches and their targets, making it
+  // more likely that the cbn?z optimization, which can only apply to forward
+  // branches, will succeed.
+  for (unsigned i = ImmBranches.size(); i != 0; --i) {
+    ImmBranch &Br = ImmBranches[i-1];
     unsigned Opcode = Br.MI->getOpcode();
     unsigned NewOpc = 0;
     unsigned Scale = 1;
diff --git a/test/CodeGen/Thumb2/cbnz.ll b/test/CodeGen/Thumb2/cbnz.ll
new file mode 100644 (file)
index 0000000..5c0bb5b
--- /dev/null
@@ -0,0 +1,54 @@
+; RUN: llc -mtriple thumbv7-unknown-linux -o - %s | FileCheck %s
+
+declare void @x()
+declare void @y()
+
+define void @f(i32 %x, i32 %y) {
+  ; CHECK-LABEL: f:
+  ; CHECK: cbnz
+  %p = icmp eq i32 %x, 0
+  br i1 %p, label %t, label %f
+
+t:
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  ; CHECK: cbnz
+  %q = icmp eq i32 %y, 0
+  br i1 %q, label %t2, label %f
+
+t2:
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  call void @x()
+  br label %f
+
+f:
+  call void @y()
+  ret void
+}