blob: faba630071277e953700f4ab03cda99170c7ef43 [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:
Dan Gohman9f23dee2010-04-17 16:29:15 +000010; CHECK: jmp .LBB0_1
Dan Gohman07adb852009-10-20 04:50:37 +000011; CHECK-NEXT: align
Dan Gohman9f23dee2010-04-17 16:29:15 +000012; CHECK-NEXT: .LBB0_2:
Sean Callanan108934c2009-12-18 00:01:26 +000013; CHECK-NEXT: callq loop_latch
Dan Gohman9f23dee2010-04-17 16:29:15 +000014; CHECK-NEXT: .LBB0_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:
Dan Gohman9f23dee2010-04-17 16:29:15 +000040; CHECK: jmp .LBB1_1
Dan Gohman07adb852009-10-20 04:50:37 +000041; CHECK-NEXT: align
Dan Gohman9f23dee2010-04-17 16:29:15 +000042; CHECK-NEXT: .LBB1_4:
Sean Callanan108934c2009-12-18 00:01:26 +000043; CHECK-NEXT: callq bar99
Dan Gohman9f23dee2010-04-17 16:29:15 +000044; CHECK-NEXT: .LBB1_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.
Evan Chengc3f507f2011-01-29 04:46:23 +000073; "callq block_a_merge_func" is tail duped.
Dan Gohman07adb852009-10-20 04:50:37 +000074
75; CHECK: yet_more_involved:
Dan Gohman9f23dee2010-04-17 16:29:15 +000076; CHECK: jmp .LBB2_1
Dan Gohman07adb852009-10-20 04:50:37 +000077; CHECK-NEXT: align
Dan Gohman9f23dee2010-04-17 16:29:15 +000078; CHECK-NEXT: .LBB2_4:
Sean Callanan108934c2009-12-18 00:01:26 +000079; CHECK-NEXT: callq bar99
80; CHECK-NEXT: callq get
Dan Gohman07adb852009-10-20 04:50:37 +000081; CHECK-NEXT: cmpl $2999, %eax
Evan Chengc3f507f2011-01-29 04:46:23 +000082; CHECK-NEXT: jle .LBB2_5
Evan Chengb0a42fd2011-01-29 02:43:04 +000083; CHECK-NEXT: callq block_a_false_func
Evan Chengc3f507f2011-01-29 04:46:23 +000084; CHECK-NEXT: callq block_a_merge_func
85; CHECK-NEXT: jmp .LBB2_1
86; CHECK-NEXT: .LBB2_5:
87; CHECK-NEXT: callq block_a_true_func
Sean Callanan108934c2009-12-18 00:01:26 +000088; CHECK-NEXT: callq block_a_merge_func
Dan Gohman9f23dee2010-04-17 16:29:15 +000089; CHECK-NEXT: .LBB2_1:
Sean Callanan108934c2009-12-18 00:01:26 +000090; CHECK-NEXT: callq body
Dan Gohman07adb852009-10-20 04:50:37 +000091
92define void @yet_more_involved() nounwind {
93entry:
94 br label %loop
95
96loop:
97 call void @body()
98 %t0 = call i32 @get()
99 %t1 = icmp slt i32 %t0, 2
100 br i1 %t1, label %block_a, label %bb
101
102bb:
103 %t2 = call i32 @get()
104 %t3 = icmp slt i32 %t2, 99
105 br i1 %t3, label %exit, label %loop
106
107block_a:
108 call void @bar99()
109 %z0 = call i32 @get()
110 %z1 = icmp slt i32 %z0, 3000
111 br i1 %z1, label %block_a_true, label %block_a_false
112
113block_a_true:
114 call void @block_a_true_func()
115 br label %block_a_merge
116
117block_a_false:
118 call void @block_a_false_func()
119 br label %block_a_merge
120
121block_a_merge:
122 call void @block_a_merge_func()
123 br label %loop
124
125exit:
126 call void @exit()
127 ret void
128}
129
130; CodeGen should move the CFG islands that are part of the loop but don't
131; conveniently fit anywhere so that they are at least contiguous with the
132; loop.
133
134; CHECK: cfg_islands:
Dan Gohman9f23dee2010-04-17 16:29:15 +0000135; CHECK: jmp .LBB3_1
Dan Gohman07adb852009-10-20 04:50:37 +0000136; CHECK-NEXT: align
Dan Gohman9f23dee2010-04-17 16:29:15 +0000137; CHECK-NEXT: .LBB3_7:
Sean Callanan108934c2009-12-18 00:01:26 +0000138; CHECK-NEXT: callq bar100
Dan Gohman9f23dee2010-04-17 16:29:15 +0000139; CHECK-NEXT: jmp .LBB3_1
140; CHECK-NEXT: .LBB3_8:
Sean Callanan108934c2009-12-18 00:01:26 +0000141; CHECK-NEXT: callq bar101
Dan Gohman9f23dee2010-04-17 16:29:15 +0000142; CHECK-NEXT: jmp .LBB3_1
143; CHECK-NEXT: .LBB3_9:
Sean Callanan108934c2009-12-18 00:01:26 +0000144; CHECK-NEXT: callq bar102
Dan Gohman9f23dee2010-04-17 16:29:15 +0000145; CHECK-NEXT: jmp .LBB3_1
146; CHECK-NEXT: .LBB3_5:
Sean Callanan108934c2009-12-18 00:01:26 +0000147; CHECK-NEXT: callq loop_latch
Dan Gohman9f23dee2010-04-17 16:29:15 +0000148; CHECK-NEXT: .LBB3_1:
Sean Callanan108934c2009-12-18 00:01:26 +0000149; CHECK-NEXT: callq loop_header
Dan Gohman07adb852009-10-20 04:50:37 +0000150
151define void @cfg_islands() nounwind {
152entry:
153 br label %loop
154
155loop:
156 call void @loop_header()
157 %t0 = call i32 @get()
158 %t1 = icmp slt i32 %t0, 100
159 br i1 %t1, label %block100, label %bb
160
161bb:
162 %t2 = call i32 @get()
163 %t3 = icmp slt i32 %t2, 101
164 br i1 %t3, label %block101, label %bb1
165
166bb1:
167 %t4 = call i32 @get()
168 %t5 = icmp slt i32 %t4, 102
169 br i1 %t5, label %block102, label %bb2
170
171bb2:
172 %t6 = call i32 @get()
173 %t7 = icmp slt i32 %t6, 103
174 br i1 %t7, label %exit, label %bb3
175
176bb3:
177 call void @loop_latch()
178 br label %loop
179
180exit:
181 call void @exit()
182 ret void
183
184block100:
185 call void @bar100()
186 br label %loop
187
188block101:
189 call void @bar101()
190 br label %loop
191
192block102:
193 call void @bar102()
194 br label %loop
195}
196
197declare void @bar99() nounwind
198declare void @bar100() nounwind
199declare void @bar101() nounwind
200declare void @bar102() nounwind
201declare void @body() nounwind
202declare void @exit() nounwind
203declare void @loop_header() nounwind
204declare void @loop_latch() nounwind
205declare i32 @get() nounwind
206declare void @block_a_true_func() nounwind
207declare void @block_a_false_func() nounwind
208declare void @block_a_merge_func() nounwind