xref: /llvm-project/llvm/test/Transforms/InstCombine/select-cmp-cttz-ctlz.ll (revision a37dbc1f51c70d92fd209c2e52a9d794eb15e4e7)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3
4; This test is to verify that the instruction combiner is able to fold
5; a cttz/ctlz followed by a icmp + select into a single cttz/ctlz with
6; the 'is_zero_undef' flag cleared.
7
8define i16 @test1(i16 %x) {
9; CHECK-LABEL: @test1(
10; CHECK-NEXT:    [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 [[X:%.*]], i1 false)
11; CHECK-NEXT:    ret i16 [[CT]]
12;
13  %ct = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
14  %tobool = icmp ne i16 %x, 0
15  %cond = select i1 %tobool, i16 %ct, i16 16
16  ret i16 %cond
17}
18
19define i32 @test2(i32 %x) {
20; CHECK-LABEL: @test2(
21; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false)
22; CHECK-NEXT:    ret i32 [[CT]]
23;
24  %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
25  %tobool = icmp ne i32 %x, 0
26  %cond = select i1 %tobool, i32 %ct, i32 32
27  ret i32 %cond
28}
29
30define i64 @test3(i64 %x) {
31; CHECK-LABEL: @test3(
32; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X:%.*]], i1 false)
33; CHECK-NEXT:    ret i64 [[CT]]
34;
35  %ct = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
36  %tobool = icmp ne i64 %x, 0
37  %cond = select i1 %tobool, i64 %ct, i64 64
38  ret i64 %cond
39}
40
41define i16 @test4(i16 %x) {
42; CHECK-LABEL: @test4(
43; CHECK-NEXT:    [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 [[X:%.*]], i1 false)
44; CHECK-NEXT:    ret i16 [[CT]]
45;
46  %ct = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
47  %tobool = icmp eq i16 %x, 0
48  %cond = select i1 %tobool, i16 16, i16 %ct
49  ret i16 %cond
50}
51
52define i16 @test4_with_range(i16 %x) {
53; CHECK-LABEL: @test4_with_range(
54; CHECK-NEXT:    [[CT:%.*]] = call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 [[X:%.*]], i1 false)
55; CHECK-NEXT:    ret i16 [[CT]]
56;
57  %ct = call range(i16 0, 16) i16 @llvm.ctlz.i16(i16 %x, i1 true)
58  %tobool = icmp eq i16 %x, 0
59  %cond = select i1 %tobool, i16 16, i16 %ct
60  ret i16 %cond
61}
62
63define i32 @test5(i32 %x) {
64; CHECK-LABEL: @test5(
65; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false)
66; CHECK-NEXT:    ret i32 [[CT]]
67;
68  %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
69  %tobool = icmp eq i32 %x, 0
70  %cond = select i1 %tobool, i32 32, i32 %ct
71  ret i32 %cond
72}
73
74define i64 @test6(i64 %x) {
75; CHECK-LABEL: @test6(
76; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X:%.*]], i1 false)
77; CHECK-NEXT:    ret i64 [[CT]]
78;
79  %ct = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
80  %tobool = icmp eq i64 %x, 0
81  %cond = select i1 %tobool, i64 64, i64 %ct
82  ret i64 %cond
83}
84
85define i16 @test1b(i16 %x) {
86; CHECK-LABEL: @test1b(
87; CHECK-NEXT:    [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 false)
88; CHECK-NEXT:    ret i16 [[CT]]
89;
90  %ct = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
91  %tobool = icmp ne i16 %x, 0
92  %cond = select i1 %tobool, i16 %ct, i16 16
93  ret i16 %cond
94}
95
96define i32 @test2b(i32 %x) {
97; CHECK-LABEL: @test2b(
98; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false)
99; CHECK-NEXT:    ret i32 [[CT]]
100;
101  %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
102  %tobool = icmp ne i32 %x, 0
103  %cond = select i1 %tobool, i32 %ct, i32 32
104  ret i32 %cond
105}
106
107define i64 @test3b(i64 %x) {
108; CHECK-LABEL: @test3b(
109; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false)
110; CHECK-NEXT:    ret i64 [[CT]]
111;
112  %ct = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
113  %tobool = icmp ne i64 %x, 0
114  %cond = select i1 %tobool, i64 %ct, i64 64
115  ret i64 %cond
116}
117
118define i16 @test4b(i16 %x) {
119; CHECK-LABEL: @test4b(
120; CHECK-NEXT:    [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 false)
121; CHECK-NEXT:    ret i16 [[CT]]
122;
123  %ct = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
124  %tobool = icmp eq i16 %x, 0
125  %cond = select i1 %tobool, i16 16, i16 %ct
126  ret i16 %cond
127}
128
129define i16 @test4b_with_range(i16 %x) {
130; CHECK-LABEL: @test4b_with_range(
131; CHECK-NEXT:    [[CT:%.*]] = call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 false)
132; CHECK-NEXT:    ret i16 [[CT]]
133;
134  %ct = call range(i16 0, 16) i16 @llvm.cttz.i16(i16 %x, i1 true)
135  %tobool = icmp eq i16 %x, 0
136  %cond = select i1 %tobool, i16 16, i16 %ct
137  ret i16 %cond
138}
139
140define i32 @test5b(i32 %x) {
141; CHECK-LABEL: @test5b(
142; CHECK-NEXT:  entry:
143; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false)
144; CHECK-NEXT:    ret i32 [[CT]]
145;
146entry:
147  %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
148  %tobool = icmp eq i32 %x, 0
149  %cond = select i1 %tobool, i32 32, i32 %ct
150  ret i32 %cond
151}
152
153define i64 @test6b(i64 %x) {
154; CHECK-LABEL: @test6b(
155; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false)
156; CHECK-NEXT:    ret i64 [[CT]]
157;
158  %ct = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
159  %tobool = icmp eq i64 %x, 0
160  %cond = select i1 %tobool, i64 64, i64 %ct
161  ret i64 %cond
162}
163
164define i32 @test1c(i16 %x) {
165; CHECK-LABEL: @test1c(
166; CHECK-NEXT:    [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 false)
167; CHECK-NEXT:    [[CAST2:%.*]] = zext nneg i16 [[CT]] to i32
168; CHECK-NEXT:    ret i32 [[CAST2]]
169;
170  %ct = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
171  %cast2 = zext i16 %ct to i32
172  %tobool = icmp ne i16 %x, 0
173  %cond = select i1 %tobool, i32 %cast2, i32 16
174  ret i32 %cond
175}
176
177define i64 @test2c(i16 %x) {
178; CHECK-LABEL: @test2c(
179; CHECK-NEXT:    [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 false)
180; CHECK-NEXT:    [[CONV:%.*]] = zext nneg i16 [[CT]] to i64
181; CHECK-NEXT:    ret i64 [[CONV]]
182;
183  %ct = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
184  %conv = zext i16 %ct to i64
185  %tobool = icmp ne i16 %x, 0
186  %cond = select i1 %tobool, i64 %conv, i64 16
187  ret i64 %cond
188}
189
190define i64 @test3c(i32 %x) {
191; CHECK-LABEL: @test3c(
192; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false)
193; CHECK-NEXT:    [[CONV:%.*]] = zext nneg i32 [[CT]] to i64
194; CHECK-NEXT:    ret i64 [[CONV]]
195;
196  %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
197  %conv = zext i32 %ct to i64
198  %tobool = icmp ne i32 %x, 0
199  %cond = select i1 %tobool, i64 %conv, i64 32
200  ret i64 %cond
201}
202
203define i32 @test4c(i16 %x) {
204; CHECK-LABEL: @test4c(
205; CHECK-NEXT:    [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 [[X:%.*]], i1 false)
206; CHECK-NEXT:    [[CAST:%.*]] = zext nneg i16 [[CT]] to i32
207; CHECK-NEXT:    ret i32 [[CAST]]
208;
209  %ct = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
210  %cast = zext i16 %ct to i32
211  %tobool = icmp ne i16 %x, 0
212  %cond = select i1 %tobool, i32 %cast, i32 16
213  ret i32 %cond
214}
215
216define i64 @test5c(i16 %x) {
217; CHECK-LABEL: @test5c(
218; CHECK-NEXT:    [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 [[X:%.*]], i1 false)
219; CHECK-NEXT:    [[CAST:%.*]] = zext nneg i16 [[CT]] to i64
220; CHECK-NEXT:    ret i64 [[CAST]]
221;
222  %ct = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
223  %cast = zext i16 %ct to i64
224  %tobool = icmp ne i16 %x, 0
225  %cond = select i1 %tobool, i64 %cast, i64 16
226  ret i64 %cond
227}
228
229define i64 @test6c(i32 %x) {
230; CHECK-LABEL: @test6c(
231; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false)
232; CHECK-NEXT:    [[CAST:%.*]] = zext nneg i32 [[CT]] to i64
233; CHECK-NEXT:    ret i64 [[CAST]]
234;
235  %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
236  %cast = zext i32 %ct to i64
237  %tobool = icmp ne i32 %x, 0
238  %cond = select i1 %tobool, i64 %cast, i64 32
239  ret i64 %cond
240}
241
242define i16 @test1d(i64 %x) {
243; CHECK-LABEL: @test1d(
244; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false)
245; CHECK-NEXT:    [[CONV:%.*]] = trunc nuw nsw i64 [[CT]] to i16
246; CHECK-NEXT:    ret i16 [[CONV]]
247;
248  %ct = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
249  %conv = trunc i64 %ct to i16
250  %tobool = icmp ne i64 %x, 0
251  %cond = select i1 %tobool, i16 %conv, i16 64
252  ret i16 %cond
253}
254
255define i32 @test2d(i64 %x) {
256; CHECK-LABEL: @test2d(
257; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false)
258; CHECK-NEXT:    [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32
259; CHECK-NEXT:    ret i32 [[CAST]]
260;
261  %ct = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
262  %cast = trunc i64 %ct to i32
263  %tobool = icmp ne i64 %x, 0
264  %cond = select i1 %tobool, i32 %cast, i32 64
265  ret i32 %cond
266}
267
268define i16 @test3d(i32 %x) {
269; CHECK-LABEL: @test3d(
270; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false)
271; CHECK-NEXT:    [[CAST:%.*]] = trunc nuw nsw i32 [[CT]] to i16
272; CHECK-NEXT:    ret i16 [[CAST]]
273;
274  %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
275  %cast = trunc i32 %ct to i16
276  %tobool = icmp ne i32 %x, 0
277  %cond = select i1 %tobool, i16 %cast, i16 32
278  ret i16 %cond
279}
280
281define i16 @test4d(i64 %x) {
282; CHECK-LABEL: @test4d(
283; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X:%.*]], i1 false)
284; CHECK-NEXT:    [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i16
285; CHECK-NEXT:    ret i16 [[CAST]]
286;
287  %ct = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
288  %cast = trunc i64 %ct to i16
289  %tobool = icmp ne i64 %x, 0
290  %cond = select i1 %tobool, i16 %cast, i16 64
291  ret i16 %cond
292}
293
294define i32 @test5d(i64 %x) {
295; CHECK-LABEL: @test5d(
296; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X:%.*]], i1 false)
297; CHECK-NEXT:    [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32
298; CHECK-NEXT:    ret i32 [[CAST]]
299;
300  %ct = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
301  %cast = trunc i64 %ct to i32
302  %tobool = icmp ne i64 %x, 0
303  %cond = select i1 %tobool, i32 %cast, i32 64
304  ret i32 %cond
305}
306
307; Same as above, but the counting zeros on an inverted operand with opposite compare.
308
309define i32 @not_op_ctlz(i64 %x) {
310; CHECK-LABEL: @not_op_ctlz(
311; CHECK-NEXT:    [[N:%.*]] = xor i64 [[X:%.*]], -1
312; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[N]], i1 false)
313; CHECK-NEXT:    [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32
314; CHECK-NEXT:    ret i32 [[CAST]]
315;
316  %n = xor i64 %x, -1
317  %ct = tail call i64 @llvm.ctlz.i64(i64 %n, i1 true)
318  %cast = trunc i64 %ct to i32
319  %tobool = icmp eq i64 %x, -1
320  %r = select i1 %tobool, i32 64, i32 %cast
321  ret i32 %r
322}
323
324define i32 @not_op_cttz(i64 %x) {
325; CHECK-LABEL: @not_op_cttz(
326; CHECK-NEXT:    [[N:%.*]] = xor i64 [[X:%.*]], -1
327; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[N]], i1 false)
328; CHECK-NEXT:    [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32
329; CHECK-NEXT:    ret i32 [[CAST]]
330;
331  %n = xor i64 %x, -1
332  %ct = tail call i64 @llvm.cttz.i64(i64 %n, i1 true)
333  %cast = trunc i64 %ct to i32
334  %tobool = icmp eq i64 %x, -1
335  %r = select i1 %tobool, i32 64, i32 %cast
336  ret i32 %r
337}
338
339; negative test
340
341define i32 @not_op_ctlz_wrong_xor_op1(i64 %x) {
342; CHECK-LABEL: @not_op_ctlz_wrong_xor_op1(
343; CHECK-NEXT:    [[N:%.*]] = xor i64 [[X:%.*]], -2
344; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[N]], i1 true)
345; CHECK-NEXT:    [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32
346; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[X]], -1
347; CHECK-NEXT:    [[R:%.*]] = select i1 [[TOBOOL]], i32 64, i32 [[CAST]]
348; CHECK-NEXT:    ret i32 [[R]]
349;
350  %n = xor i64 %x, -2
351  %ct = tail call i64 @llvm.ctlz.i64(i64 %n, i1 true)
352  %cast = trunc i64 %ct to i32
353  %tobool = icmp eq i64 %x, -1
354  %r = select i1 %tobool, i32 64, i32 %cast
355  ret i32 %r
356}
357
358; negative test
359
360define i32 @not_op_ctlz_wrong_xor_op0(i64 %x, i64 %y) {
361; CHECK-LABEL: @not_op_ctlz_wrong_xor_op0(
362; CHECK-NEXT:    [[N:%.*]] = xor i64 [[Y:%.*]], -1
363; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[N]], i1 true)
364; CHECK-NEXT:    [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32
365; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], -1
366; CHECK-NEXT:    [[R:%.*]] = select i1 [[TOBOOL]], i32 64, i32 [[CAST]]
367; CHECK-NEXT:    ret i32 [[R]]
368;
369  %n = xor i64 %y, -1
370  %ct = tail call i64 @llvm.ctlz.i64(i64 %n, i1 true)
371  %cast = trunc i64 %ct to i32
372  %tobool = icmp eq i64 %x, -1
373  %r = select i1 %tobool, i32 64, i32 %cast
374  ret i32 %r
375}
376
377; negative test
378
379define i32 @not_op_cttz_wrong_cmp(i64 %x) {
380; CHECK-LABEL: @not_op_cttz_wrong_cmp(
381; CHECK-NEXT:    [[N:%.*]] = xor i64 [[X:%.*]], -1
382; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[N]], i1 true)
383; CHECK-NEXT:    [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32
384; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[X]], 0
385; CHECK-NEXT:    [[R:%.*]] = select i1 [[TOBOOL]], i32 64, i32 [[CAST]]
386; CHECK-NEXT:    ret i32 [[R]]
387;
388  %n = xor i64 %x, -1
389  %ct = tail call i64 @llvm.cttz.i64(i64 %n, i1 true)
390  %cast = trunc i64 %ct to i32
391  %tobool = icmp eq i64 %x, 0
392  %r = select i1 %tobool, i32 64, i32 %cast
393  ret i32 %r
394}
395
396define i16 @test6d(i32 %x) {
397; CHECK-LABEL: @test6d(
398; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false)
399; CHECK-NEXT:    [[CAST:%.*]] = trunc nuw nsw i32 [[CT]] to i16
400; CHECK-NEXT:    ret i16 [[CAST]]
401;
402  %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
403  %cast = trunc i32 %ct to i16
404  %tobool = icmp ne i32 %x, 0
405  %cond = select i1 %tobool, i16 %cast, i16 32
406  ret i16 %cond
407}
408
409define i64 @select_bug1(i32 %x) {
410; CHECK-LABEL: @select_bug1(
411; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false)
412; CHECK-NEXT:    [[CONV:%.*]] = zext nneg i32 [[CT]] to i64
413; CHECK-NEXT:    ret i64 [[CONV]]
414;
415  %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
416  %conv = zext i32 %ct to i64
417  %tobool = icmp ne i32 %x, 0
418  %cond = select i1 %tobool, i64 %conv, i64 32
419  ret i64 %cond
420}
421
422define i16 @select_bug2(i32 %x) {
423; CHECK-LABEL: @select_bug2(
424; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false)
425; CHECK-NEXT:    [[CONV:%.*]] = trunc nuw nsw i32 [[CT]] to i16
426; CHECK-NEXT:    ret i16 [[CONV]]
427;
428  %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
429  %conv = trunc i32 %ct to i16
430  %tobool = icmp ne i32 %x, 0
431  %cond = select i1 %tobool, i16 %conv, i16 32
432  ret i16 %cond
433}
434
435define i128 @test7(i128 %x) {
436; CHECK-LABEL: @test7(
437; CHECK-NEXT:    [[CT:%.*]] = tail call range(i128 0, 129) i128 @llvm.ctlz.i128(i128 [[X:%.*]], i1 false)
438; CHECK-NEXT:    ret i128 [[CT]]
439;
440  %ct = tail call i128 @llvm.ctlz.i128(i128 %x, i1 true)
441  %tobool = icmp ne i128 %x, 0
442  %cond = select i1 %tobool, i128 %ct, i128 128
443  ret i128 %cond
444}
445
446define i128 @test8(i128 %x) {
447; CHECK-LABEL: @test8(
448; CHECK-NEXT:    [[CT:%.*]] = tail call range(i128 0, 129) i128 @llvm.cttz.i128(i128 [[X:%.*]], i1 false)
449; CHECK-NEXT:    ret i128 [[CT]]
450;
451  %ct = tail call i128 @llvm.cttz.i128(i128 %x, i1 true)
452  %tobool = icmp ne i128 %x, 0
453  %cond = select i1 %tobool, i128 %ct, i128 128
454  ret i128 %cond
455}
456
457define i32 @test_ctlz_not_bw(i32 %x) {
458; CHECK-LABEL: @test_ctlz_not_bw(
459; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 true)
460; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[X]], 0
461; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP_NOT]], i32 123, i32 [[CT]]
462; CHECK-NEXT:    ret i32 [[RES]]
463;
464  %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
465  %cmp = icmp ne i32 %x, 0
466  %res = select i1 %cmp, i32 %ct, i32 123
467  ret i32 %res
468}
469
470define i32 @test_ctlz_not_bw_multiuse(i32 %x) {
471; CHECK-LABEL: @test_ctlz_not_bw_multiuse(
472; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false)
473; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[X]], 0
474; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP_NOT]], i32 123, i32 [[CT]]
475; CHECK-NEXT:    [[RES:%.*]] = or i32 [[SEL]], [[CT]]
476; CHECK-NEXT:    ret i32 [[RES]]
477;
478  %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
479  %cmp = icmp ne i32 %x, 0
480  %sel = select i1 %cmp, i32 %ct, i32 123
481  %res = or i32 %sel, %ct
482  ret i32 %res
483}
484
485define i32 @test_cttz_not_bw(i32 %x) {
486; CHECK-LABEL: @test_cttz_not_bw(
487; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
488; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[X]], 0
489; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP_NOT]], i32 123, i32 [[CT]]
490; CHECK-NEXT:    ret i32 [[RES]]
491;
492  %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
493  %cmp = icmp ne i32 %x, 0
494  %res = select i1 %cmp, i32 %ct, i32 123
495  ret i32 %res
496}
497
498define i32 @test_cttz_not_bw_noundef(i32 %x) {
499; CHECK-LABEL: @test_cttz_not_bw_noundef(
500; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
501; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[X]], 0
502; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP_NOT]], i32 123, i32 [[CT]]
503; CHECK-NEXT:    ret i32 [[RES]]
504;
505  %ct = tail call noundef i32 @llvm.cttz.i32(i32 %x, i1 false)
506  %cmp = icmp ne i32 %x, 0
507  %res = select i1 %cmp, i32 %ct, i32 123
508  ret i32 %res
509}
510
511define i32 @test_cttz_not_bw_multiuse(i32 %x) {
512; CHECK-LABEL: @test_cttz_not_bw_multiuse(
513; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false)
514; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[X]], 0
515; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP_NOT]], i32 123, i32 [[CT]]
516; CHECK-NEXT:    [[RES:%.*]] = or i32 [[SEL]], [[CT]]
517; CHECK-NEXT:    ret i32 [[RES]]
518;
519  %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
520  %cmp = icmp ne i32 %x, 0
521  %sel = select i1 %cmp, i32 %ct, i32 123
522  %res = or i32 %sel, %ct
523  ret i32 %res
524}
525
526define <2 x i32> @test_ctlz_bw_vec(<2 x i32> %x) {
527; CHECK-LABEL: @test_ctlz_bw_vec(
528; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[X:%.*]], i1 false)
529; CHECK-NEXT:    ret <2 x i32> [[CT]]
530;
531  %ct = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %x, i1 true)
532  %cmp = icmp ne <2 x i32> %x, zeroinitializer
533  %res = select <2 x i1> %cmp, <2 x i32> %ct, <2 x i32> <i32 32, i32 32>
534  ret <2 x i32> %res
535}
536
537define <2 x i32> @test_ctlz_not_bw_vec(<2 x i32> %x) {
538; CHECK-LABEL: @test_ctlz_not_bw_vec(
539; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[X:%.*]], i1 true)
540; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i32> [[X]], zeroinitializer
541; CHECK-NEXT:    [[RES:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i32> zeroinitializer, <2 x i32> [[CT]]
542; CHECK-NEXT:    ret <2 x i32> [[RES]]
543;
544  %ct = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %x, i1 false)
545  %cmp = icmp ne <2 x i32> %x, zeroinitializer
546  %res = select <2 x i1> %cmp, <2 x i32> %ct, <2 x i32> <i32 0, i32 0>
547  ret <2 x i32> %res
548}
549
550define <2 x i32> @test_cttz_bw_vec(<2 x i32> %x) {
551; CHECK-LABEL: @test_cttz_bw_vec(
552; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X:%.*]], i1 false)
553; CHECK-NEXT:    ret <2 x i32> [[CT]]
554;
555  %ct = tail call <2 x i32> @llvm.cttz.v2i32(<2 x i32> %x, i1 true)
556  %cmp = icmp ne <2 x i32> %x, zeroinitializer
557  %res = select <2 x i1> %cmp, <2 x i32> %ct, <2 x i32> <i32 32, i32 32>
558  ret <2 x i32> %res
559}
560
561define <2 x i32> @test_cttz_not_bw_vec(<2 x i32> %x) {
562; CHECK-LABEL: @test_cttz_not_bw_vec(
563; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X:%.*]], i1 true)
564; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i32> [[X]], zeroinitializer
565; CHECK-NEXT:    [[RES:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i32> zeroinitializer, <2 x i32> [[CT]]
566; CHECK-NEXT:    ret <2 x i32> [[RES]]
567;
568  %ct = tail call <2 x i32> @llvm.cttz.v2i32(<2 x i32> %x, i1 false)
569  %cmp = icmp ne <2 x i32> %x, zeroinitializer
570  %res = select <2 x i1> %cmp, <2 x i32> %ct, <2 x i32> <i32 0, i32 0>
571  ret <2 x i32> %res
572}
573
574define i32 @test_multiuse_def(i32 %x, ptr %p) {
575; CHECK-LABEL: @test_multiuse_def(
576; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false)
577; CHECK-NEXT:    store i32 [[CT]], ptr [[P:%.*]], align 4
578; CHECK-NEXT:    ret i32 [[CT]]
579;
580  %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
581  %tobool = icmp ne i32 %x, 0
582  %cond = select i1 %tobool, i32 %ct, i32 32
583  store i32 %ct, ptr %p
584  ret i32 %cond
585}
586
587define i32 @test_multiuse_undef(i32 %x, ptr %p) {
588; CHECK-LABEL: @test_multiuse_undef(
589; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false)
590; CHECK-NEXT:    store i32 [[CT]], ptr [[P:%.*]], align 4
591; CHECK-NEXT:    ret i32 [[CT]]
592;
593  %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
594  %tobool = icmp ne i32 %x, 0
595  %cond = select i1 %tobool, i32 %ct, i32 32
596  store i32 %ct, ptr %p
597  ret i32 %cond
598}
599
600define i64 @test_multiuse_zext_def(i32 %x, ptr %p) {
601; CHECK-LABEL: @test_multiuse_zext_def(
602; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false)
603; CHECK-NEXT:    [[CONV:%.*]] = zext nneg i32 [[CT]] to i64
604; CHECK-NEXT:    store i64 [[CONV]], ptr [[P:%.*]], align 4
605; CHECK-NEXT:    ret i64 [[CONV]]
606;
607  %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
608  %conv = zext i32 %ct to i64
609  %tobool = icmp ne i32 %x, 0
610  %cond = select i1 %tobool, i64 %conv, i64 32
611  store i64 %conv, ptr %p
612  ret i64 %cond
613}
614
615define i64 @test_multiuse_zext_undef(i32 %x, ptr %p) {
616; CHECK-LABEL: @test_multiuse_zext_undef(
617; CHECK-NEXT:    [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false)
618; CHECK-NEXT:    [[CONV:%.*]] = zext nneg i32 [[CT]] to i64
619; CHECK-NEXT:    store i64 [[CONV]], ptr [[P:%.*]], align 4
620; CHECK-NEXT:    ret i64 [[CONV]]
621;
622  %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
623  %conv = zext i32 %ct to i64
624  %tobool = icmp ne i32 %x, 0
625  %cond = select i1 %tobool, i64 %conv, i64 32
626  store i64 %conv, ptr %p
627  ret i64 %cond
628}
629
630define i16 @test_multiuse_trunc_def(i64 %x, ptr %p) {
631; CHECK-LABEL: @test_multiuse_trunc_def(
632; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false)
633; CHECK-NEXT:    [[CONV:%.*]] = trunc nuw nsw i64 [[CT]] to i16
634; CHECK-NEXT:    store i16 [[CONV]], ptr [[P:%.*]], align 2
635; CHECK-NEXT:    ret i16 [[CONV]]
636;
637  %ct = tail call i64 @llvm.cttz.i64(i64 %x, i1 false)
638  %conv = trunc i64 %ct to i16
639  %tobool = icmp ne i64 %x, 0
640  %cond = select i1 %tobool, i16 %conv, i16 64
641  store i16 %conv, ptr %p
642  ret i16 %cond
643}
644
645define i16 @test_multiuse_trunc_undef(i64 %x, ptr %p) {
646; CHECK-LABEL: @test_multiuse_trunc_undef(
647; CHECK-NEXT:    [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false)
648; CHECK-NEXT:    [[CONV:%.*]] = trunc nuw nsw i64 [[CT]] to i16
649; CHECK-NEXT:    store i16 [[CONV]], ptr [[P:%.*]], align 2
650; CHECK-NEXT:    ret i16 [[CONV]]
651;
652  %ct = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
653  %conv = trunc i64 %ct to i16
654  %tobool = icmp ne i64 %x, 0
655  %cond = select i1 %tobool, i16 %conv, i16 64
656  store i16 %conv, ptr %p
657  ret i16 %cond
658}
659
660declare i16 @llvm.ctlz.i16(i16, i1)
661declare i32 @llvm.ctlz.i32(i32, i1)
662declare i64 @llvm.ctlz.i64(i64, i1)
663declare i128 @llvm.ctlz.i128(i128, i1)
664declare <2 x i32> @llvm.ctlz.v2i32(<2 x i32>, i1)
665declare i16 @llvm.cttz.i16(i16, i1)
666declare i32 @llvm.cttz.i32(i32, i1)
667declare i64 @llvm.cttz.i64(i64, i1)
668declare i128 @llvm.cttz.i128(i128, i1)
669declare <2 x i32> @llvm.cttz.v2i32(<2 x i32>, i1)
670