[ARM] Cortex-M4 schedule additions
[llvm-complete.git] / test / CodeGen / ARM / tail-opts.ll
blob475b80b3bb070eec6d84366483e94d68e5c08df5
1 ; RUN: llc < %s -mtriple=arm-apple-darwin -relocation-model=dynamic-no-pic -mcpu=cortex-a8 -asm-verbose=false | FileCheck %s
3 declare void @bar(i32)
4 declare void @car(i32)
5 declare void @dar(i32)
6 declare void @ear(i32)
7 declare void @far(i32)
8 declare i1 @qux()
10 @GHJK = global i32 0
12 declare i8* @choose(i8*, i8*)
14 ; BranchFolding should tail-duplicate the indirect jump to avoid
15 ; redundant branching.
17 ; CHECK-LABEL: tail_duplicate_me:
18 ; CHECK:      qux
19 ; CHECK:      movw r{{[0-9]+}}, :lower16:_GHJK
20 ; CHECK:      movt r{{[0-9]+}}, :upper16:_GHJK
21 ; CHECK:      str r
22 ; CHECK-NEXT: bx r
23 ; CHECK:      qux
24 ; CHECK:      movw r{{[0-9]+}}, :lower16:_GHJK
25 ; CHECK:      movt r{{[0-9]+}}, :upper16:_GHJK
26 ; CHECK:      str r
27 ; CHECK-NEXT: bx r
28 ; CHECK:      movw r{{[0-9]+}}, :lower16:_GHJK
29 ; CHECK:      movt r{{[0-9]+}}, :upper16:_GHJK
30 ; CHECK:      str r
31 ; CHECK-NEXT: bx r
33 define void @tail_duplicate_me() nounwind {
34 entry:
35   %a = call i1 @qux()
36   %c = call i8* @choose(i8* blockaddress(@tail_duplicate_me, %return),
37                         i8* blockaddress(@tail_duplicate_me, %altret))
38   br i1 %a, label %A, label %next
39 next:
40   %b = call i1 @qux()
41   br i1 %b, label %B, label %C
44   call void @bar(i32 0)
45   store i32 0, i32* @GHJK
46   br label %M
49   call void @car(i32 1)
50   store i32 0, i32* @GHJK
51   br label %M
54   call void @dar(i32 2)
55   store i32 0, i32* @GHJK
56   br label %M
59   indirectbr i8* %c, [label %return, label %altret]
61 return:
62   call void @ear(i32 1000)
63   ret void
64 altret:
65   call void @far(i32 1001)
66   ret void
69 ; Use alternating abort functions so that the blocks we wish to merge are not
70 ; layout successors during branch folding.
72 ; CHECK-LABEL: merge_alternating_aborts:
73 ; CHECK-NOT: _abort
74 ; CHECK-NOT: _alt_abort
75 ; CHECK: bxne lr
76 ; CHECK-NOT: _abort
77 ; CHECK-NOT: _alt_abort
78 ; CHECK: LBB{{.*}}:
79 ; CHECK: mov lr, pc
80 ; CHECK: b _alt_abort
81 ; CHECK-NOT: _abort
82 ; CHECK-NOT: _alt_abort
83 ; CHECK: LBB{{.*}}:
84 ; CHECK: mov lr, pc
85 ; CHECK: b _abort
86 ; CHECK-NOT: _abort
87 ; CHECK-NOT: _alt_abort
89 declare void @abort()
90 declare void @alt_abort()
92 define void @merge_alternating_aborts() {
93 entry:
94   %c1 = call i1 @qux()
95   br i1 %c1, label %cont1, label %abort1
96 abort1:
97   call void @abort()
98   unreachable
99 cont1:
100   %c2 = call i1 @qux()
101   br i1 %c2, label %cont2, label %abort2
102 abort2:
103   call void @alt_abort()
104   unreachable
105 cont2:
106   %c3 = call i1 @qux()
107   br i1 %c3, label %cont3, label %abort3
108 abort3:
109   call void @abort()
110   unreachable
111 cont3:
112   %c4 = call i1 @qux()
113   br i1 %c4, label %cont4, label %abort4
114 abort4:
115   call void @alt_abort()
116   unreachable
117 cont4:
118   ret void