xref: /llvm-project/llvm/test/Transforms/InstCombine/cttz.ll (revision 3318a7248ae464af0abd0bea5515fa58c962b890)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -S -passes=instcombine | FileCheck %s
3
4declare i32 @llvm.cttz.i32(i32, i1)
5declare i32 @llvm.ctlz.i32(i32, i1)
6declare <2 x i64> @llvm.cttz.v2i64(<2 x i64>, i1)
7declare void @use(i32)
8
9define i32 @cttz_zext_zero_undef(i16 %x) {
10; CHECK-LABEL: @cttz_zext_zero_undef(
11; CHECK-NEXT:    [[TMP1:%.*]] = call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 true)
12; CHECK-NEXT:    [[TZ:%.*]] = zext nneg i16 [[TMP1]] to i32
13; CHECK-NEXT:    ret i32 [[TZ]]
14;
15  %z = zext i16 %x to i32
16  %tz = call i32 @llvm.cttz.i32(i32 %z, i1 true)
17  ret i32 %tz
18}
19
20define i32 @cttz_zext_zero_def(i16 %x) {
21; CHECK-LABEL: @cttz_zext_zero_def(
22; CHECK-NEXT:    [[Z:%.*]] = zext i16 [[X:%.*]] to i32
23; CHECK-NEXT:    [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[Z]], i1 false)
24; CHECK-NEXT:    ret i32 [[TZ]]
25;
26  %z = zext i16 %x to i32
27  %tz = call i32 @llvm.cttz.i32(i32 %z, i1 false)
28  ret i32 %tz
29}
30
31define i32 @cttz_zext_zero_undef_extra_use(i16 %x) {
32; CHECK-LABEL: @cttz_zext_zero_undef_extra_use(
33; CHECK-NEXT:    [[Z:%.*]] = zext i16 [[X:%.*]] to i32
34; CHECK-NEXT:    call void @use(i32 [[Z]])
35; CHECK-NEXT:    [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[Z]], i1 true)
36; CHECK-NEXT:    ret i32 [[TZ]]
37;
38  %z = zext i16 %x to i32
39  call void @use(i32 %z)
40  %tz = call i32 @llvm.cttz.i32(i32 %z, i1 true)
41  ret i32 %tz
42}
43
44define <2 x i64> @cttz_zext_zero_undef_vec(<2 x i32> %x) {
45; CHECK-LABEL: @cttz_zext_zero_undef_vec(
46; CHECK-NEXT:    [[TMP1:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X:%.*]], i1 true)
47; CHECK-NEXT:    [[TZ:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>
48; CHECK-NEXT:    ret <2 x i64> [[TZ]]
49;
50  %z = zext <2 x i32> %x to <2 x i64>
51  %tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %z, i1 true)
52  ret <2 x i64> %tz
53}
54
55define <2 x i64> @cttz_zext_zero_def_vec(<2 x i32> %x) {
56; CHECK-LABEL: @cttz_zext_zero_def_vec(
57; CHECK-NEXT:    [[Z:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64>
58; CHECK-NEXT:    [[TZ:%.*]] = tail call range(i64 0, 65) <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[Z]], i1 false)
59; CHECK-NEXT:    ret <2 x i64> [[TZ]]
60;
61  %z = zext <2 x i32> %x to <2 x i64>
62  %tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %z, i1 false)
63  ret <2 x i64> %tz
64}
65
66define i32 @cttz_sext_zero_undef(i16 %x) {
67; CHECK-LABEL: @cttz_sext_zero_undef(
68; CHECK-NEXT:    [[TMP1:%.*]] = call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 true)
69; CHECK-NEXT:    [[TZ:%.*]] = zext nneg i16 [[TMP1]] to i32
70; CHECK-NEXT:    ret i32 [[TZ]]
71;
72  %s = sext i16 %x to i32
73  %tz = call i32 @llvm.cttz.i32(i32 %s, i1 true)
74  ret i32 %tz
75}
76
77define i32 @cttz_sext_zero_def(i16 %x) {
78; CHECK-LABEL: @cttz_sext_zero_def(
79; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[X:%.*]] to i32
80; CHECK-NEXT:    [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[TMP1]], i1 false)
81; CHECK-NEXT:    ret i32 [[TZ]]
82;
83  %s = sext i16 %x to i32
84  %tz = call i32 @llvm.cttz.i32(i32 %s, i1 false)
85  ret i32 %tz
86}
87
88define i32 @cttz_sext_zero_undef_extra_use(i16 %x) {
89; CHECK-LABEL: @cttz_sext_zero_undef_extra_use(
90; CHECK-NEXT:    [[S:%.*]] = sext i16 [[X:%.*]] to i32
91; CHECK-NEXT:    call void @use(i32 [[S]])
92; CHECK-NEXT:    [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[S]], i1 true)
93; CHECK-NEXT:    ret i32 [[TZ]]
94;
95  %s = sext i16 %x to i32
96  call void @use(i32 %s)
97  %tz = call i32 @llvm.cttz.i32(i32 %s, i1 true)
98  ret i32 %tz
99}
100
101define <2 x i64> @cttz_sext_zero_undef_vec(<2 x i32> %x) {
102; CHECK-LABEL: @cttz_sext_zero_undef_vec(
103; CHECK-NEXT:    [[TMP1:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X:%.*]], i1 true)
104; CHECK-NEXT:    [[TZ:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>
105; CHECK-NEXT:    ret <2 x i64> [[TZ]]
106;
107  %s = sext <2 x i32> %x to <2 x i64>
108  %tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %s, i1 true)
109  ret <2 x i64> %tz
110}
111
112define <2 x i64> @cttz_sext_zero_def_vec(<2 x i32> %x) {
113; CHECK-LABEL: @cttz_sext_zero_def_vec(
114; CHECK-NEXT:    [[TMP1:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64>
115; CHECK-NEXT:    [[TZ:%.*]] = call range(i64 0, 65) <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[TMP1]], i1 false)
116; CHECK-NEXT:    ret <2 x i64> [[TZ]]
117;
118  %s = sext <2 x i32> %x to <2 x i64>
119  %tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %s, i1 false)
120  ret <2 x i64> %tz
121}
122
123define i32 @cttz_of_lowest_set_bit(i32 %x) {
124; CHECK-LABEL: @cttz_of_lowest_set_bit(
125; CHECK-NEXT:    [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false)
126; CHECK-NEXT:    ret i32 [[TZ]]
127;
128  %sub = sub i32 0, %x
129  %and = and i32 %sub, %x
130  %tz = call i32 @llvm.cttz.i32(i32 %and, i1 false)
131  ret i32 %tz
132}
133
134define i32 @cttz_of_lowest_set_bit_commuted(i32 %xx) {
135; CHECK-LABEL: @cttz_of_lowest_set_bit_commuted(
136; CHECK-NEXT:    [[X:%.*]] = udiv i32 42, [[XX:%.*]]
137; CHECK-NEXT:    [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 false)
138; CHECK-NEXT:    ret i32 [[TZ]]
139;
140  %x = udiv i32 42, %xx ; thwart complexity-based canonicalization
141  %sub = sub i32 0, %x
142  %and = and i32 %x, %sub
143  %tz = call i32 @llvm.cttz.i32(i32 %and, i1 false)
144  ret i32 %tz
145}
146
147define i32 @cttz_of_lowest_set_bit_poison_flag(i32 %x) {
148; CHECK-LABEL: @cttz_of_lowest_set_bit_poison_flag(
149; CHECK-NEXT:    [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
150; CHECK-NEXT:    ret i32 [[TZ]]
151;
152  %sub = sub i32 0, %x
153  %and = and i32 %sub, %x
154  %tz = call i32 @llvm.cttz.i32(i32 %and, i1 true)
155  ret i32 %tz
156}
157
158define <2 x i64> @cttz_of_lowest_set_bit_vec(<2 x i64> %x) {
159; CHECK-LABEL: @cttz_of_lowest_set_bit_vec(
160; CHECK-NEXT:    [[TZ:%.*]] = call range(i64 0, 65) <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[X:%.*]], i1 false)
161; CHECK-NEXT:    ret <2 x i64> [[TZ]]
162;
163  %sub = sub <2 x i64> zeroinitializer, %x
164  %and = and <2 x i64> %sub, %x
165  %tz = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %and, i1 false)
166  ret <2 x i64> %tz
167}
168
169define <2 x i64> @cttz_of_lowest_set_bit_vec_undef(<2 x i64> %x) {
170; CHECK-LABEL: @cttz_of_lowest_set_bit_vec_undef(
171; CHECK-NEXT:    [[TZ:%.*]] = call range(i64 0, 65) <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[X:%.*]], i1 false)
172; CHECK-NEXT:    ret <2 x i64> [[TZ]]
173;
174  %sub = sub <2 x i64> zeroinitializer, %x
175  %and = and <2 x i64> %sub, %x
176  %tz = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %and, i1 false)
177  ret <2 x i64> %tz
178}
179
180define i32 @cttz_of_lowest_set_bit_wrong_const(i32 %x) {
181; CHECK-LABEL: @cttz_of_lowest_set_bit_wrong_const(
182; CHECK-NEXT:    [[SUB:%.*]] = sub i32 1, [[X:%.*]]
183; CHECK-NEXT:    [[AND:%.*]] = and i32 [[SUB]], [[X]]
184; CHECK-NEXT:    [[TZ:%.*]] = call range(i32 1, 33) i32 @llvm.cttz.i32(i32 [[AND]], i1 false)
185; CHECK-NEXT:    ret i32 [[TZ]]
186;
187  %sub = sub i32 1, %x
188  %and = and i32 %sub, %x
189  %tz = call i32 @llvm.cttz.i32(i32 %and, i1 false)
190  ret i32 %tz
191}
192
193define i32 @cttz_of_lowest_set_bit_wrong_operand(i32 %x, i32 %y) {
194; CHECK-LABEL: @cttz_of_lowest_set_bit_wrong_operand(
195; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[Y:%.*]]
196; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[SUB]]
197; CHECK-NEXT:    [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[AND]], i1 false)
198; CHECK-NEXT:    ret i32 [[TZ]]
199;
200  %sub = sub i32 0, %y
201  %and = and i32 %sub, %x
202  %tz = call i32 @llvm.cttz.i32(i32 %and, i1 false)
203  ret i32 %tz
204}
205
206define i32 @cttz_of_lowest_set_bit_wrong_intrinsic(i32 %x) {
207; CHECK-LABEL: @cttz_of_lowest_set_bit_wrong_intrinsic(
208; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[X:%.*]]
209; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], [[SUB]]
210; CHECK-NEXT:    [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[AND]], i1 false)
211; CHECK-NEXT:    ret i32 [[TZ]]
212;
213  %sub = sub i32 0, %x
214  %and = and i32 %sub, %x
215  %tz = call i32 @llvm.ctlz.i32(i32 %and, i1 false)
216  ret i32 %tz
217}
218
219define i32 @cttz_of_power_of_two(i32 %x) {
220; CHECK-LABEL: @cttz_of_power_of_two(
221; CHECK-NEXT:    [[R:%.*]] = sub i32 32, [[X:%.*]]
222; CHECK-NEXT:    ret i32 [[R]]
223;
224  %lshr = lshr i32 -1, %x
225  %add = add i32 %lshr, 1
226  %r = call i32 @llvm.cttz.i32(i32 %add, i1 false)
227  ret i32 %r
228}
229
230define i32 @cttz_of_power_of_two_zero_poison(i32 %x) {
231; CHECK-LABEL: @cttz_of_power_of_two_zero_poison(
232; CHECK-NEXT:    [[R:%.*]] = sub i32 32, [[X:%.*]]
233; CHECK-NEXT:    ret i32 [[R]]
234;
235  %lshr = lshr i32 -1, %x
236  %add = add i32 %lshr, 1
237  %r = call i32 @llvm.cttz.i32(i32 %add, i1 true)
238  ret i32 %r
239}
240
241define i32 @cttz_of_power_of_two_wrong_intrinsic(i32 %x) {
242; CHECK-LABEL: @cttz_of_power_of_two_wrong_intrinsic(
243; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 -1, [[X:%.*]]
244; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LSHR]], 1
245; CHECK-NEXT:    [[R:%.*]] = call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[ADD]], i1 false)
246; CHECK-NEXT:    ret i32 [[R]]
247;
248  %lshr = lshr i32 -1, %x
249  %add = add i32 %lshr, 1
250  %r = call i32 @llvm.ctlz.i32(i32 %add, i1 false)
251  ret i32 %r
252}
253
254define i32 @cttz_of_power_of_two_wrong_constant_1(i32 %x) {
255; CHECK-LABEL: @cttz_of_power_of_two_wrong_constant_1(
256; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 -2, [[X:%.*]]
257; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[LSHR]], 1
258; CHECK-NEXT:    [[R:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[ADD]], i1 true)
259; CHECK-NEXT:    ret i32 [[R]]
260;
261  %lshr = lshr i32 -2, %x
262  %add = add i32 %lshr, 1
263  %r = call i32 @llvm.cttz.i32(i32 %add, i1 false)
264  ret i32 %r
265}
266
267define i32 @cttz_of_power_of_two_wrong_constant_2(i32 %x) {
268; CHECK-LABEL: @cttz_of_power_of_two_wrong_constant_2(
269; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 -1, [[X:%.*]]
270; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[LSHR]], -1
271; CHECK-NEXT:    [[R:%.*]] = call range(i32 1, 33) i32 @llvm.cttz.i32(i32 [[ADD]], i1 false)
272; CHECK-NEXT:    ret i32 [[R]]
273;
274  %lshr = lshr i32 -1, %x
275  %add = add i32 %lshr, -1
276  %r = call i32 @llvm.cttz.i32(i32 %add, i1 false)
277  ret i32 %r
278}
279
280define i16 @cttz_assume(i16 %x) {
281; CHECK-LABEL: @cttz_assume(
282; CHECK-NEXT:    [[ADD:%.*]] = add i16 [[X:%.*]], 1
283; CHECK-NEXT:    [[COND0:%.*]] = icmp ult i16 [[ADD]], 10
284; CHECK-NEXT:    call void @llvm.assume(i1 [[COND0]])
285; CHECK-NEXT:    [[COND1:%.*]] = icmp ne i16 [[X]], 0
286; CHECK-NEXT:    call void @llvm.assume(i1 [[COND1]])
287; CHECK-NEXT:    [[CTTZ:%.*]] = call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X]], i1 true)
288; CHECK-NEXT:    ret i16 [[CTTZ]]
289;
290  %add = add i16 %x, 1
291  %cond0 = icmp ult i16 %add, 10
292  call void @llvm.assume(i1 %cond0)
293
294  %cond1 = icmp ne i16 %x, 0
295  call void @llvm.assume(i1 %cond1)
296
297  %cttz = call i16 @llvm.cttz.i16(i16 %x, i1 false)
298  ret i16 %cttz
299}
300
301
302declare void @use.i8(i8)
303define i8 @fold_ctz_log2(i8 %x) {
304; CHECK-LABEL: @fold_ctz_log2(
305; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 5)
306; CHECK-NEXT:    ret i8 [[R]]
307;
308  %p2 = shl i8 1, %x
309  %v = call i8 @llvm.umin(i8 %p2, i8 32)
310  %r = call i8 @llvm.cttz(i8 %v, i1 false)
311  ret i8 %r
312}
313
314define i9 @fold_ctz_log2_i9_okay(i9 %x) {
315; CHECK-LABEL: @fold_ctz_log2_i9_okay(
316; CHECK-NEXT:    [[R:%.*]] = call i9 @llvm.umin.i9(i9 [[X:%.*]], i9 5)
317; CHECK-NEXT:    ret i9 [[R]]
318;
319  %p2 = shl i9 1, %x
320  %v = call i9 @llvm.umin(i9 %p2, i9 32)
321  %r = call i9 @llvm.cttz(i9 %v, i1 false)
322  ret i9 %r
323}
324
325define i8 @fold_ctz_log2_maybe_z(i8 %x, i8 %y, i1 %c) {
326; CHECK-LABEL: @fold_ctz_log2_maybe_z(
327; CHECK-NEXT:    [[V:%.*]] = shl i8 2, [[V_V:%.*]]
328; CHECK-NEXT:    [[P2_2:%.*]] = shl i8 4, [[Y:%.*]]
329; CHECK-NEXT:    [[V1:%.*]] = select i1 [[C:%.*]], i8 [[V]], i8 [[P2_2]]
330; CHECK-NEXT:    [[R:%.*]] = call range(i8 1, 9) i8 @llvm.cttz.i8(i8 [[V1]], i1 false)
331; CHECK-NEXT:    ret i8 [[R]]
332;
333  %p2 = shl i8 2, %x
334  %p2_2 = shl i8 4, %y
335  %v = select i1 %c, i8 %p2, i8 %p2_2
336  %r = call i8 @llvm.cttz(i8 %v, i1 false)
337  ret i8 %r
338}
339
340define i8 @fold_ctz_log2_maybe_z_okay(i8 %x, i8 %y, i1 %c) {
341; CHECK-LABEL: @fold_ctz_log2_maybe_z_okay(
342; CHECK-NEXT:    [[X:%.*]] = add i8 [[X1:%.*]], 1
343; CHECK-NEXT:    [[Y:%.*]] = add i8 [[Y1:%.*]], 2
344; CHECK-NEXT:    [[V_V:%.*]] = select i1 [[C:%.*]], i8 [[X]], i8 [[Y]]
345; CHECK-NEXT:    ret i8 [[V_V]]
346;
347  %p2 = shl i8 2, %x
348  %p2_2 = shl i8 4, %y
349  %v = select i1 %c, i8 %p2, i8 %p2_2
350  %r = call i8 @llvm.cttz(i8 %v, i1 true)
351  ret i8 %r
352}
353
354define i8 @fold_clz_log2(i8 %x) {
355; CHECK-LABEL: @fold_clz_log2(
356; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 5)
357; CHECK-NEXT:    [[R:%.*]] = xor i8 [[TMP1]], 7
358; CHECK-NEXT:    ret i8 [[R]]
359;
360  %p2 = shl i8 1, %x
361  %v = call i8 @llvm.umin(i8 %p2, i8 32)
362  %r = call i8 @llvm.ctlz(i8 %v, i1 false)
363  ret i8 %r
364}
365
366define i8 @fold_clz_log2_multiuse_fail(i8 %x) {
367; CHECK-LABEL: @fold_clz_log2_multiuse_fail(
368; CHECK-NEXT:    [[P2:%.*]] = shl nuw i8 2, [[X:%.*]]
369; CHECK-NEXT:    [[V:%.*]] = call i8 @llvm.umin.i8(i8 [[P2]], i8 32)
370; CHECK-NEXT:    call void @use.i8(i8 [[V]])
371; CHECK-NEXT:    [[R:%.*]] = call range(i8 2, 9) i8 @llvm.ctlz.i8(i8 [[V]], i1 true)
372; CHECK-NEXT:    ret i8 [[R]]
373;
374  %p2 = shl nuw i8 2, %x
375  %v = call i8 @llvm.umin(i8 %p2, i8 32)
376  call void @use.i8(i8 %v)
377  %r = call i8 @llvm.ctlz(i8 %v, i1 true)
378  ret i8 %r
379}
380
381
382define i9 @fold_clz_log2_i9(i9 %x) {
383; CHECK-LABEL: @fold_clz_log2_i9(
384; CHECK-NEXT:    [[TMP1:%.*]] = call i9 @llvm.umin.i9(i9 [[X:%.*]], i9 5)
385; CHECK-NEXT:    [[R:%.*]] = sub nuw nsw i9 8, [[TMP1]]
386; CHECK-NEXT:    ret i9 [[R]]
387;
388  %p2 = shl i9 1, %x
389  %v = call i9 @llvm.umin(i9 %p2, i9 32)
390  %r = call i9 @llvm.ctlz(i9 %v, i1 true)
391  ret i9 %r
392}
393