1; RUN: llc < %s -mtriple=x86_64-pc-linux -mattr=+bmi,+lzcnt | FileCheck %s
2
3; LZCNT and TZCNT will always produce the operand size when the input operand
4; is zero. This test is to verify that we efficiently select LZCNT/TZCNT
5; based on the fact that the 'icmp+select' sequence is always redundant
6; in every function defined below.
7
8
9define i16 @test1_ctlz(i16 %v) {
10  %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true)
11  %tobool = icmp eq i16 %v, 0
12  %cond = select i1 %tobool, i16 16, i16 %cnt
13  ret i16 %cond
14}
15; CHECK-LABEL: test1_ctlz
16; CHECK: lzcnt
17; CHECK-NEXT: ret
18
19
20define i32 @test2_ctlz(i32 %v) {
21  %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true)
22  %tobool = icmp eq i32 %v, 0
23  %cond = select i1 %tobool, i32 32, i32 %cnt
24  ret i32 %cond
25}
26; CHECK-LABEL: test2_ctlz
27; CHECK: lzcnt
28; CHECK-NEXT: ret
29
30
31define i64 @test3_ctlz(i64 %v) {
32  %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
33  %tobool = icmp eq i64 %v, 0
34  %cond = select i1 %tobool, i64 64, i64 %cnt
35  ret i64 %cond
36}
37; CHECK-LABEL: test3_ctlz
38; CHECK: lzcnt
39; CHECK-NEXT: ret
40
41
42define i16 @test4_ctlz(i16 %v) {
43  %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true)
44  %tobool = icmp eq i16 0, %v
45  %cond = select i1 %tobool, i16 16, i16 %cnt
46  ret i16 %cond
47}
48; CHECK-LABEL: test4_ctlz
49; CHECK: lzcnt
50; CHECK-NEXT: ret
51
52
53define i32 @test5_ctlz(i32 %v) {
54  %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true)
55  %tobool = icmp eq i32 0, %v
56  %cond = select i1 %tobool, i32 32, i32 %cnt
57  ret i32 %cond
58}
59; CHECK-LABEL: test5_ctlz
60; CHECK: lzcnt
61; CHECK-NEXT: ret
62
63
64define i64 @test6_ctlz(i64 %v) {
65  %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
66  %tobool = icmp eq i64 0, %v
67  %cond = select i1 %tobool, i64 64, i64 %cnt
68  ret i64 %cond
69}
70; CHECK-LABEL: test6_ctlz
71; CHECK: lzcnt
72; CHECK-NEXT: ret
73
74
75define i16 @test7_ctlz(i16 %v) {
76  %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true)
77  %tobool = icmp eq i16 0, %v
78  %cond = select i1 %tobool, i16 %cnt, i16 16
79  ret i16 %cond
80}
81; CHECK-LABEL: test7_ctlz
82; CHECK: lzcnt
83; CHECK-NEXT: ret
84
85
86define i32 @test8_ctlz(i32 %v) {
87  %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true)
88  %tobool = icmp eq i32 0, %v
89  %cond = select i1 %tobool, i32 %cnt, i32 32
90  ret i32 %cond
91}
92; CHECK-LABEL: test8_ctlz
93; CHECK: lzcnt
94; CHECK-NEXT: ret
95
96
97define i64 @test9_ctlz(i64 %v) {
98  %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
99  %tobool = icmp eq i64 0, %v
100  %cond = select i1 %tobool, i64 %cnt, i64 64
101  ret i64 %cond
102}
103; CHECK-LABEL: test9_ctlz
104; CHECK: lzcnt
105; CHECK-NEXT: ret
106
107
108define i16 @test10_ctlz(i16* %ptr) {
109  %v = load i16, i16* %ptr
110  %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true)
111  %tobool = icmp eq i16 %v, 0
112  %cond = select i1 %tobool, i16 16, i16 %cnt
113  ret i16 %cond
114}
115; CHECK-LABEL: test10_ctlz
116; CHECK-NOT: movw
117; CHECK: lzcnt
118; CHECK-NEXT: ret
119
120
121define i32 @test11_ctlz(i32* %ptr) {
122  %v = load i32, i32* %ptr
123  %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true)
124  %tobool = icmp eq i32 %v, 0
125  %cond = select i1 %tobool, i32 32, i32 %cnt
126  ret i32 %cond
127}
128; CHECK-LABEL: test11_ctlz
129; CHECK-NOT: movd
130; CHECK: lzcnt
131; CHECK-NEXT: ret
132
133
134define i64 @test12_ctlz(i64* %ptr) {
135  %v = load i64, i64* %ptr
136  %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
137  %tobool = icmp eq i64 %v, 0
138  %cond = select i1 %tobool, i64 64, i64 %cnt
139  ret i64 %cond
140}
141; CHECK-LABEL: test12_ctlz
142; CHECK-NOT: movq
143; CHECK: lzcnt
144; CHECK-NEXT: ret
145
146
147define i16 @test13_ctlz(i16* %ptr) {
148  %v = load i16, i16* %ptr
149  %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true)
150  %tobool = icmp eq i16 0, %v
151  %cond = select i1 %tobool, i16 16, i16 %cnt
152  ret i16 %cond
153}
154; CHECK-LABEL: test13_ctlz
155; CHECK-NOT: movw
156; CHECK: lzcnt
157; CHECK-NEXT: ret
158
159
160define i32 @test14_ctlz(i32* %ptr) {
161  %v = load i32, i32* %ptr
162  %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true)
163  %tobool = icmp eq i32 0, %v
164  %cond = select i1 %tobool, i32 32, i32 %cnt
165  ret i32 %cond
166}
167; CHECK-LABEL: test14_ctlz
168; CHECK-NOT: movd
169; CHECK: lzcnt
170; CHECK-NEXT: ret
171
172
173define i64 @test15_ctlz(i64* %ptr) {
174  %v = load i64, i64* %ptr
175  %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
176  %tobool = icmp eq i64 0, %v
177  %cond = select i1 %tobool, i64 64, i64 %cnt
178  ret i64 %cond
179}
180; CHECK-LABEL: test15_ctlz
181; CHECK-NOT: movq
182; CHECK: lzcnt
183; CHECK-NEXT: ret
184
185
186define i16 @test16_ctlz(i16* %ptr) {
187  %v = load i16, i16* %ptr
188  %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true)
189  %tobool = icmp eq i16 0, %v
190  %cond = select i1 %tobool, i16 %cnt, i16 16
191  ret i16 %cond
192}
193; CHECK-LABEL: test16_ctlz
194; CHECK-NOT: movw
195; CHECK: lzcnt
196; CHECK-NEXT: ret
197
198
199define i32 @test17_ctlz(i32* %ptr) {
200  %v = load i32, i32* %ptr
201  %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true)
202  %tobool = icmp eq i32 0, %v
203  %cond = select i1 %tobool, i32 %cnt, i32 32
204  ret i32 %cond
205}
206; CHECK-LABEL: test17_ctlz
207; CHECK-NOT: movd
208; CHECK: lzcnt
209; CHECK-NEXT: ret
210
211
212define i64 @test18_ctlz(i64* %ptr) {
213  %v = load i64, i64* %ptr
214  %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
215  %tobool = icmp eq i64 0, %v
216  %cond = select i1 %tobool, i64 %cnt, i64 64
217  ret i64 %cond
218}
219; CHECK-LABEL: test18_ctlz
220; CHECK-NOT: movq
221; CHECK: lzcnt
222; CHECK-NEXT: ret
223
224
225define i16 @test1_cttz(i16 %v) {
226  %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true)
227  %tobool = icmp eq i16 %v, 0
228  %cond = select i1 %tobool, i16 16, i16 %cnt
229  ret i16 %cond
230}
231; CHECK-LABEL: test1_cttz
232; CHECK: tzcnt
233; CHECK-NEXT: ret
234
235
236define i32 @test2_cttz(i32 %v) {
237  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
238  %tobool = icmp eq i32 %v, 0
239  %cond = select i1 %tobool, i32 32, i32 %cnt
240  ret i32 %cond
241}
242; CHECK-LABEL: test2_cttz
243; CHECK: tzcnt
244; CHECK-NEXT: ret
245
246
247define i64 @test3_cttz(i64 %v) {
248  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
249  %tobool = icmp eq i64 %v, 0
250  %cond = select i1 %tobool, i64 64, i64 %cnt
251  ret i64 %cond
252}
253; CHECK-LABEL: test3_cttz
254; CHECK: tzcnt
255; CHECK-NEXT: ret
256
257
258define i16 @test4_cttz(i16 %v) {
259  %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true)
260  %tobool = icmp eq i16 0, %v
261  %cond = select i1 %tobool, i16 16, i16 %cnt
262  ret i16 %cond
263}
264; CHECK-LABEL: test4_cttz
265; CHECK: tzcnt
266; CHECK-NEXT: ret
267
268
269define i32 @test5_cttz(i32 %v) {
270  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
271  %tobool = icmp eq i32 0, %v
272  %cond = select i1 %tobool, i32 32, i32 %cnt
273  ret i32 %cond
274}
275; CHECK-LABEL: test5_cttz
276; CHECK: tzcnt
277; CHECK-NEXT: ret
278
279
280define i64 @test6_cttz(i64 %v) {
281  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
282  %tobool = icmp eq i64 0, %v
283  %cond = select i1 %tobool, i64 64, i64 %cnt
284  ret i64 %cond
285}
286; CHECK-LABEL: test6_cttz
287; CHECK: tzcnt
288; CHECK-NEXT: ret
289
290
291define i16 @test7_cttz(i16 %v) {
292  %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true)
293  %tobool = icmp eq i16 0, %v
294  %cond = select i1 %tobool, i16 %cnt, i16 16
295  ret i16 %cond
296}
297; CHECK-LABEL: test7_cttz
298; CHECK: tzcnt
299; CHECK-NEXT: ret
300
301
302define i32 @test8_cttz(i32 %v) {
303  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
304  %tobool = icmp eq i32 0, %v
305  %cond = select i1 %tobool, i32 %cnt, i32 32
306  ret i32 %cond
307}
308; CHECK-LABEL: test8_cttz
309; CHECK: tzcnt
310; CHECK-NEXT: ret
311
312
313define i64 @test9_cttz(i64 %v) {
314  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
315  %tobool = icmp eq i64 0, %v
316  %cond = select i1 %tobool, i64 %cnt, i64 64
317  ret i64 %cond
318}
319; CHECK-LABEL: test9_cttz
320; CHECK: tzcnt
321; CHECK-NEXT: ret
322
323
324define i16 @test10_cttz(i16* %ptr) {
325  %v = load i16, i16* %ptr
326  %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true)
327  %tobool = icmp eq i16 %v, 0
328  %cond = select i1 %tobool, i16 16, i16 %cnt
329  ret i16 %cond
330}
331; CHECK-LABEL: test10_cttz
332; CHECK-NOT: movw
333; CHECK: tzcnt
334; CHECK-NEXT: ret
335
336
337define i32 @test11_cttz(i32* %ptr) {
338  %v = load i32, i32* %ptr
339  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
340  %tobool = icmp eq i32 %v, 0
341  %cond = select i1 %tobool, i32 32, i32 %cnt
342  ret i32 %cond
343}
344; CHECK-LABEL: test11_cttz
345; CHECK-NOT: movd
346; CHECK: tzcnt
347; CHECK-NEXT: ret
348
349
350define i64 @test12_cttz(i64* %ptr) {
351  %v = load i64, i64* %ptr
352  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
353  %tobool = icmp eq i64 %v, 0
354  %cond = select i1 %tobool, i64 64, i64 %cnt
355  ret i64 %cond
356}
357; CHECK-LABEL: test12_cttz
358; CHECK-NOT: movq
359; CHECK: tzcnt
360; CHECK-NEXT: ret
361
362
363define i16 @test13_cttz(i16* %ptr) {
364  %v = load i16, i16* %ptr
365  %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true)
366  %tobool = icmp eq i16 0, %v
367  %cond = select i1 %tobool, i16 16, i16 %cnt
368  ret i16 %cond
369}
370; CHECK-LABEL: test13_cttz
371; CHECK-NOT: movw
372; CHECK: tzcnt
373; CHECK-NEXT: ret
374
375
376define i32 @test14_cttz(i32* %ptr) {
377  %v = load i32, i32* %ptr
378  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
379  %tobool = icmp eq i32 0, %v
380  %cond = select i1 %tobool, i32 32, i32 %cnt
381  ret i32 %cond
382}
383; CHECK-LABEL: test14_cttz
384; CHECK-NOT: movd
385; CHECK: tzcnt
386; CHECK-NEXT: ret
387
388
389define i64 @test15_cttz(i64* %ptr) {
390  %v = load i64, i64* %ptr
391  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
392  %tobool = icmp eq i64 0, %v
393  %cond = select i1 %tobool, i64 64, i64 %cnt
394  ret i64 %cond
395}
396; CHECK-LABEL: test15_cttz
397; CHECK-NOT: movq
398; CHECK: tzcnt
399; CHECK-NEXT: ret
400
401
402define i16 @test16_cttz(i16* %ptr) {
403  %v = load i16, i16* %ptr
404  %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true)
405  %tobool = icmp eq i16 0, %v
406  %cond = select i1 %tobool, i16 %cnt, i16 16
407  ret i16 %cond
408}
409; CHECK-LABEL: test16_cttz
410; CHECK-NOT: movw
411; CHECK: tzcnt
412; CHECK-NEXT: ret
413
414
415define i32 @test17_cttz(i32* %ptr) {
416  %v = load i32, i32* %ptr
417  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
418  %tobool = icmp eq i32 0, %v
419  %cond = select i1 %tobool, i32 %cnt, i32 32
420  ret i32 %cond
421}
422; CHECK-LABEL: test17_cttz
423; CHECK-NOT: movd
424; CHECK: tzcnt
425; CHECK-NEXT: ret
426
427
428define i64 @test18_cttz(i64* %ptr) {
429  %v = load i64, i64* %ptr
430  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
431  %tobool = icmp eq i64 0, %v
432  %cond = select i1 %tobool, i64 %cnt, i64 64
433  ret i64 %cond
434}
435; CHECK-LABEL: test18_cttz
436; CHECK-NOT: movq
437; CHECK: tzcnt
438; CHECK-NEXT: ret
439
440define i16 @test1b_ctlz(i16 %v) {
441  %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true)
442  %tobool = icmp ne i16 %v, 0
443  %cond = select i1 %tobool, i16 16, i16 %cnt
444  ret i16 %cond
445}
446; CHECK-LABEL: test1b_ctlz
447; CHECK: lzcnt
448; CHECK-NEXT: ret
449
450
451define i32 @test2b_ctlz(i32 %v) {
452  %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true)
453  %tobool = icmp ne i32 %v, 0
454  %cond = select i1 %tobool, i32 32, i32 %cnt
455  ret i32 %cond
456}
457; CHECK-LABEL: test2b_ctlz
458; CHECK: lzcnt
459; CHECK-NEXT: ret
460
461
462define i64 @test3b_ctlz(i64 %v) {
463  %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
464  %tobool = icmp ne i64 %v, 0
465  %cond = select i1 %tobool, i64 64, i64 %cnt
466  ret i64 %cond
467}
468; CHECK-LABEL: test3b_ctlz
469; CHECK: lzcnt
470; CHECK-NEXT: ret
471
472
473define i16 @test4b_ctlz(i16 %v) {
474  %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true)
475  %tobool = icmp ne i16 %v, 0
476  %cond = select i1 %tobool, i16 %cnt, i16 16
477  ret i16 %cond
478}
479; CHECK-LABEL: test4b_ctlz
480; CHECK: lzcnt
481; CHECK-NEXT: ret
482
483
484define i32 @test5b_ctlz(i32 %v) {
485  %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true)
486  %tobool = icmp ne i32 %v, 0
487  %cond = select i1 %tobool, i32 %cnt, i32 32
488  ret i32 %cond
489}
490; CHECK-LABEL: test5b_ctlz
491; CHECK: lzcnt
492; CHECK-NEXT: ret
493
494
495define i64 @test6b_ctlz(i64 %v) {
496  %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true)
497  %tobool = icmp ne i64 %v, 0
498  %cond = select i1 %tobool, i64 %cnt, i64 64
499  ret i64 %cond
500}
501; CHECK-LABEL: test6b_ctlz
502; CHECK: lzcnt
503; CHECK-NEXT: ret
504
505
506define i16 @test1b_cttz(i16 %v) {
507  %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true)
508  %tobool = icmp ne i16 %v, 0
509  %cond = select i1 %tobool, i16 16, i16 %cnt
510  ret i16 %cond
511}
512; CHECK-LABEL: test1b_cttz
513; CHECK: tzcnt
514; CHECK-NEXT: ret
515
516
517define i32 @test2b_cttz(i32 %v) {
518  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
519  %tobool = icmp ne i32 %v, 0
520  %cond = select i1 %tobool, i32 32, i32 %cnt
521  ret i32 %cond
522}
523; CHECK-LABEL: test2b_cttz
524; CHECK: tzcnt
525; CHECK-NEXT: ret
526
527
528define i64 @test3b_cttz(i64 %v) {
529  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
530  %tobool = icmp ne i64 %v, 0
531  %cond = select i1 %tobool, i64 64, i64 %cnt
532  ret i64 %cond
533}
534; CHECK-LABEL: test3b_cttz
535; CHECK: tzcnt
536; CHECK-NEXT: ret
537
538
539define i16 @test4b_cttz(i16 %v) {
540  %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true)
541  %tobool = icmp ne i16 %v, 0
542  %cond = select i1 %tobool, i16 %cnt, i16 16
543  ret i16 %cond
544}
545; CHECK-LABEL: test4b_cttz
546; CHECK: tzcnt
547; CHECK-NEXT: ret
548
549
550define i32 @test5b_cttz(i32 %v) {
551  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
552  %tobool = icmp ne i32 %v, 0
553  %cond = select i1 %tobool, i32 %cnt, i32 32
554  ret i32 %cond
555}
556; CHECK-LABEL: test5b_cttz
557; CHECK: tzcnt
558; CHECK-NEXT: ret
559
560
561define i64 @test6b_cttz(i64 %v) {
562  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
563  %tobool = icmp ne i64 %v, 0
564  %cond = select i1 %tobool, i64 %cnt, i64 64
565  ret i64 %cond
566}
567; CHECK-LABEL: test6b_cttz
568; CHECK: tzcnt
569; CHECK-NEXT: ret
570
571
572declare i64 @llvm.cttz.i64(i64, i1)
573declare i32 @llvm.cttz.i32(i32, i1)
574declare i16 @llvm.cttz.i16(i16, i1)
575declare i64 @llvm.ctlz.i64(i64, i1)
576declare i32 @llvm.ctlz.i32(i32, i1)
577declare i16 @llvm.ctlz.i16(i16, i1)
578
579