OSDN Git Service

69f6c69059d482d9296d3c49346bbef0cf1d55df
[android-x86/external-llvm.git] / test / Transforms / SimplifyCFG / X86 / speculate-cttz-ctlz.ll
1 ; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+bmi < %s | FileCheck %s --check-prefix=ALL --check-prefix=BMI
2 ; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+lzcnt < %s | FileCheck %s --check-prefix=ALL --check-prefix=LZCNT
3 ; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown < %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC
4
5
6 define i64 @test1(i64 %A) {
7 ; ALL-LABEL: @test1(
8 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
9 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
10 ; LZCNT-NEXT: select i1 [[COND]], i64 64, i64 [[CTLZ]]
11 ; BMI-NOT: select
12 ; GENERIC-NOT: select
13 ; ALL: ret
14 entry:
15   %tobool = icmp eq i64 %A, 0
16   br i1 %tobool, label %cond.end, label %cond.true
17
18 cond.true:                                        ; preds = %entry
19   %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
20   br label %cond.end
21
22 cond.end:                                         ; preds = %entry, %cond.true
23   %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
24   ret i64 %cond
25 }
26
27 define i32 @test2(i32 %A) {
28 ; ALL-LABEL: @test2(
29 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
30 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
31 ; LZCNT-NEXT: select i1 [[COND]], i32 32, i32 [[CTLZ]]
32 ; BMI-NOT: select
33 ; GENERIC-NOT: select
34 ; ALL: ret
35 entry:
36   %tobool = icmp eq i32 %A, 0
37   br i1 %tobool, label %cond.end, label %cond.true
38
39 cond.true:                                        ; preds = %entry
40   %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
41   br label %cond.end
42
43 cond.end:                                         ; preds = %entry, %cond.true
44   %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
45   ret i32 %cond
46 }
47
48
49 define signext i16 @test3(i16 signext %A) {
50 ; ALL-LABEL: @test3(
51 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
52 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
53 ; LZCNT-NEXT: select i1 [[COND]], i16 16, i16 [[CTLZ]]
54 ; BMI-NOT: select
55 ; GENERIC-NOT: select
56 ; ALL: ret
57 entry:
58   %tobool = icmp eq i16 %A, 0
59   br i1 %tobool, label %cond.end, label %cond.true
60
61 cond.true:                                        ; preds = %entry
62   %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
63   br label %cond.end
64
65 cond.end:                                         ; preds = %entry, %cond.true
66   %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
67   ret i16 %cond
68 }
69
70
71 define i64 @test1b(i64 %A) {
72 ; ALL-LABEL: @test1b(
73 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
74 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
75 ; BMI-NEXT: select i1 [[COND]], i64 64, i64 [[CTTZ]]
76 ; LZCNT-NOT: select
77 ; GENERIC-NOT: select
78 ; ALL: ret
79 entry:
80   %tobool = icmp eq i64 %A, 0
81   br i1 %tobool, label %cond.end, label %cond.true
82
83 cond.true:                                        ; preds = %entry
84   %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
85   br label %cond.end
86
87 cond.end:                                         ; preds = %entry, %cond.true
88   %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
89   ret i64 %cond
90 }
91
92
93 define i32 @test2b(i32 %A) {
94 ; ALL-LABEL: @test2b(
95 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
96 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
97 ; BMI-NEXT: select i1 [[COND]], i32 32, i32 [[CTTZ]]
98 ; LZCNT-NOT: select
99 ; GENERIC-NOT: select
100 ; ALL: ret
101 entry:
102   %tobool = icmp eq i32 %A, 0
103   br i1 %tobool, label %cond.end, label %cond.true
104
105 cond.true:                                        ; preds = %entry
106   %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
107   br label %cond.end
108
109 cond.end:                                         ; preds = %entry, %cond.true
110   %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
111   ret i32 %cond
112 }
113
114
115 define signext i16 @test3b(i16 signext %A) {
116 ; ALL-LABEL: @test3b(
117 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
118 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
119 ; BMI-NEXT: select i1 [[COND]], i16 16, i16 [[CTTZ]]
120 ; LZCNT-NOT: select
121 ; GENERIC-NOT: select
122 ; ALL: ret
123 entry:
124   %tobool = icmp eq i16 %A, 0
125   br i1 %tobool, label %cond.end, label %cond.true
126
127 cond.true:                                        ; preds = %entry
128   %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
129   br label %cond.end
130
131 cond.end:                                         ; preds = %entry, %cond.true
132   %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
133   ret i16 %cond
134 }
135
136 ; The following tests verify that calls to cttz/ctlz are speculated even if
137 ; basic block %cond.true has an extra zero extend/truncate which is "free"
138 ; for the target.
139
140 define i64 @test1e(i32 %x) {
141 ; ALL-LABEL: @test1e(
142 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
143 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
144 ; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTTZ]] to i64
145 ; BMI-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]]
146 ; LZCNT-NOT: select
147 ; GENERIC-NOT: select
148 ; ALL: ret
149 entry:
150   %tobool = icmp eq i32 %x, 0
151   br i1 %tobool, label %cond.end, label %cond.true
152
153 cond.true:                                        ; preds = %entry
154   %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
155   %phitmp2 = zext i32 %0 to i64
156   br label %cond.end
157
158 cond.end:                                         ; preds = %entry, %cond.true
159   %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
160   ret i64 %cond
161 }
162
163 define i32 @test2e(i64 %x) {
164 ; ALL-LABEL: @test2e(
165 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
166 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
167 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i32
168 ; BMI-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]]
169 ; LZCNT-NOT: select
170 ; GENERIC-NOT: select
171 ; ALL: ret
172 entry:
173   %tobool = icmp eq i64 %x, 0
174   br i1 %tobool, label %cond.end, label %cond.true
175
176 cond.true:                                        ; preds = %entry
177   %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
178   %cast = trunc i64 %0 to i32
179   br label %cond.end
180
181 cond.end:                                         ; preds = %entry, %cond.true
182   %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
183   ret i32 %cond
184 }
185
186 define i64 @test3e(i32 %x) {
187 ; ALL-LABEL: @test3e(
188 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
189 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
190 ; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTLZ]] to i64
191 ; LZCNT-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]]
192 ; BMI-NOT: select
193 ; GENERIC-NOT: select
194 ; ALL: ret
195 entry:
196   %tobool = icmp eq i32 %x, 0
197   br i1 %tobool, label %cond.end, label %cond.true
198
199 cond.true:                                        ; preds = %entry
200   %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
201   %phitmp2 = zext i32 %0 to i64
202   br label %cond.end
203
204 cond.end:                                         ; preds = %entry, %cond.true
205   %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
206   ret i64 %cond
207 }
208
209 define i32 @test4e(i64 %x) {
210 ; ALL-LABEL: @test4e(
211 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
212 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
213 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i32
214 ; LZCNT-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]]
215 ; BMI-NOT: select
216 ; GENERIC-NOT: select
217 ; ALL: ret
218 entry:
219   %tobool = icmp eq i64 %x, 0
220   br i1 %tobool, label %cond.end, label %cond.true
221
222 cond.true:                                        ; preds = %entry
223   %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
224   %cast = trunc i64 %0 to i32
225   br label %cond.end
226
227 cond.end:                                         ; preds = %entry, %cond.true
228   %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
229   ret i32 %cond
230 }
231
232 define i16 @test5e(i64 %x) {
233 ; ALL-LABEL: @test5e(
234 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
235 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
236 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i16
237 ; LZCNT-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]]
238 ; BMI-NOT: select
239 ; GENERIC-NOT: select
240 ; ALL: ret
241 entry:
242   %tobool = icmp eq i64 %x, 0
243   br i1 %tobool, label %cond.end, label %cond.true
244
245 cond.true:                                        ; preds = %entry
246   %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
247   %cast = trunc i64 %0 to i16
248   br label %cond.end
249
250 cond.end:                                         ; preds = %entry, %cond.true
251   %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
252   ret i16 %cond
253 }
254
255 define i16 @test6e(i32 %x) {
256 ; ALL-LABEL: @test6e(
257 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
258 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
259 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTLZ]] to i16
260 ; LZCNT-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]]
261 ; BMI-NOT: select
262 ; GENERIC-NOT: select
263 ; ALL: ret
264 entry:
265   %tobool = icmp eq i32 %x, 0
266   br i1 %tobool, label %cond.end, label %cond.true
267
268 cond.true:                                        ; preds = %entry
269   %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
270   %cast = trunc i32 %0 to i16
271   br label %cond.end
272
273 cond.end:                                         ; preds = %entry, %cond.true
274   %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
275   ret i16 %cond
276 }
277
278 define i16 @test7e(i64 %x) {
279 ; ALL-LABEL: @test7e(
280 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
281 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
282 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i16
283 ; BMI-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]]
284 ; LZCNT-NOT: select
285 ; GENERIC-NOT: select
286 ; ALL: ret
287 entry:
288   %tobool = icmp eq i64 %x, 0
289   br i1 %tobool, label %cond.end, label %cond.true
290
291 cond.true:                                        ; preds = %entry
292   %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
293   %cast = trunc i64 %0 to i16
294   br label %cond.end
295
296 cond.end:                                         ; preds = %entry, %cond.true
297   %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
298   ret i16 %cond
299 }
300
301 define i16 @test8e(i32 %x) {
302 ; ALL-LABEL: @test8e(
303 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
304 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
305 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTTZ]] to i16
306 ; BMI-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]]
307 ; LZCNT-NOT: select
308 ; GENERIC-NOT: select
309 ; ALL: ret
310 entry:
311   %tobool = icmp eq i32 %x, 0
312   br i1 %tobool, label %cond.end, label %cond.true
313
314 cond.true:                                        ; preds = %entry
315   %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
316   %cast = trunc i32 %0 to i16
317   br label %cond.end
318
319 cond.end:                                         ; preds = %entry, %cond.true
320   %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
321   ret i16 %cond
322 }
323
324
325 declare i64 @llvm.ctlz.i64(i64, i1)
326 declare i32 @llvm.ctlz.i32(i32, i1)
327 declare i16 @llvm.ctlz.i16(i16, i1)
328 declare i64 @llvm.cttz.i64(i64, i1)
329 declare i32 @llvm.cttz.i32(i32, i1)
330 declare i16 @llvm.cttz.i16(i16, i1)