[Reland][Runtimes] Merge 'compile_commands.json' files from runtimes build (#116303)
[llvm-project.git] / llvm / test / CodeGen / X86 / loop-blocks.ll
blobe970061c0cf705cd8d58c578d3614914c9d040e3
1 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -asm-verbose=false | FileCheck %s
3 ; These tests check for loop branching structure, and that the loop align
4 ; directive is placed in the expected place.
6 ; CodeGen should insert a branch into the middle of the loop in
7 ; order to avoid a branch within the loop.
9 ; CHECK-LABEL: simple:
10 ;      CHECK:   align
11 ; CHECK-NEXT: .LBB0_1:
12 ; CHECK-NEXT:   callq loop_header
13 ;      CHECK:   js .LBB0_3
14 ; CHECK-NEXT:   callq loop_latch
15 ; CHECK-NEXT:   jmp .LBB0_1
16 ; CHECK-NEXT: .LBB0_3:
17 ; CHECK-NEXT:   callq exit
19 define void @simple() nounwind {
20 entry:
21   br label %loop
23 loop:
24   call void @loop_header()
25   %t0 = tail call i32 @get()
26   %t1 = icmp slt i32 %t0, 0
27   br i1 %t1, label %done, label %bb
29 bb:
30   call void @loop_latch()
31   br label %loop
33 done:
34   call void @exit()
35   ret void
38 ; CodeGen should move block_a to the top of the loop so that it
39 ; falls through into the loop, avoiding a branch within the loop.
41 ; CHECK-LABEL: slightly_more_involved:
42 ;      CHECK:   jmp .LBB1_1
43 ; CHECK-NEXT:   align
44 ; CHECK-NEXT: .LBB1_4:
45 ; CHECK-NEXT:   callq bar99
46 ; CHECK-NEXT: .LBB1_1:
47 ; CHECK-NEXT:   callq body
49 define void @slightly_more_involved() nounwind {
50 entry:
51   br label %loop
53 loop:
54   call void @body()
55   %t0 = call i32 @get()
56   %t1 = icmp slt i32 %t0, 2
57   br i1 %t1, label %block_a, label %bb
59 bb:
60   %t2 = call i32 @get()
61   %t3 = icmp slt i32 %t2, 99
62   br i1 %t3, label %exit, label %loop
64 block_a:
65   call void @bar99()
66   br label %loop
68 exit:
69   call void @exit()
70   ret void
73 ; Same as slightly_more_involved, but block_a is now a CFG diamond with
74 ; fallthrough edges which should be preserved.
75 ; "callq block_a_merge_func" is tail duped.
77 ; CHECK-LABEL: yet_more_involved:
78 ;      CHECK:   jmp .LBB2_1
79 ; CHECK-NEXT:   align
81 ;      CHECK: .LBB2_1:
82 ; CHECK-NEXT:   callq body
83 ; CHECK-NEXT:   callq get
84 ; CHECK-NEXT:   cmpl $2, %eax
85 ; CHECK-NEXT:   jge .LBB2_2
86 ; CHECK-NEXT:   callq bar99
87 ; CHECK-NEXT:   callq get
88 ; CHECK-NEXT:   cmpl $2999, %eax
89 ; CHECK-NEXT:   jg .LBB2_6
90 ; CHECK-NEXT:   callq block_a_true_func
91 ; CHECK-NEXT:   callq block_a_merge_func
92 ; CHECK-NEXT:   jmp .LBB2_1
93 ; CHECK-NEXT:   align
94 ; CHECK-NEXT: .LBB2_6:
95 ; CHECK-NEXT:   callq block_a_false_func
96 ; CHECK-NEXT:   callq block_a_merge_func
97 ; CHECK-NEXT:   jmp .LBB2_1
99 define void @yet_more_involved() nounwind {
100 entry:
101   br label %loop
103 loop:
104   call void @body()
105   %t0 = call i32 @get()
106   %t1 = icmp slt i32 %t0, 2
107   br i1 %t1, label %block_a, label %bb
110   %t2 = call i32 @get()
111   %t3 = icmp slt i32 %t2, 99
112   br i1 %t3, label %exit, label %loop
114 block_a:
115   call void @bar99()
116   %z0 = call i32 @get()
117   %z1 = icmp slt i32 %z0, 3000
118   br i1 %z1, label %block_a_true, label %block_a_false
120 block_a_true:
121   call void @block_a_true_func()
122   br label %block_a_merge
124 block_a_false:
125   call void @block_a_false_func()
126   br label %block_a_merge
128 block_a_merge:
129   call void @block_a_merge_func()
130   br label %loop
132 exit:
133   call void @exit()
134   ret void
137 ; CodeGen should move the CFG islands that are part of the loop but don't
138 ; conveniently fit anywhere so that they are at least contiguous with the
139 ; loop.
141 ; CHECK-LABEL: cfg_islands:
142 ;      CHECK:   jmp     .LBB3_1
143 ; CHECK-NEXT:   align
144 ; CHECK-NEXT: .LBB3_7:
145 ; CHECK-NEXT:   callq   bar100
146 ; CHECK-NEXT: .LBB3_1:
147 ; CHECK-NEXT:   callq   loop_header
148 ;      CHECK:   jl .LBB3_7
149 ;      CHECK:   jge .LBB3_3
150 ; CHECK-NEXT:   callq   bar101
151 ; CHECK-NEXT:   jmp     .LBB3_1
152 ; CHECK-NEXT:   align
153 ; CHECK-NEXT: .LBB3_3:
154 ;      CHECK:   jge .LBB3_4
155 ; CHECK-NEXT:   callq   bar102
156 ; CHECK-NEXT:   jmp     .LBB3_1
157 ; CHECK-NEXT: .LBB3_4:
158 ;      CHECK:   jl .LBB3_6
159 ; CHECK-NEXT:   callq   loop_latch
160 ; CHECK-NEXT:   jmp     .LBB3_1
161 ; CHECK-NEXT: .LBB3_6:
163 define void @cfg_islands() nounwind {
164 entry:
165   br label %loop
167 loop:
168   call void @loop_header()
169   %t0 = call i32 @get()
170   %t1 = icmp slt i32 %t0, 100
171   br i1 %t1, label %block100, label %bb
174   %t2 = call i32 @get()
175   %t3 = icmp slt i32 %t2, 101
176   br i1 %t3, label %block101, label %bb1
178 bb1:
179   %t4 = call i32 @get()
180   %t5 = icmp slt i32 %t4, 102
181   br i1 %t5, label %block102, label %bb2
183 bb2:
184   %t6 = call i32 @get()
185   %t7 = icmp slt i32 %t6, 103
186   br i1 %t7, label %exit, label %bb3
188 bb3:
189   call void @loop_latch()
190   br label %loop
192 exit:
193   call void @exit()
194   ret void
196 block100:
197   call void @bar100()
198   br label %loop
200 block101:
201   call void @bar101()
202   br label %loop
204 block102:
205   call void @bar102()
206   br label %loop
209 ; CHECK-LABEL: check_minsize:
210 ; CHECK-NOT:   align
211 ; CHECK:      .LBB4_1:
212 ; CHECK-NEXT:   callq loop_header
213 ; CHECK:        callq loop_latch
214 ; CHECK:      .LBB4_3:
215 ; CHECK:        callq exit
218 define void @check_minsize() minsize nounwind {
219 entry:
220   br label %loop
222 loop:
223   call void @loop_header()
224   %t0 = tail call i32 @get()
225   %t1 = icmp slt i32 %t0, 0
226   br i1 %t1, label %done, label %bb
229   call void @loop_latch()
230   br label %loop
232 done:
233   call void @exit()
234   ret void
237 ; This is exactly the same function as slightly_more_involved.
238 ; The difference is that when optimising for size, we do not want
239 ; to see this reordering.
241 ; CHECK-LABEL: slightly_more_involved_2:
242 ; CHECK-NOT:      jmp .LBB5_1
243 ; CHECK:          .LBB5_1:
244 ; CHECK-NEXT:     callq body
246 define void @slightly_more_involved_2() #0 {
247 entry:
248   br label %loop
250 loop:
251   call void @body()
252   %t0 = call i32 @get()
253   %t1 = icmp slt i32 %t0, 2
254   br i1 %t1, label %block_a, label %bb
257   %t2 = call i32 @get()
258   %t3 = icmp slt i32 %t2, 99
259   br i1 %t3, label %exit, label %loop
261 block_a:
262   call void @bar99()
263   br label %loop
265 exit:
266   call void @exit()
267   ret void
270 attributes #0 = { minsize norecurse nounwind optsize readnone uwtable }
272 ; CHECK-LABEL: slightly_more_involved_2_pgso:
273 ; CHECK-NOT:      jmp .LBB6_1
274 ; CHECK:          .LBB6_1:
275 ; CHECK-NEXT:     callq body
277 define void @slightly_more_involved_2_pgso() norecurse nounwind readnone uwtable !prof !14 {
278 entry:
279   br label %loop
281 loop:
282   call void @body()
283   %t0 = call i32 @get()
284   %t1 = icmp slt i32 %t0, 2
285   br i1 %t1, label %block_a, label %bb
288   %t2 = call i32 @get()
289   %t3 = icmp slt i32 %t2, 99
290   br i1 %t3, label %exit, label %loop
292 block_a:
293   call void @bar99()
294   br label %loop
296 exit:
297   call void @exit()
298   ret void
301 declare void @bar99() nounwind
302 declare void @bar100() nounwind
303 declare void @bar101() nounwind
304 declare void @bar102() nounwind
305 declare void @body() nounwind
306 declare void @exit() nounwind
307 declare void @loop_header() nounwind
308 declare void @loop_latch() nounwind
309 declare i32 @get() nounwind
310 declare void @block_a_true_func() nounwind
311 declare void @block_a_false_func() nounwind
312 declare void @block_a_merge_func() nounwind
314 !llvm.module.flags = !{!0}
315 !0 = !{i32 1, !"ProfileSummary", !1}
316 !1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
317 !2 = !{!"ProfileFormat", !"InstrProf"}
318 !3 = !{!"TotalCount", i64 10000}
319 !4 = !{!"MaxCount", i64 10}
320 !5 = !{!"MaxInternalCount", i64 1}
321 !6 = !{!"MaxFunctionCount", i64 1000}
322 !7 = !{!"NumCounts", i64 3}
323 !8 = !{!"NumFunctions", i64 3}
324 !9 = !{!"DetailedSummary", !10}
325 !10 = !{!11, !12, !13}
326 !11 = !{i32 10000, i64 100, i32 1}
327 !12 = !{i32 999000, i64 100, i32 1}
328 !13 = !{i32 999999, i64 1, i32 2}
329 !14 = !{!"function_entry_count", i64 0}