blob: a125e54050bb7ab562b36535f68139fce502e36d [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:
Sean Callanan108934c2009-12-18 00:01:26 +000013; CHECK-NEXT: callq loop_latch
Dan Gohman07adb852009-10-20 04:50:37 +000014; CHECK-NEXT: .LBB1_1:
Sean Callanan108934c2009-12-18 00:01:26 +000015; CHECK-NEXT: callq loop_header
Dan Gohman07adb852009-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:
40; CHECK: jmp .LBB2_1
41; CHECK-NEXT: align
42; CHECK-NEXT: .LBB2_4:
Sean Callanan108934c2009-12-18 00:01:26 +000043; CHECK-NEXT: callq bar99
Dan Gohman07adb852009-10-20 04:50:37 +000044; CHECK-NEXT: .LBB2_1:
Sean Callanan108934c2009-12-18 00:01:26 +000045; CHECK-NEXT: callq body
Dan Gohman07adb852009-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.
73
74; CHECK: yet_more_involved:
75; CHECK: jmp .LBB3_1
76; CHECK-NEXT: align
Dan Gohman2210c0b2009-11-11 19:48:59 +000077; CHECK-NEXT: .LBB3_4:
Sean Callanan108934c2009-12-18 00:01:26 +000078; CHECK-NEXT: callq bar99
79; CHECK-NEXT: callq get
Dan Gohman07adb852009-10-20 04:50:37 +000080; CHECK-NEXT: cmpl $2999, %eax
Dan Gohman2210c0b2009-11-11 19:48:59 +000081; CHECK-NEXT: jg .LBB3_6
Sean Callanan108934c2009-12-18 00:01:26 +000082; CHECK-NEXT: callq block_a_true_func
Dan Gohman2210c0b2009-11-11 19:48:59 +000083; CHECK-NEXT: jmp .LBB3_7
Dan Gohman6d312682009-10-22 00:03:58 +000084; CHECK-NEXT: .LBB3_6:
Sean Callanan108934c2009-12-18 00:01:26 +000085; CHECK-NEXT: callq block_a_false_func
Dan Gohman2210c0b2009-11-11 19:48:59 +000086; CHECK-NEXT: .LBB3_7:
Sean Callanan108934c2009-12-18 00:01:26 +000087; CHECK-NEXT: callq block_a_merge_func
Dan Gohman07adb852009-10-20 04:50:37 +000088; CHECK-NEXT: .LBB3_1:
Sean Callanan108934c2009-12-18 00:01:26 +000089; CHECK-NEXT: callq body
Dan Gohman07adb852009-10-20 04:50:37 +000090
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:
Sean Callanan108934c2009-12-18 00:01:26 +0000137; CHECK-NEXT: callq bar100
Dan Gohman07adb852009-10-20 04:50:37 +0000138; CHECK-NEXT: jmp .LBB4_1
139; CHECK-NEXT: .LBB4_8:
Sean Callanan108934c2009-12-18 00:01:26 +0000140; CHECK-NEXT: callq bar101
Dan Gohman07adb852009-10-20 04:50:37 +0000141; CHECK-NEXT: jmp .LBB4_1
142; CHECK-NEXT: .LBB4_9:
Sean Callanan108934c2009-12-18 00:01:26 +0000143; CHECK-NEXT: callq bar102
Dan Gohman07adb852009-10-20 04:50:37 +0000144; CHECK-NEXT: jmp .LBB4_1
145; CHECK-NEXT: .LBB4_5:
Sean Callanan108934c2009-12-18 00:01:26 +0000146; CHECK-NEXT: callq loop_latch
Dan Gohman07adb852009-10-20 04:50:37 +0000147; CHECK-NEXT: .LBB4_1:
Sean Callanan108934c2009-12-18 00:01:26 +0000148; CHECK-NEXT: callq loop_header
Dan Gohman07adb852009-10-20 04:50:37 +0000149
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