[X86][AVX2] Missing AVX2 memory folding instructions
[oota-llvm.git] / test / CodeGen / X86 / cttz-ctlz.ll
1 ; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown -mattr=+bmi < %s | FileCheck %s --check-prefix=ALL --check-prefix=BMI
2 ; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown -mattr=+lzcnt < %s | FileCheck %s --check-prefix=ALL --check-prefix=LZCNT
3 ; RUN: opt -S -codegenprepare -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 ; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i64 @llvm.ctlz.i64(i64 %A, i1 false)
9 ; LZCNT-NEXT: ret i64 [[CTLZ]]
10 ; BMI: icmp eq i64 %A, 0
11 ; BMI: call i64 @llvm.ctlz.i64(i64 %A, i1 true)
12 ; GENERIC: icmp eq i64 %A, 0
13 ; GENERIC: call i64 @llvm.ctlz.i64(i64 %A, i1 true)
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
28 define i32 @test2(i32 %A) {
29 ; ALL-LABEL: @test2(
30 ; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i32 @llvm.ctlz.i32(i32 %A, i1 false)
31 ; LZCNT-NEXT: ret i32 [[CTLZ]]
32 ; BMI: icmp eq i32 %A, 0
33 ; BMI: call i32 @llvm.ctlz.i32(i32 %A, i1 true)
34 ; GENERIC: icmp eq i32 %A, 0
35 ; GENERIC: call i32 @llvm.ctlz.i32(i32 %A, i1 true)
36 entry:
37   %tobool = icmp eq i32 %A, 0
38   br i1 %tobool, label %cond.end, label %cond.true
39
40 cond.true:                                        ; preds = %entry
41   %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
42   br label %cond.end
43
44 cond.end:                                         ; preds = %entry, %cond.true
45   %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
46   ret i32 %cond
47 }
48
49
50 define signext i16 @test3(i16 signext %A) {
51 ; ALL-LABEL: @test3(
52 ; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i16 @llvm.ctlz.i16(i16 %A, i1 false)
53 ; LZCNT-NEXT: ret i16 [[CTLZ]]
54 ; BMI: icmp eq i16 %A, 0
55 ; BMI: call i16 @llvm.ctlz.i16(i16 %A, i1 true)
56 ; GENERIC: icmp eq i16 %A, 0
57 ; GENERIC: call i16 @llvm.ctlz.i16(i16 %A, i1 true)
58 entry:
59   %tobool = icmp eq i16 %A, 0
60   br i1 %tobool, label %cond.end, label %cond.true
61
62 cond.true:                                        ; preds = %entry
63   %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
64   br label %cond.end
65
66 cond.end:                                         ; preds = %entry, %cond.true
67   %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
68   ret i16 %cond
69 }
70
71
72 define i64 @test1b(i64 %A) {
73 ; ALL-LABEL: @test1b(
74 ; LZCNT: icmp eq i64 %A, 0
75 ; LZCNT: call i64 @llvm.cttz.i64(i64 %A, i1 true)
76 ; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %A, i1 false)
77 ; BMI-NEXT: ret i64 [[CTTZ]]
78 ; GENERIC: icmp eq i64 %A, 0
79 ; GENERIC: call i64 @llvm.cttz.i64(i64 %A, i1 true)
80 entry:
81   %tobool = icmp eq i64 %A, 0
82   br i1 %tobool, label %cond.end, label %cond.true
83
84 cond.true:                                        ; preds = %entry
85   %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
86   br label %cond.end
87
88 cond.end:                                         ; preds = %entry, %cond.true
89   %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
90   ret i64 %cond
91 }
92
93
94 define i32 @test2b(i32 %A) {
95 ; ALL-LABEL: @test2b(
96 ; LZCNT: icmp eq i32 %A, 0
97 ; LZCNT: call i32 @llvm.cttz.i32(i32 %A, i1 true)
98 ; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %A, i1 false)
99 ; BMI-NEXT: ret i32 [[CTTZ]]
100 ; GENERIC: icmp eq i32 %A, 0
101 ; GENERIC: call i32 @llvm.cttz.i32(i32 %A, i1 true)
102 entry:
103   %tobool = icmp eq i32 %A, 0
104   br i1 %tobool, label %cond.end, label %cond.true
105
106 cond.true:                                        ; preds = %entry
107   %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
108   br label %cond.end
109
110 cond.end:                                         ; preds = %entry, %cond.true
111   %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
112   ret i32 %cond
113 }
114
115
116 define signext i16 @test3b(i16 signext %A) {
117 ; ALL-LABEL: @test3b(
118 ; LZCNT: icmp eq i16 %A, 0
119 ; LZCNT: call i16 @llvm.cttz.i16(i16 %A, i1 true)
120 ; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i16 @llvm.cttz.i16(i16 %A, i1 false)
121 ; BMI-NEXT: ret i16 [[CTTZ]]
122 ; GENERIC: icmp eq i16 %A, 0
123 ; GENERIC: call i16 @llvm.cttz.i16(i16 %A, i1 true)
124 entry:
125   %tobool = icmp eq i16 %A, 0
126   br i1 %tobool, label %cond.end, label %cond.true
127
128 cond.true:                                        ; preds = %entry
129   %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
130   br label %cond.end
131
132 cond.end:                                         ; preds = %entry, %cond.true
133   %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
134   ret i16 %cond
135 }
136
137
138 define i64 @test1c(i64 %A) {
139 ; ALL-LABEL: @test1c(
140 ; ALL: icmp eq i64 %A, 0
141 ; ALL: call i64 @llvm.ctlz.i64(i64 %A, i1 true)
142 entry:
143   %tobool = icmp eq i64 %A, 0
144   br i1 %tobool, label %cond.end, label %cond.true
145
146 cond.true:                                        ; preds = %entry
147   %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
148   br label %cond.end
149
150 cond.end:                                         ; preds = %entry, %cond.true
151   %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ]
152   ret i64 %cond
153 }
154
155 define i32 @test2c(i32 %A) {
156 ; ALL-LABEL: @test2c(
157 ; ALL: icmp eq i32 %A, 0
158 ; ALL: call i32 @llvm.ctlz.i32(i32 %A, i1 true)
159 entry:
160   %tobool = icmp eq i32 %A, 0
161   br i1 %tobool, label %cond.end, label %cond.true
162
163 cond.true:                                        ; preds = %entry
164   %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
165   br label %cond.end
166
167 cond.end:                                         ; preds = %entry, %cond.true
168   %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ]
169   ret i32 %cond
170 }
171
172
173 define signext i16 @test3c(i16 signext %A) {
174 ; ALL-LABEL: @test3c(
175 ; ALL: icmp eq i16 %A, 0
176 ; ALL: call i16 @llvm.ctlz.i16(i16 %A, i1 true)
177 entry:
178   %tobool = icmp eq i16 %A, 0
179   br i1 %tobool, label %cond.end, label %cond.true
180
181 cond.true:                                        ; preds = %entry
182   %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
183   br label %cond.end
184
185 cond.end:                                         ; preds = %entry, %cond.true
186   %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ]
187   ret i16 %cond
188 }
189
190
191 define i64 @test1d(i64 %A) {
192 ; ALL-LABEL: @test1d(
193 ; ALL: icmp eq i64 %A, 0
194 ; ALL: call i64 @llvm.cttz.i64(i64 %A, i1 true)
195 entry:
196   %tobool = icmp eq i64 %A, 0
197   br i1 %tobool, label %cond.end, label %cond.true
198
199 cond.true:                                        ; preds = %entry
200   %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
201   br label %cond.end
202
203 cond.end:                                         ; preds = %entry, %cond.true
204   %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ]
205   ret i64 %cond
206 }
207
208
209 define i32 @test2d(i32 %A) {
210 ; ALL-LABEL: @test2d(
211 ; ALL: icmp eq i32 %A, 0
212 ; ALL: call i32 @llvm.cttz.i32(i32 %A, i1 true)
213 entry:
214   %tobool = icmp eq i32 %A, 0
215   br i1 %tobool, label %cond.end, label %cond.true
216
217 cond.true:                                        ; preds = %entry
218   %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
219   br label %cond.end
220
221 cond.end:                                         ; preds = %entry, %cond.true
222   %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ]
223   ret i32 %cond
224 }
225
226
227 define signext i16 @test3d(i16 signext %A) {
228 ; ALL-LABEL: @test3d(
229 ; ALL: icmp eq i16 %A, 0
230 ; ALL: call i16 @llvm.cttz.i16(i16 %A, i1 true)
231 entry:
232   %tobool = icmp eq i16 %A, 0
233   br i1 %tobool, label %cond.end, label %cond.true
234
235 cond.true:                                        ; preds = %entry
236   %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
237   br label %cond.end
238
239 cond.end:                                         ; preds = %entry, %cond.true
240   %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ]
241   ret i16 %cond
242 }
243
244 ; The following tests verify that calls to cttz/ctlz are speculated even if
245 ; basic block %cond.true has an extra zero extend/truncate which is "free"
246 ; for the target.
247
248 define i64 @test1e(i32 %x) {
249 ; ALL-LABEL: @test1e(
250 ; LZCNT: icmp eq i32 %x, 0
251 ; LZCNT: call i32 @llvm.cttz.i32(i32 %x, i1 true)
252 ; BMI: call i32 @llvm.cttz.i32(i32 %x, i1 false)
253 ; GENERIC: icmp eq i32 %x, 0
254 ; GENERIC: call i32 @llvm.cttz.i32(i32 %x, i1 true)
255 entry:
256   %tobool = icmp eq i32 %x, 0
257   br i1 %tobool, label %cond.end, label %cond.true
258
259 cond.true:                                        ; preds = %entry
260   %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
261   %phitmp2 = zext i32 %0 to i64
262   br label %cond.end
263
264 cond.end:                                         ; preds = %entry, %cond.true
265   %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
266   ret i64 %cond
267 }
268
269 define i32 @test2e(i64 %x) {
270 ; ALL-LABEL: @test2e(
271 ; LZCNT: icmp eq i64 %x, 0
272 ; LZCNT: call i64 @llvm.cttz.i64(i64 %x, i1 true)
273 ; BMI: call i64 @llvm.cttz.i64(i64 %x, i1 false)
274 ; GENERIC: icmp eq i64 %x, 0
275 ; GENERIC: call i64 @llvm.cttz.i64(i64 %x, i1 true)
276 entry:
277   %tobool = icmp eq i64 %x, 0
278   br i1 %tobool, label %cond.end, label %cond.true
279
280 cond.true:                                        ; preds = %entry
281   %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
282   %cast = trunc i64 %0 to i32
283   br label %cond.end
284
285 cond.end:                                         ; preds = %entry, %cond.true
286   %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
287   ret i32 %cond
288 }
289
290 define i64 @test3e(i32 %x) {
291 ; ALL-LABEL: @test3e(
292 ; BMI: icmp eq i32 %x, 0
293 ; BMI: call i32 @llvm.ctlz.i32(i32 %x, i1 true)
294 ; LZCNT: call i32 @llvm.ctlz.i32(i32 %x, i1 false)
295 ; GENERIC: icmp eq i32 %x, 0
296 ; GENERIC: call i32 @llvm.ctlz.i32(i32 %x, i1 true)
297 entry:
298   %tobool = icmp eq i32 %x, 0
299   br i1 %tobool, label %cond.end, label %cond.true
300
301 cond.true:                                        ; preds = %entry
302   %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
303   %phitmp2 = zext i32 %0 to i64
304   br label %cond.end
305
306 cond.end:                                         ; preds = %entry, %cond.true
307   %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
308   ret i64 %cond
309 }
310
311 define i32 @test4e(i64 %x) {
312 ; ALL-LABEL: @test4e(
313 ; BMI: icmp eq i64 %x, 0
314 ; BMI: call i64 @llvm.ctlz.i64(i64 %x, i1 true)
315 ; LZCNT: call i64 @llvm.ctlz.i64(i64 %x, i1 false)
316 ; GENERIC: icmp eq i64 %x, 0
317 ; GENERIC: call i64 @llvm.ctlz.i64(i64 %x, i1 true)
318 entry:
319   %tobool = icmp eq i64 %x, 0
320   br i1 %tobool, label %cond.end, label %cond.true
321
322 cond.true:                                        ; preds = %entry
323   %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
324   %cast = trunc i64 %0 to i32
325   br label %cond.end
326
327 cond.end:                                         ; preds = %entry, %cond.true
328   %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
329   ret i32 %cond
330 }
331
332 define i16 @test5e(i64 %x) {
333 ; ALL-LABEL: @test5e(
334 ; BMI: icmp eq i64 %x, 0
335 ; BMI: call i64 @llvm.ctlz.i64(i64 %x, i1 true)
336 ; LZCNT: call i64 @llvm.ctlz.i64(i64 %x, i1 false)
337 ; GENERIC: icmp eq i64 %x, 0
338 ; GENERIC: call i64 @llvm.ctlz.i64(i64 %x, i1 true)
339 entry:
340   %tobool = icmp eq i64 %x, 0
341   br i1 %tobool, label %cond.end, label %cond.true
342
343 cond.true:                                        ; preds = %entry
344   %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
345   %cast = trunc i64 %0 to i16
346   br label %cond.end
347
348 cond.end:                                         ; preds = %entry, %cond.true
349   %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
350   ret i16 %cond
351 }
352
353 define i16 @test6e(i32 %x) {
354 ; ALL-LABEL: @test6e(
355 ; BMI: icmp eq i32 %x, 0
356 ; BMI: call i32 @llvm.ctlz.i32(i32 %x, i1 true)
357 ; LZCNT: call i32 @llvm.ctlz.i32(i32 %x, i1 false)
358 ; GENERIC: icmp eq i32 %x, 0
359 ; GENERIC: call i32 @llvm.ctlz.i32(i32 %x, i1 true)
360 entry:
361   %tobool = icmp eq i32 %x, 0
362   br i1 %tobool, label %cond.end, label %cond.true
363
364 cond.true:                                        ; preds = %entry
365   %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
366   %cast = trunc i32 %0 to i16
367   br label %cond.end
368
369 cond.end:                                         ; preds = %entry, %cond.true
370   %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
371   ret i16 %cond
372 }
373
374 define i16 @test7e(i64 %x) {
375 ; ALL-LABEL: @test7e(
376 ; LZCNT: icmp eq i64 %x, 0
377 ; LZCNT: call i64 @llvm.cttz.i64(i64 %x, i1 true)
378 ; BMI: call i64 @llvm.cttz.i64(i64 %x, i1 false)
379 ; GENERIC: icmp eq i64 %x, 0
380 ; GENERIC: call i64 @llvm.cttz.i64(i64 %x, i1 true)
381 entry:
382   %tobool = icmp eq i64 %x, 0
383   br i1 %tobool, label %cond.end, label %cond.true
384
385 cond.true:                                        ; preds = %entry
386   %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
387   %cast = trunc i64 %0 to i16
388   br label %cond.end
389
390 cond.end:                                         ; preds = %entry, %cond.true
391   %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
392   ret i16 %cond
393 }
394
395 define i16 @test8e(i32 %x) {
396 ; ALL-LABEL: @test8e(
397 ; LZCNT: icmp eq i32 %x, 0
398 ; LZCNT: call i32 @llvm.cttz.i32(i32 %x, i1 true)
399 ; BMI: call i32 @llvm.cttz.i32(i32 %x, i1 false)
400 ; GENERIC: icmp eq i32 %x, 0
401 ; GENERIC: call i32 @llvm.cttz.i32(i32 %x, i1 true)
402 entry:
403   %tobool = icmp eq i32 %x, 0
404   br i1 %tobool, label %cond.end, label %cond.true
405
406 cond.true:                                        ; preds = %entry
407   %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
408   %cast = trunc i32 %0 to i16
409   br label %cond.end
410
411 cond.end:                                         ; preds = %entry, %cond.true
412   %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
413   ret i16 %cond
414 }
415
416
417 declare i64 @llvm.ctlz.i64(i64, i1)
418 declare i32 @llvm.ctlz.i32(i32, i1)
419 declare i16 @llvm.ctlz.i16(i16, i1)
420 declare i64 @llvm.cttz.i64(i64, i1)
421 declare i32 @llvm.cttz.i32(i32, i1)
422 declare i16 @llvm.cttz.i16(i16, i1)