add test to show suboptimal load merging behavior
[oota-llvm.git] / test / CodeGen / X86 / loop-blocks.ll
1 ; RUN: llc < %s -march=x86-64 -mtriple=x86_64-unknown-linux-gnu -asm-verbose=false | FileCheck %s
2
3 ; These tests check for loop branching structure, and that the loop align
4 ; directive is placed in the expected place.
5
6 ; CodeGen should insert a branch into the middle of the loop in
7 ; order to avoid a branch within the loop.
8
9 ; CHECK-LABEL: simple:
10 ;      CHECK:   jmp   .LBB0_1
11 ; CHECK-NEXT:   align
12 ; CHECK-NEXT: .LBB0_2:
13 ; CHECK-NEXT:   callq loop_latch
14 ; CHECK-NEXT: .LBB0_1:
15 ; CHECK-NEXT:   callq loop_header
16
17 define void @simple() nounwind {
18 entry:
19   br label %loop
20
21 loop:
22   call void @loop_header()
23   %t0 = tail call i32 @get()
24   %t1 = icmp slt i32 %t0, 0
25   br i1 %t1, label %done, label %bb
26
27 bb:
28   call void @loop_latch()
29   br label %loop
30
31 done:
32   call void @exit()
33   ret void
34 }
35
36 ; CodeGen should move block_a to the top of the loop so that it
37 ; falls through into the loop, avoiding a branch within the loop.
38
39 ; CHECK-LABEL: slightly_more_involved:
40 ;      CHECK:   jmp .LBB1_1
41 ; CHECK-NEXT:   align
42 ; CHECK-NEXT: .LBB1_4:
43 ; CHECK-NEXT:   callq bar99
44 ; CHECK-NEXT: .LBB1_1:
45 ; CHECK-NEXT:   callq body
46
47 define void @slightly_more_involved() nounwind {
48 entry:
49   br label %loop
50
51 loop:
52   call void @body()
53   %t0 = call i32 @get()
54   %t1 = icmp slt i32 %t0, 2
55   br i1 %t1, label %block_a, label %bb
56
57 bb:
58   %t2 = call i32 @get()
59   %t3 = icmp slt i32 %t2, 99
60   br i1 %t3, label %exit, label %loop
61
62 block_a:
63   call void @bar99()
64   br label %loop
65
66 exit:
67   call void @exit()
68   ret void
69 }
70
71 ; Same as slightly_more_involved, but block_a is now a CFG diamond with
72 ; fallthrough edges which should be preserved.
73 ; "callq block_a_merge_func" is tail duped.
74
75 ; CHECK-LABEL: yet_more_involved:
76 ;      CHECK:   jmp .LBB2_1
77 ; CHECK-NEXT:   align
78 ; CHECK-NEXT: .LBB2_5:
79 ; CHECK-NEXT:   callq block_a_true_func
80 ; CHECK-NEXT:   callq block_a_merge_func
81 ; CHECK-NEXT: .LBB2_1:
82 ; CHECK-NEXT:   callq body
83 ;
84 ; LBB2_4
85 ;      CHECK:   callq bar99
86 ; CHECK-NEXT:   callq get
87 ; CHECK-NEXT:   cmpl $2999, %eax
88 ; CHECK-NEXT:   jle .LBB2_5
89 ; CHECK-NEXT:   callq block_a_false_func
90 ; CHECK-NEXT:   callq block_a_merge_func
91 ; CHECK-NEXT:   jmp .LBB2_1
92
93 define void @yet_more_involved() nounwind {
94 entry:
95   br label %loop
96
97 loop:
98   call void @body()
99   %t0 = call i32 @get()
100   %t1 = icmp slt i32 %t0, 2
101   br i1 %t1, label %block_a, label %bb
102
103 bb:
104   %t2 = call i32 @get()
105   %t3 = icmp slt i32 %t2, 99
106   br i1 %t3, label %exit, label %loop
107
108 block_a:
109   call void @bar99()
110   %z0 = call i32 @get()
111   %z1 = icmp slt i32 %z0, 3000
112   br i1 %z1, label %block_a_true, label %block_a_false
113
114 block_a_true:
115   call void @block_a_true_func()
116   br label %block_a_merge
117
118 block_a_false:
119   call void @block_a_false_func()
120   br label %block_a_merge
121
122 block_a_merge:
123   call void @block_a_merge_func()
124   br label %loop
125
126 exit:
127   call void @exit()
128   ret void
129 }
130
131 ; CodeGen should move the CFG islands that are part of the loop but don't
132 ; conveniently fit anywhere so that they are at least contiguous with the
133 ; loop.
134
135 ; CHECK-LABEL: cfg_islands:
136 ;      CHECK:   jmp     .LBB3_1
137 ; CHECK-NEXT:   align
138 ; CHECK-NEXT: .LBB3_7:
139 ; CHECK-NEXT:   callq   bar100
140 ; CHECK-NEXT: .LBB3_1:
141 ; CHECK-NEXT:   callq   loop_header
142 ;      CHECK:   jl .LBB3_7
143 ;      CHECK:   jge .LBB3_3
144 ; CHECK-NEXT:   callq   bar101
145 ; CHECK-NEXT:   jmp     .LBB3_1
146 ; CHECK-NEXT:   align
147 ; CHECK-NEXT: .LBB3_3:
148 ;      CHECK:   jge .LBB3_4
149 ; CHECK-NEXT:   callq   bar102
150 ; CHECK-NEXT:   jmp     .LBB3_1
151 ; CHECK-NEXT: .LBB3_4:
152 ;      CHECK:   jl .LBB3_6
153 ; CHECK-NEXT:   callq   loop_latch
154 ; CHECK-NEXT:   jmp     .LBB3_1
155 ; CHECK-NEXT: .LBB3_6:
156
157 define void @cfg_islands() nounwind {
158 entry:
159   br label %loop
160
161 loop:
162   call void @loop_header()
163   %t0 = call i32 @get()
164   %t1 = icmp slt i32 %t0, 100
165   br i1 %t1, label %block100, label %bb
166
167 bb:
168   %t2 = call i32 @get()
169   %t3 = icmp slt i32 %t2, 101
170   br i1 %t3, label %block101, label %bb1
171
172 bb1:
173   %t4 = call i32 @get()
174   %t5 = icmp slt i32 %t4, 102
175   br i1 %t5, label %block102, label %bb2
176
177 bb2:
178   %t6 = call i32 @get()
179   %t7 = icmp slt i32 %t6, 103
180   br i1 %t7, label %exit, label %bb3
181
182 bb3:
183   call void @loop_latch()
184   br label %loop
185
186 exit:
187   call void @exit()
188   ret void
189
190 block100:
191   call void @bar100()
192   br label %loop
193
194 block101:
195   call void @bar101()
196   br label %loop
197
198 block102:
199   call void @bar102()
200   br label %loop
201 }
202
203 declare void @bar99() nounwind
204 declare void @bar100() nounwind
205 declare void @bar101() nounwind
206 declare void @bar102() nounwind
207 declare void @body() nounwind
208 declare void @exit() nounwind
209 declare void @loop_header() nounwind
210 declare void @loop_latch() nounwind
211 declare i32 @get() nounwind
212 declare void @block_a_true_func() nounwind
213 declare void @block_a_false_func() nounwind
214 declare void @block_a_merge_func() nounwind