Test for the the problem with xors being changed into ands
[oota-llvm.git] / test / CodeGen / X86 / loop-blocks.ll
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
17 define void @simple() nounwind {
18 entry:
19   br label %loop
20
21 loop:
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
27 bb:
28   call void @loop_latch()
29   br label %loop
30
31 done:
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:   align
45 ; CHECK-NEXT: .LBB1_1:
46 ; CHECK-NEXT:   callq body
47
48 define void @slightly_more_involved() nounwind {
49 entry:
50   br label %loop
51
52 loop:
53   call void @body()
54   %t0 = call i32 @get()
55   %t1 = icmp slt i32 %t0, 2
56   br i1 %t1, label %block_a, label %bb
57
58 bb:
59   %t2 = call i32 @get()
60   %t3 = icmp slt i32 %t2, 99
61   br i1 %t3, label %exit, label %loop
62
63 block_a:
64   call void @bar99()
65   br label %loop
66
67 exit:
68   call void @exit()
69   ret void
70 }
71
72 ; Same as slightly_more_involved, but block_a is now a CFG diamond with
73 ; fallthrough edges which should be preserved.
74 ; "callq block_a_merge_func" is tail duped.
75
76 ; CHECK: yet_more_involved:
77 ;      CHECK:   jmp .LBB2_1
78 ; CHECK-NEXT:   align
79 ; CHECK-NEXT: .LBB2_5:
80 ; CHECK-NEXT:   callq block_a_true_func
81 ; CHECK-NEXT:   callq block_a_merge_func
82 ; CHECK-NEXT:   align
83 ; CHECK-NEXT: .LBB2_1:
84 ; CHECK-NEXT:   callq body
85 ;
86 ; LBB2_4
87 ;      CHECK:   callq bar99
88 ; CHECK-NEXT:   callq get
89 ; CHECK-NEXT:   cmpl $2999, %eax
90 ; CHECK-NEXT:   jle .LBB2_5
91 ; CHECK-NEXT:   callq block_a_false_func
92 ; CHECK-NEXT:   callq block_a_merge_func
93 ; CHECK-NEXT:   jmp .LBB2_1
94
95 define void @yet_more_involved() nounwind {
96 entry:
97   br label %loop
98
99 loop:
100   call void @body()
101   %t0 = call i32 @get()
102   %t1 = icmp slt i32 %t0, 2
103   br i1 %t1, label %block_a, label %bb
104
105 bb:
106   %t2 = call i32 @get()
107   %t3 = icmp slt i32 %t2, 99
108   br i1 %t3, label %exit, label %loop
109
110 block_a:
111   call void @bar99()
112   %z0 = call i32 @get()
113   %z1 = icmp slt i32 %z0, 3000
114   br i1 %z1, label %block_a_true, label %block_a_false
115
116 block_a_true:
117   call void @block_a_true_func()
118   br label %block_a_merge
119
120 block_a_false:
121   call void @block_a_false_func()
122   br label %block_a_merge
123
124 block_a_merge:
125   call void @block_a_merge_func()
126   br label %loop
127
128 exit:
129   call void @exit()
130   ret void
131 }
132
133 ; CodeGen should move the CFG islands that are part of the loop but don't
134 ; conveniently fit anywhere so that they are at least contiguous with the
135 ; loop.
136
137 ; CHECK: cfg_islands:
138 ;      CHECK:   jmp     .LBB3_1
139 ; CHECK-NEXT:   align
140 ; CHECK-NEXT: .LBB3_7:
141 ; CHECK-NEXT:   callq   bar100
142 ; CHECK-NEXT:   align
143 ; CHECK-NEXT: .LBB3_1:
144 ; CHECK-NEXT:   callq   loop_header
145 ;      CHECK:   jl .LBB3_7
146 ;      CHECK:   jge .LBB3_3
147 ; CHECK-NEXT:   callq   bar101
148 ; CHECK-NEXT:   jmp     .LBB3_1
149 ; CHECK-NEXT: .LBB3_3:
150 ;      CHECK:   jge .LBB3_4
151 ; CHECK-NEXT:   callq   bar102
152 ; CHECK-NEXT:   jmp     .LBB3_1
153 ; CHECK-NEXT: .LBB3_4:
154 ;      CHECK:   jl .LBB3_6
155 ; CHECK-NEXT:   callq   loop_latch
156 ; CHECK-NEXT:   jmp     .LBB3_1
157 ; CHECK-NEXT: .LBB3_6:
158
159 define void @cfg_islands() nounwind {
160 entry:
161   br label %loop
162
163 loop:
164   call void @loop_header()
165   %t0 = call i32 @get()
166   %t1 = icmp slt i32 %t0, 100
167   br i1 %t1, label %block100, label %bb
168
169 bb:
170   %t2 = call i32 @get()
171   %t3 = icmp slt i32 %t2, 101
172   br i1 %t3, label %block101, label %bb1
173
174 bb1:
175   %t4 = call i32 @get()
176   %t5 = icmp slt i32 %t4, 102
177   br i1 %t5, label %block102, label %bb2
178
179 bb2:
180   %t6 = call i32 @get()
181   %t7 = icmp slt i32 %t6, 103
182   br i1 %t7, label %exit, label %bb3
183
184 bb3:
185   call void @loop_latch()
186   br label %loop
187
188 exit:
189   call void @exit()
190   ret void
191
192 block100:
193   call void @bar100()
194   br label %loop
195
196 block101:
197   call void @bar101()
198   br label %loop
199
200 block102:
201   call void @bar102()
202   br label %loop
203 }
204
205 declare void @bar99() nounwind
206 declare void @bar100() nounwind
207 declare void @bar101() nounwind
208 declare void @bar102() nounwind
209 declare void @body() nounwind
210 declare void @exit() nounwind
211 declare void @loop_header() nounwind
212 declare void @loop_latch() nounwind
213 declare i32 @get() nounwind
214 declare void @block_a_true_func() nounwind
215 declare void @block_a_false_func() nounwind
216 declare void @block_a_merge_func() nounwind