blob: af50bd95f3bde4bf930c9242ffca240638a05c5b [file] [log] [blame]
Dan Gohman07adb852009-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:
10; CHECK: jmp .LBB1_1
11; CHECK-NEXT: align
12; CHECK-NEXT: .LBB1_2:
13; CHECK-NEXT: call loop_latch
14; CHECK-NEXT: .LBB1_1:
15; CHECK-NEXT: call loop_header
16
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:
40; CHECK: jmp .LBB2_1
41; CHECK-NEXT: align
42; CHECK-NEXT: .LBB2_4:
43; CHECK-NEXT: call bar99
44; CHECK-NEXT: .LBB2_1:
45; CHECK-NEXT: call body
46
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.
73
74; CHECK: yet_more_involved:
75; CHECK: jmp .LBB3_1
76; CHECK-NEXT: align
77; CHECK-NEXT: .LBB3_7:
78; CHECK-NEXT: call block_a_true_func
79; CHECK-NEXT: jmp .LBB3_4
80; CHECK-NEXT: .LBB3_2:
81; CHECK-NEXT: call bar99
82; CHECK-NEXT: call get
83; CHECK-NEXT: cmpl $2999, %eax
84; CHECK-NEXT: jle .LBB3_7
85; CHECK-NEXT: call block_a_false_func
86; CHECK-NEXT: .LBB3_4:
87; CHECK-NEXT: call block_a_merge_func
88; CHECK-NEXT: .LBB3_1:
89; CHECK-NEXT: call body
90
91define void @yet_more_involved() nounwind {
92entry:
93 br label %loop
94
95loop:
96 call void @body()
97 %t0 = call i32 @get()
98 %t1 = icmp slt i32 %t0, 2
99 br i1 %t1, label %block_a, label %bb
100
101bb:
102 %t2 = call i32 @get()
103 %t3 = icmp slt i32 %t2, 99
104 br i1 %t3, label %exit, label %loop
105
106block_a:
107 call void @bar99()
108 %z0 = call i32 @get()
109 %z1 = icmp slt i32 %z0, 3000
110 br i1 %z1, label %block_a_true, label %block_a_false
111
112block_a_true:
113 call void @block_a_true_func()
114 br label %block_a_merge
115
116block_a_false:
117 call void @block_a_false_func()
118 br label %block_a_merge
119
120block_a_merge:
121 call void @block_a_merge_func()
122 br label %loop
123
124exit:
125 call void @exit()
126 ret void
127}
128
129; CodeGen should move the CFG islands that are part of the loop but don't
130; conveniently fit anywhere so that they are at least contiguous with the
131; loop.
132
133; CHECK: cfg_islands:
134; CHECK: jmp .LBB4_1
135; CHECK-NEXT: align
136; CHECK-NEXT: .LBB4_7:
137; CHECK-NEXT: call bar100
138; CHECK-NEXT: jmp .LBB4_1
139; CHECK-NEXT: .LBB4_8:
140; CHECK-NEXT: call bar101
141; CHECK-NEXT: jmp .LBB4_1
142; CHECK-NEXT: .LBB4_9:
143; CHECK-NEXT: call bar102
144; CHECK-NEXT: jmp .LBB4_1
145; CHECK-NEXT: .LBB4_5:
146; CHECK-NEXT: call loop_latch
147; CHECK-NEXT: .LBB4_1:
148; CHECK-NEXT: call loop_header
149
150define void @cfg_islands() nounwind {
151entry:
152 br label %loop
153
154loop:
155 call void @loop_header()
156 %t0 = call i32 @get()
157 %t1 = icmp slt i32 %t0, 100
158 br i1 %t1, label %block100, label %bb
159
160bb:
161 %t2 = call i32 @get()
162 %t3 = icmp slt i32 %t2, 101
163 br i1 %t3, label %block101, label %bb1
164
165bb1:
166 %t4 = call i32 @get()
167 %t5 = icmp slt i32 %t4, 102
168 br i1 %t5, label %block102, label %bb2
169
170bb2:
171 %t6 = call i32 @get()
172 %t7 = icmp slt i32 %t6, 103
173 br i1 %t7, label %exit, label %bb3
174
175bb3:
176 call void @loop_latch()
177 br label %loop
178
179exit:
180 call void @exit()
181 ret void
182
183block100:
184 call void @bar100()
185 br label %loop
186
187block101:
188 call void @bar101()
189 br label %loop
190
191block102:
192 call void @bar102()
193 br label %loop
194}
195
196declare void @bar99() nounwind
197declare void @bar100() nounwind
198declare void @bar101() nounwind
199declare void @bar102() nounwind
200declare void @body() nounwind
201declare void @exit() nounwind
202declare void @loop_header() nounwind
203declare void @loop_latch() nounwind
204declare i32 @get() nounwind
205declare void @block_a_true_func() nounwind
206declare void @block_a_false_func() nounwind
207declare void @block_a_merge_func() nounwind