blob: 4bd162b45294477b60691c583e948f9de03c5ed4 [file] [log] [blame]
Dan Gohmanc0964a52009-10-20 04:50:37 +00001; 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: simple:
Dan Gohman4fee6f32010-04-17 16:29:15 +000010; CHECK: jmp .LBB0_1
Dan Gohmanc0964a52009-10-20 04:50:37 +000011; CHECK-NEXT: align
Dan Gohman4fee6f32010-04-17 16:29:15 +000012; CHECK-NEXT: .LBB0_2:
Sean Callanan04d8cb72009-12-18 00:01:26 +000013; CHECK-NEXT: callq loop_latch
Dan Gohman4fee6f32010-04-17 16:29:15 +000014; CHECK-NEXT: .LBB0_1:
Sean Callanan04d8cb72009-12-18 00:01:26 +000015; CHECK-NEXT: callq loop_header
Dan Gohmanc0964a52009-10-20 04:50:37 +000016
17define void @simple() nounwind {
18entry:
19 br label %loop
20
21loop:
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
27bb:
28 call void @loop_latch()
29 br label %loop
30
31done:
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: slightly_more_involved:
Dan Gohman4fee6f32010-04-17 16:29:15 +000040; CHECK: jmp .LBB1_1
Dan Gohmanc0964a52009-10-20 04:50:37 +000041; CHECK-NEXT: align
Dan Gohman4fee6f32010-04-17 16:29:15 +000042; CHECK-NEXT: .LBB1_4:
Sean Callanan04d8cb72009-12-18 00:01:26 +000043; CHECK-NEXT: callq bar99
Dan Gohman4fee6f32010-04-17 16:29:15 +000044; CHECK-NEXT: .LBB1_1:
Sean Callanan04d8cb72009-12-18 00:01:26 +000045; CHECK-NEXT: callq body
Dan Gohmanc0964a52009-10-20 04:50:37 +000046
47define void @slightly_more_involved() nounwind {
48entry:
49 br label %loop
50
51loop:
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
57bb:
58 %t2 = call i32 @get()
59 %t3 = icmp slt i32 %t2, 99
60 br i1 %t3, label %exit, label %loop
61
62block_a:
63 call void @bar99()
64 br label %loop
65
66exit:
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.
Evan Chengd983eba2011-01-29 04:46:23 +000073; "callq block_a_merge_func" is tail duped.
Dan Gohmanc0964a52009-10-20 04:50:37 +000074
75; CHECK: yet_more_involved:
Dan Gohman4fee6f32010-04-17 16:29:15 +000076; CHECK: jmp .LBB2_1
Dan Gohmanc0964a52009-10-20 04:50:37 +000077; CHECK-NEXT: align
Chandler Carruth4190b502012-04-16 13:49:17 +000078; CHECK-NEXT: .LBB2_5:
79; CHECK-NEXT: callq block_a_true_func
80; CHECK-NEXT: callq block_a_merge_func
Chandler Carruth4190b502012-04-16 13:49:17 +000081; CHECK-NEXT: .LBB2_1:
82; CHECK-NEXT: callq body
83;
84; LBB2_4
85; CHECK: callq bar99
Sean Callanan04d8cb72009-12-18 00:01:26 +000086; CHECK-NEXT: callq get
Dan Gohmanc0964a52009-10-20 04:50:37 +000087; CHECK-NEXT: cmpl $2999, %eax
Evan Chengd983eba2011-01-29 04:46:23 +000088; CHECK-NEXT: jle .LBB2_5
Evan Cheng65b8ccf2011-01-29 02:43:04 +000089; CHECK-NEXT: callq block_a_false_func
Evan Chengd983eba2011-01-29 04:46:23 +000090; CHECK-NEXT: callq block_a_merge_func
91; CHECK-NEXT: jmp .LBB2_1
Dan Gohmanc0964a52009-10-20 04:50:37 +000092
93define void @yet_more_involved() nounwind {
94entry:
95 br label %loop
96
97loop:
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
103bb:
104 %t2 = call i32 @get()
105 %t3 = icmp slt i32 %t2, 99
106 br i1 %t3, label %exit, label %loop
107
108block_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
114block_a_true:
115 call void @block_a_true_func()
116 br label %block_a_merge
117
118block_a_false:
119 call void @block_a_false_func()
120 br label %block_a_merge
121
122block_a_merge:
123 call void @block_a_merge_func()
124 br label %loop
125
126exit:
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: cfg_islands:
Dan Gohman4fee6f32010-04-17 16:29:15 +0000136; CHECK: jmp .LBB3_1
Dan Gohmanc0964a52009-10-20 04:50:37 +0000137; CHECK-NEXT: align
Dan Gohman4fee6f32010-04-17 16:29:15 +0000138; CHECK-NEXT: .LBB3_7:
Sean Callanan04d8cb72009-12-18 00:01:26 +0000139; CHECK-NEXT: callq bar100
Dan Gohman4fee6f32010-04-17 16:29:15 +0000140; CHECK-NEXT: .LBB3_1:
Sean Callanan04d8cb72009-12-18 00:01:26 +0000141; CHECK-NEXT: callq loop_header
Chandler Carruth4190b502012-04-16 13:49:17 +0000142; CHECK: jl .LBB3_7
143; CHECK: jge .LBB3_3
144; CHECK-NEXT: callq bar101
145; CHECK-NEXT: jmp .LBB3_1
Chandler Carruth881d0a72012-08-07 09:45:24 +0000146; CHECK-NEXT: align
Chandler Carruth4190b502012-04-16 13:49:17 +0000147; 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:
Dan Gohmanc0964a52009-10-20 04:50:37 +0000156
157define void @cfg_islands() nounwind {
158entry:
159 br label %loop
160
161loop:
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
167bb:
168 %t2 = call i32 @get()
169 %t3 = icmp slt i32 %t2, 101
170 br i1 %t3, label %block101, label %bb1
171
172bb1:
173 %t4 = call i32 @get()
174 %t5 = icmp slt i32 %t4, 102
175 br i1 %t5, label %block102, label %bb2
176
177bb2:
178 %t6 = call i32 @get()
179 %t7 = icmp slt i32 %t6, 103
180 br i1 %t7, label %exit, label %bb3
181
182bb3:
183 call void @loop_latch()
184 br label %loop
185
186exit:
187 call void @exit()
188 ret void
189
190block100:
191 call void @bar100()
192 br label %loop
193
194block101:
195 call void @bar101()
196 br label %loop
197
198block102:
199 call void @bar102()
200 br label %loop
201}
202
203declare void @bar99() nounwind
204declare void @bar100() nounwind
205declare void @bar101() nounwind
206declare void @bar102() nounwind
207declare void @body() nounwind
208declare void @exit() nounwind
209declare void @loop_header() nounwind
210declare void @loop_latch() nounwind
211declare i32 @get() nounwind
212declare void @block_a_true_func() nounwind
213declare void @block_a_false_func() nounwind
214declare void @block_a_merge_func() nounwind