• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; 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   .LBB0_1
11; CHECK-NEXT:   align
12; CHECK-NEXT: .LBB0_2:
13; CHECK-NEXT:   callq loop_latch
14; CHECK-NEXT: .LBB0_1:
15; CHECK-NEXT:   callq 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 .LBB1_1
41; CHECK-NEXT:   align
42; CHECK-NEXT: .LBB1_4:
43; CHECK-NEXT:   callq bar99
44; CHECK-NEXT: .LBB1_1:
45; CHECK-NEXT:   callq 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; "callq block_a_merge_func" is tail duped.
74
75; CHECK: yet_more_involved:
76;      CHECK:   jmp .LBB2_1
77; CHECK-NEXT:   align
78; CHECK-NEXT: .LBB2_4:
79; CHECK-NEXT:   callq bar99
80; CHECK-NEXT:   callq get
81; CHECK-NEXT:   cmpl $2999, %eax
82; CHECK-NEXT:   jle .LBB2_5
83; CHECK-NEXT:   callq block_a_false_func
84; 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
88; CHECK-NEXT:   callq block_a_merge_func
89; CHECK-NEXT: .LBB2_1:
90; CHECK-NEXT:   callq body
91
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:
135;      CHECK:   jmp     .LBB3_1
136; CHECK-NEXT:   align
137; CHECK-NEXT: .LBB3_7:
138; CHECK-NEXT:   callq   bar100
139; CHECK-NEXT:   jmp     .LBB3_1
140; CHECK-NEXT: .LBB3_8:
141; CHECK-NEXT:   callq   bar101
142; CHECK-NEXT:   jmp     .LBB3_1
143; CHECK-NEXT: .LBB3_9:
144; CHECK-NEXT:   callq   bar102
145; CHECK-NEXT:   jmp     .LBB3_1
146; CHECK-NEXT: .LBB3_5:
147; CHECK-NEXT:   callq   loop_latch
148; CHECK-NEXT: .LBB3_1:
149; CHECK-NEXT:   callq   loop_header
150
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
209