xref: /llvm-project/llvm/test/Analysis/ValueTracking/known-power-of-two.ll (revision a105877646d68e48cdeeeadd9d1e075dc3c5d68d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3
4; https://llvm.org/bugs/show_bug.cgi?id=25900
5; An arithmetic shift right of a power of two is not a power
6; of two if the original value is the sign bit. Therefore,
7; we can't transform the sdiv into a udiv.
8
9declare i16 @llvm.bitreverse.i16(i16)
10declare i16 @llvm.bswap.i16(i16)
11declare i16 @llvm.ctpop.i16(i16)
12declare i16 @llvm.fshl.i16(i16, i16, i16)
13declare i16 @llvm.fshr.i16(i16, i16, i16)
14declare i16 @llvm.umax.i16(i16, i16)
15
16define i32 @pr25900(i32 %d) {
17; CHECK-LABEL: define i32 @pr25900
18; CHECK-SAME: (i32 [[D:%.*]]) {
19; CHECK-NEXT:    [[ASHR:%.*]] = ashr i32 [[D]], 31
20; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 4, [[ASHR]]
21; CHECK-NEXT:    ret i32 [[DIV]]
22;
23  %and = and i32 %d, -2147483648
24; The next 3 lines prevent another fold from masking the bug.
25  %ext = zext i32 %and to i64
26  %or = or i64 %ext, 4294967296
27  %trunc = trunc i64 %or to i32
28  %ashr = ashr exact i32 %trunc, 31
29  %div = sdiv i32 4, %ashr
30  ret i32 %div
31
32}
33
34define i8 @trunc_is_pow2_or_zero(i16 %x, i8 %y) {
35; CHECK-LABEL: define i8 @trunc_is_pow2_or_zero
36; CHECK-SAME: (i16 [[X:%.*]], i8 [[Y:%.*]]) {
37; CHECK-NEXT:    [[XP2:%.*]] = shl i16 4, [[X]]
38; CHECK-NEXT:    [[XX:%.*]] = trunc i16 [[XP2]] to i8
39; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[XX]], -1
40; CHECK-NEXT:    [[R:%.*]] = and i8 [[Y]], [[TMP1]]
41; CHECK-NEXT:    ret i8 [[R]]
42;
43  %xp2 = shl i16 4, %x
44  %xx = trunc i16 %xp2 to i8
45
46  %r = urem i8 %y, %xx
47  ret i8 %r
48}
49
50define i8 @trunc_is_pow2_or_zero_fail(i16 %x, i8 %y) {
51; CHECK-LABEL: define i8 @trunc_is_pow2_or_zero_fail
52; CHECK-SAME: (i16 [[X:%.*]], i8 [[Y:%.*]]) {
53; CHECK-NEXT:    [[XP2:%.*]] = shl i16 5, [[X]]
54; CHECK-NEXT:    [[XX:%.*]] = trunc i16 [[XP2]] to i8
55; CHECK-NEXT:    [[R:%.*]] = urem i8 [[Y]], [[XX]]
56; CHECK-NEXT:    ret i8 [[R]]
57;
58  %xp2 = shl i16 5, %x
59  %xx = trunc i16 %xp2 to i8
60
61  %r = urem i8 %y, %xx
62  ret i8 %r
63}
64
65define i1 @trunc_is_pow2_fail(i16 %x, i8 %y) {
66; CHECK-LABEL: define i1 @trunc_is_pow2_fail
67; CHECK-SAME: (i16 [[X:%.*]], i8 [[Y:%.*]]) {
68; CHECK-NEXT:    [[XP2:%.*]] = shl i16 4, [[X]]
69; CHECK-NEXT:    [[XX:%.*]] = trunc i16 [[XP2]] to i8
70; CHECK-NEXT:    [[AND:%.*]] = and i8 [[Y]], [[XX]]
71; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[AND]], [[XX]]
72; CHECK-NEXT:    ret i1 [[R]]
73;
74  %xp2 = shl i16 4, %x
75  %xx = trunc i16 %xp2 to i8
76
77  %and = and i8 %y, %xx
78  %r = icmp eq i8 %and, %xx
79  ret i1 %r
80}
81
82define i16 @bswap_is_pow2_or_zero(i16 %x, i16 %y) {
83; CHECK-LABEL: define i16 @bswap_is_pow2_or_zero
84; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
85; CHECK-NEXT:    [[XP2:%.*]] = shl i16 4, [[X]]
86; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.bswap.i16(i16 [[XP2]])
87; CHECK-NEXT:    [[TMP1:%.*]] = add i16 [[XX]], -1
88; CHECK-NEXT:    [[R:%.*]] = and i16 [[Y]], [[TMP1]]
89; CHECK-NEXT:    ret i16 [[R]]
90;
91  %xp2 = shl i16 4, %x
92  %xx = call i16 @llvm.bswap.i16(i16 %xp2)
93
94  %r = urem i16 %y, %xx
95  ret i16 %r
96}
97
98define i16 @bswap_is_pow2_or_zero_fail(i16 %x, i16 %y) {
99; CHECK-LABEL: define i16 @bswap_is_pow2_or_zero_fail
100; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
101; CHECK-NEXT:    [[XP2:%.*]] = shl i16 5, [[X]]
102; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.bswap.i16(i16 [[XP2]])
103; CHECK-NEXT:    [[R:%.*]] = urem i16 [[Y]], [[XX]]
104; CHECK-NEXT:    ret i16 [[R]]
105;
106  %xp2 = shl i16 5, %x
107  %xx = call i16 @llvm.bswap.i16(i16 %xp2)
108
109  %r = urem i16 %y, %xx
110  ret i16 %r
111}
112
113define i1 @bswap_is_pow2(i16 %x, i16 %y) {
114; CHECK-LABEL: define i1 @bswap_is_pow2
115; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
116; CHECK-NEXT:    [[XP2:%.*]] = shl nuw i16 1, [[X]]
117; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.bswap.i16(i16 [[XP2]])
118; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
119; CHECK-NEXT:    [[R:%.*]] = icmp ne i16 [[AND]], 0
120; CHECK-NEXT:    ret i1 [[R]]
121;
122  %xp2 = shl i16 1, %x
123  %xx = call i16 @llvm.bswap.i16(i16 %xp2)
124
125  %and = and i16 %y, %xx
126  %r = icmp eq i16 %and, %xx
127  ret i1 %r
128}
129
130define i1 @bswap_is_pow2_fail(i16 %x, i16 %y) {
131; CHECK-LABEL: define i1 @bswap_is_pow2_fail
132; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
133; CHECK-NEXT:    [[XP2:%.*]] = shl i16 2, [[X]]
134; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.bswap.i16(i16 [[XP2]])
135; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
136; CHECK-NEXT:    [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
137; CHECK-NEXT:    ret i1 [[R]]
138;
139  %xp2 = shl i16 2, %x
140  %xx = call i16 @llvm.bswap.i16(i16 %xp2)
141
142  %and = and i16 %y, %xx
143  %r = icmp eq i16 %and, %xx
144  ret i1 %r
145}
146
147define i16 @bitreverse_is_pow2_or_zero(i16 %x, i16 %y) {
148; CHECK-LABEL: define i16 @bitreverse_is_pow2_or_zero
149; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
150; CHECK-NEXT:    [[XP2:%.*]] = shl i16 4, [[X]]
151; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.bitreverse.i16(i16 [[XP2]])
152; CHECK-NEXT:    [[TMP1:%.*]] = add nsw i16 [[XX]], -1
153; CHECK-NEXT:    [[R:%.*]] = and i16 [[Y]], [[TMP1]]
154; CHECK-NEXT:    ret i16 [[R]]
155;
156  %xp2 = shl i16 4, %x
157  %xx = call i16 @llvm.bitreverse.i16(i16 %xp2)
158
159  %r = urem i16 %y, %xx
160  ret i16 %r
161}
162
163define i16 @bitreverse_is_pow2_or_zero_fail(i16 %x, i16 %y) {
164; CHECK-LABEL: define i16 @bitreverse_is_pow2_or_zero_fail
165; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
166; CHECK-NEXT:    [[XP2:%.*]] = shl i16 5, [[X]]
167; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.bitreverse.i16(i16 [[XP2]])
168; CHECK-NEXT:    [[R:%.*]] = urem i16 [[Y]], [[XX]]
169; CHECK-NEXT:    ret i16 [[R]]
170;
171  %xp2 = shl i16 5, %x
172  %xx = call i16 @llvm.bitreverse.i16(i16 %xp2)
173
174  %r = urem i16 %y, %xx
175  ret i16 %r
176}
177
178define i1 @bitreverse_is_pow2(i16 %x, i16 %y) {
179; CHECK-LABEL: define i1 @bitreverse_is_pow2
180; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
181; CHECK-NEXT:    [[XP2:%.*]] = shl nuw i16 1, [[X]]
182; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.bitreverse.i16(i16 [[XP2]])
183; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
184; CHECK-NEXT:    [[R:%.*]] = icmp ne i16 [[AND]], 0
185; CHECK-NEXT:    ret i1 [[R]]
186;
187  %xp2 = shl i16 1, %x
188  %xx = call i16 @llvm.bitreverse.i16(i16 %xp2)
189
190  %and = and i16 %y, %xx
191  %r = icmp eq i16 %and, %xx
192  ret i1 %r
193}
194
195define i1 @bitreverse_is_pow2_fail(i16 %x, i16 %y) {
196; CHECK-LABEL: define i1 @bitreverse_is_pow2_fail
197; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
198; CHECK-NEXT:    [[XP2:%.*]] = shl i16 2, [[X]]
199; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.bitreverse.i16(i16 [[XP2]])
200; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
201; CHECK-NEXT:    [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
202; CHECK-NEXT:    ret i1 [[R]]
203;
204  %xp2 = shl i16 2, %x
205  %xx = call i16 @llvm.bitreverse.i16(i16 %xp2)
206
207  %and = and i16 %y, %xx
208  %r = icmp eq i16 %and, %xx
209  ret i1 %r
210}
211
212define i16 @fshl_is_pow2_or_zero(i16 %x, i16 %y, i16 %z) {
213; CHECK-LABEL: define i16 @fshl_is_pow2_or_zero
214; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
215; CHECK-NEXT:    [[XP2:%.*]] = shl i16 4, [[X]]
216; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.fshl.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]])
217; CHECK-NEXT:    [[TMP1:%.*]] = add i16 [[XX]], -1
218; CHECK-NEXT:    [[R:%.*]] = and i16 [[Y]], [[TMP1]]
219; CHECK-NEXT:    ret i16 [[R]]
220;
221  %xp2 = shl i16 4, %x
222  %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z)
223
224  %r = urem i16 %y, %xx
225  ret i16 %r
226}
227
228define i16 @fshl_is_pow2_or_zero_fail_not_rotate(i16 %w, i16 %x, i16 %y, i16 %z) {
229; CHECK-LABEL: define i16 @fshl_is_pow2_or_zero_fail_not_rotate
230; CHECK-SAME: (i16 [[W:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
231; CHECK-NEXT:    [[XP2:%.*]] = shl i16 4, [[X]]
232; CHECK-NEXT:    [[WP2:%.*]] = shl i16 2, [[W]]
233; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.fshl.i16(i16 [[XP2]], i16 [[WP2]], i16 [[Z]])
234; CHECK-NEXT:    [[R:%.*]] = urem i16 [[Y]], [[XX]]
235; CHECK-NEXT:    ret i16 [[R]]
236;
237  %xp2 = shl i16 4, %x
238  %wp2 = shl i16 2, %w
239  %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %wp2, i16 %z)
240
241  %r = urem i16 %y, %xx
242  ret i16 %r
243}
244
245define i16 @fshl_is_pow2_or_zero_fail(i16 %x, i16 %y, i16 %z) {
246; CHECK-LABEL: define i16 @fshl_is_pow2_or_zero_fail
247; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
248; CHECK-NEXT:    [[XP2:%.*]] = shl i16 5, [[X]]
249; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.fshl.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]])
250; CHECK-NEXT:    [[R:%.*]] = urem i16 [[Y]], [[XX]]
251; CHECK-NEXT:    ret i16 [[R]]
252;
253  %xp2 = shl i16 5, %x
254  %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z)
255
256  %r = urem i16 %y, %xx
257  ret i16 %r
258}
259
260define i1 @fshl_is_pow2(i16 %x, i16 %y, i16 %z) {
261; CHECK-LABEL: define i1 @fshl_is_pow2
262; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
263; CHECK-NEXT:    [[XP2:%.*]] = shl nuw i16 1, [[X]]
264; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.fshl.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]])
265; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
266; CHECK-NEXT:    [[R:%.*]] = icmp ne i16 [[AND]], 0
267; CHECK-NEXT:    ret i1 [[R]]
268;
269  %xp2 = shl i16 1, %x
270  %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z)
271
272  %and = and i16 %y, %xx
273  %r = icmp eq i16 %and, %xx
274  ret i1 %r
275}
276
277define i1 @fshl_is_pow2_fail(i16 %x, i16 %y, i16 %z) {
278; CHECK-LABEL: define i1 @fshl_is_pow2_fail
279; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
280; CHECK-NEXT:    [[XP2:%.*]] = shl i16 2, [[X]]
281; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.fshl.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]])
282; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
283; CHECK-NEXT:    [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
284; CHECK-NEXT:    ret i1 [[R]]
285;
286  %xp2 = shl i16 2, %x
287  %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z)
288
289  %and = and i16 %y, %xx
290  %r = icmp eq i16 %and, %xx
291  ret i1 %r
292}
293
294define i16 @fshr_is_pow2_or_zero(i16 %x, i16 %y, i16 %z) {
295; CHECK-LABEL: define i16 @fshr_is_pow2_or_zero
296; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
297; CHECK-NEXT:    [[XP2:%.*]] = shl i16 4, [[X]]
298; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.fshr.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]])
299; CHECK-NEXT:    [[TMP1:%.*]] = add i16 [[XX]], -1
300; CHECK-NEXT:    [[R:%.*]] = and i16 [[Y]], [[TMP1]]
301; CHECK-NEXT:    ret i16 [[R]]
302;
303  %xp2 = shl i16 4, %x
304  %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z)
305
306  %r = urem i16 %y, %xx
307  ret i16 %r
308}
309
310define i16 @fshr_is_pow2_or_zero_fail_not_rotate(i16 %w, i16 %x, i16 %y, i16 %z) {
311; CHECK-LABEL: define i16 @fshr_is_pow2_or_zero_fail_not_rotate
312; CHECK-SAME: (i16 [[W:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
313; CHECK-NEXT:    [[XP2:%.*]] = shl i16 4, [[X]]
314; CHECK-NEXT:    [[WP2:%.*]] = shl i16 2, [[W]]
315; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.fshr.i16(i16 [[XP2]], i16 [[WP2]], i16 [[Z]])
316; CHECK-NEXT:    [[R:%.*]] = urem i16 [[Y]], [[XX]]
317; CHECK-NEXT:    ret i16 [[R]]
318;
319  %xp2 = shl i16 4, %x
320  %wp2 = shl i16 2, %w
321  %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %wp2, i16 %z)
322
323  %r = urem i16 %y, %xx
324  ret i16 %r
325}
326
327define i16 @fshr_is_pow2_or_zero_fail(i16 %x, i16 %y, i16 %z) {
328; CHECK-LABEL: define i16 @fshr_is_pow2_or_zero_fail
329; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
330; CHECK-NEXT:    [[XP2:%.*]] = shl i16 5, [[X]]
331; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.fshr.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]])
332; CHECK-NEXT:    [[R:%.*]] = urem i16 [[Y]], [[XX]]
333; CHECK-NEXT:    ret i16 [[R]]
334;
335  %xp2 = shl i16 5, %x
336  %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z)
337
338  %r = urem i16 %y, %xx
339  ret i16 %r
340}
341
342define i1 @fshr_is_pow2(i16 %x, i16 %y, i16 %z) {
343; CHECK-LABEL: define i1 @fshr_is_pow2
344; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
345; CHECK-NEXT:    [[XP2:%.*]] = shl nuw i16 1, [[X]]
346; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.fshr.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]])
347; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
348; CHECK-NEXT:    [[R:%.*]] = icmp ne i16 [[AND]], 0
349; CHECK-NEXT:    ret i1 [[R]]
350;
351  %xp2 = shl i16 1, %x
352  %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z)
353
354  %and = and i16 %y, %xx
355  %r = icmp eq i16 %and, %xx
356  ret i1 %r
357}
358
359define i1 @fshr_is_pow2_fail(i16 %x, i16 %y, i16 %z) {
360; CHECK-LABEL: define i1 @fshr_is_pow2_fail
361; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
362; CHECK-NEXT:    [[XP2:%.*]] = shl i16 2, [[X]]
363; CHECK-NEXT:    [[XX:%.*]] = call i16 @llvm.fshr.i16(i16 [[XP2]], i16 [[XP2]], i16 [[Z]])
364; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
365; CHECK-NEXT:    [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
366; CHECK-NEXT:    ret i1 [[R]]
367;
368  %xp2 = shl i16 2, %x
369  %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z)
370
371  %and = and i16 %y, %xx
372  %r = icmp eq i16 %and, %xx
373  ret i1 %r
374}
375
376define i16 @mul_is_pow2_or_zero(i16 %x, i16 %y, i16 %z) {
377; CHECK-LABEL: define i16 @mul_is_pow2_or_zero
378; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
379; CHECK-NEXT:    [[XP2:%.*]] = shl i16 4, [[X]]
380; CHECK-NEXT:    [[ZP2:%.*]] = shl i16 2, [[Z]]
381; CHECK-NEXT:    [[XX:%.*]] = mul i16 [[XP2]], [[ZP2]]
382; CHECK-NEXT:    [[TMP1:%.*]] = add i16 [[XX]], -1
383; CHECK-NEXT:    [[R:%.*]] = and i16 [[Y]], [[TMP1]]
384; CHECK-NEXT:    ret i16 [[R]]
385;
386  %xp2 = shl i16 4, %x
387  %zp2 = shl i16 2, %z
388  %xx = mul i16 %xp2, %zp2
389
390  %r = urem i16 %y, %xx
391  ret i16 %r
392}
393
394define i16 @mul_is_pow2_or_zero_fail(i16 %x, i16 %y, i16 %z) {
395; CHECK-LABEL: define i16 @mul_is_pow2_or_zero_fail
396; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
397; CHECK-NEXT:    [[XP2:%.*]] = shl i16 4, [[X]]
398; CHECK-NEXT:    [[ZP2:%.*]] = shl i16 5, [[Z]]
399; CHECK-NEXT:    [[XX:%.*]] = mul i16 [[XP2]], [[ZP2]]
400; CHECK-NEXT:    [[R:%.*]] = urem i16 [[Y]], [[XX]]
401; CHECK-NEXT:    ret i16 [[R]]
402;
403  %xp2 = shl i16 4, %x
404  %zp2 = shl i16 5, %z
405  %xx = mul i16 %xp2, %zp2
406
407  %r = urem i16 %y, %xx
408  ret i16 %r
409}
410
411define i1 @mul_is_pow2(i16 %x, i16 %y, i16 %z) {
412; CHECK-LABEL: define i1 @mul_is_pow2
413; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
414; CHECK-NEXT:    [[XSMALL:%.*]] = and i16 [[X]], 3
415; CHECK-NEXT:    [[ZSMALL:%.*]] = and i16 [[Z]], 3
416; CHECK-NEXT:    [[ZP2:%.*]] = shl nuw nsw i16 2, [[ZSMALL]]
417; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i16 [[XSMALL]], 2
418; CHECK-NEXT:    [[XX:%.*]] = shl nuw nsw i16 [[ZP2]], [[TMP1]]
419; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
420; CHECK-NEXT:    [[R:%.*]] = icmp ne i16 [[AND]], 0
421; CHECK-NEXT:    ret i1 [[R]]
422;
423  %xsmall = and i16 %x, 3
424  %zsmall = and i16 %z, 3
425  %xp2 = shl i16 4, %xsmall
426  %zp2 = shl i16 2, %zsmall
427  %xx = mul i16 %xp2, %zp2
428
429  %and = and i16 %y, %xx
430  %r = icmp eq i16 %and, %xx
431  ret i1 %r
432}
433
434define i1 @mul_is_pow2_fail(i16 %x, i16 %y, i16 %z) {
435; CHECK-LABEL: define i1 @mul_is_pow2_fail
436; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
437; CHECK-NEXT:    [[XSMALL:%.*]] = and i16 [[X]], 7
438; CHECK-NEXT:    [[ZSMALL:%.*]] = and i16 [[Z]], 7
439; CHECK-NEXT:    [[ZP2:%.*]] = shl nuw nsw i16 2, [[ZSMALL]]
440; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i16 [[XSMALL]], 2
441; CHECK-NEXT:    [[XX:%.*]] = shl i16 [[ZP2]], [[TMP1]]
442; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
443; CHECK-NEXT:    [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
444; CHECK-NEXT:    ret i1 [[R]]
445;
446  %xsmall = and i16 %x, 7
447  %zsmall = and i16 %z, 7
448  %xp2 = shl i16 4, %xsmall
449  %zp2 = shl i16 2, %zsmall
450  %xx = mul i16 %xp2, %zp2
451
452  %and = and i16 %y, %xx
453  %r = icmp eq i16 %and, %xx
454  ret i1 %r
455}
456
457define i1 @mul_is_pow2_fail2(i16 %x, i16 %y, i16 %z) {
458; CHECK-LABEL: define i1 @mul_is_pow2_fail2
459; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
460; CHECK-NEXT:    [[XSMALL:%.*]] = and i16 [[X]], 3
461; CHECK-NEXT:    [[ZSMALL:%.*]] = and i16 [[Z]], 3
462; CHECK-NEXT:    [[XP2:%.*]] = shl nuw nsw i16 3, [[XSMALL]]
463; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i16 [[ZSMALL]], 1
464; CHECK-NEXT:    [[XX:%.*]] = shl nuw nsw i16 [[XP2]], [[TMP1]]
465; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
466; CHECK-NEXT:    [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
467; CHECK-NEXT:    ret i1 [[R]]
468;
469  %xsmall = and i16 %x, 3
470  %zsmall = and i16 %z, 3
471  %xp2 = shl i16 3, %xsmall
472  %zp2 = shl i16 2, %zsmall
473  %xx = mul i16 %xp2, %zp2
474
475  %and = and i16 %y, %xx
476  %r = icmp eq i16 %and, %xx
477  ret i1 %r
478}
479
480define i1 @shl_is_pow2(i16 %x, i16 %y) {
481; CHECK-LABEL: define i1 @shl_is_pow2
482; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
483; CHECK-NEXT:    [[XSMALL:%.*]] = and i16 [[X]], 7
484; CHECK-NEXT:    [[XX:%.*]] = shl nuw nsw i16 4, [[XSMALL]]
485; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
486; CHECK-NEXT:    [[R:%.*]] = icmp ne i16 [[AND]], 0
487; CHECK-NEXT:    ret i1 [[R]]
488;
489  %xsmall = and i16 %x, 7
490  %xx = shl i16 4, %xsmall
491
492  %and = and i16 %y, %xx
493  %r = icmp eq i16 %and, %xx
494  ret i1 %r
495}
496
497define i1 @shl_is_pow2_fail(i16 %x, i16 %y) {
498; CHECK-LABEL: define i1 @shl_is_pow2_fail
499; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
500; CHECK-NEXT:    [[XSMALL:%.*]] = and i16 [[X]], 7
501; CHECK-NEXT:    [[XX:%.*]] = shl i16 512, [[XSMALL]]
502; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
503; CHECK-NEXT:    [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
504; CHECK-NEXT:    ret i1 [[R]]
505;
506  %xsmall = and i16 %x, 7
507  %xx = shl i16 512, %xsmall
508
509  %and = and i16 %y, %xx
510  %r = icmp eq i16 %and, %xx
511  ret i1 %r
512}
513
514define i1 @shl_is_pow2_fail2(i16 %x, i16 %y) {
515; CHECK-LABEL: define i1 @shl_is_pow2_fail2
516; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
517; CHECK-NEXT:    [[XSMALL:%.*]] = and i16 [[X]], 7
518; CHECK-NEXT:    [[XX:%.*]] = shl nuw nsw i16 5, [[XSMALL]]
519; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
520; CHECK-NEXT:    [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
521; CHECK-NEXT:    ret i1 [[R]]
522;
523  %xsmall = and i16 %x, 7
524  %xx = shl i16 5, %xsmall
525
526  %and = and i16 %y, %xx
527  %r = icmp eq i16 %and, %xx
528  ret i1 %r
529}
530
531define i1 @lshr_is_pow2(i16 %x, i16 %y) {
532; CHECK-LABEL: define i1 @lshr_is_pow2
533; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
534; CHECK-NEXT:    [[XSMALL:%.*]] = and i16 [[X]], 7
535; CHECK-NEXT:    [[XX:%.*]] = lshr exact i16 512, [[XSMALL]]
536; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
537; CHECK-NEXT:    [[R:%.*]] = icmp ne i16 [[AND]], 0
538; CHECK-NEXT:    ret i1 [[R]]
539;
540  %xsmall = and i16 %x, 7
541  %xx = lshr i16 512, %xsmall
542
543  %and = and i16 %y, %xx
544  %r = icmp eq i16 %and, %xx
545  ret i1 %r
546}
547
548define i1 @lshr_is_pow2_fail(i16 %x, i16 %y) {
549; CHECK-LABEL: define i1 @lshr_is_pow2_fail
550; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
551; CHECK-NEXT:    [[XSMALL:%.*]] = and i16 [[X]], 7
552; CHECK-NEXT:    [[XX:%.*]] = lshr i16 4, [[XSMALL]]
553; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
554; CHECK-NEXT:    [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
555; CHECK-NEXT:    ret i1 [[R]]
556;
557  %xsmall = and i16 %x, 7
558  %xx = lshr i16 4, %xsmall
559
560  %and = and i16 %y, %xx
561  %r = icmp eq i16 %and, %xx
562  ret i1 %r
563}
564
565define i1 @lshr_is_pow2_fail2(i16 %x, i16 %y) {
566; CHECK-LABEL: define i1 @lshr_is_pow2_fail2
567; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
568; CHECK-NEXT:    [[XSMALL:%.*]] = and i16 [[X]], 7
569; CHECK-NEXT:    [[XX:%.*]] = lshr i16 513, [[XSMALL]]
570; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
571; CHECK-NEXT:    [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
572; CHECK-NEXT:    ret i1 [[R]]
573;
574  %xsmall = and i16 %x, 7
575  %xx = lshr i16 513, %xsmall
576
577  %and = and i16 %y, %xx
578  %r = icmp eq i16 %and, %xx
579  ret i1 %r
580}
581
582define i1 @and_is_pow2(i16 %x, i16 %y) {
583; CHECK-LABEL: define i1 @and_is_pow2
584; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
585; CHECK-NEXT:    [[XNZ:%.*]] = or i16 [[X]], 4
586; CHECK-NEXT:    [[X_NEG:%.*]] = sub nsw i16 0, [[XNZ]]
587; CHECK-NEXT:    [[TMP1:%.*]] = and i16 [[Y]], [[X_NEG]]
588; CHECK-NEXT:    [[AND:%.*]] = and i16 [[TMP1]], [[XNZ]]
589; CHECK-NEXT:    [[R:%.*]] = icmp ne i16 [[AND]], 0
590; CHECK-NEXT:    ret i1 [[R]]
591;
592  %xnz = or i16 %x, 4
593  %x_neg = sub i16 0, %xnz
594  %xx = and i16 %xnz, %x_neg
595
596  %and = and i16 %y, %xx
597  %r = icmp eq i16 %and, %xx
598  ret i1 %r
599}
600
601define i1 @and_is_pow2_fail(i16 %x, i16 %y) {
602; CHECK-LABEL: define i1 @and_is_pow2_fail
603; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) {
604; CHECK-NEXT:    [[X_NEG:%.*]] = sub i16 0, [[X]]
605; CHECK-NEXT:    [[XX:%.*]] = and i16 [[X]], [[X_NEG]]
606; CHECK-NEXT:    [[AND:%.*]] = and i16 [[Y]], [[XX]]
607; CHECK-NEXT:    [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
608; CHECK-NEXT:    ret i1 [[R]]
609;
610  %x_neg = sub i16 0, %x
611  %xx = and i16 %x, %x_neg
612
613  %and = and i16 %y, %xx
614  %r = icmp eq i16 %and, %xx
615  ret i1 %r
616}
617
618define i16 @i1_is_pow2_or_zero(i1 %x, i16 %y) {
619; CHECK-LABEL: define i16 @i1_is_pow2_or_zero
620; CHECK-SAME: (i1 [[X:%.*]], i16 [[Y:%.*]]) {
621; CHECK-NEXT:    [[XX:%.*]] = zext i1 [[X]] to i16
622; CHECK-NEXT:    [[R:%.*]] = or i16 [[Y]], [[XX]]
623; CHECK-NEXT:    ret i16 [[R]]
624;
625  %xx = zext i1 %x to i16
626  %yy = xor i16 %y, %xx
627  %r = call i16 @llvm.umax.i16(i16 %yy, i16 %y)
628  ret i16 %r
629}
630
631define i16 @i1_is_pow2_or_zero2(i1 %x, i16 %y0, i16 %z) {
632; CHECK-LABEL: define i16 @i1_is_pow2_or_zero2
633; CHECK-SAME: (i1 [[X:%.*]], i16 [[Y0:%.*]], i16 [[Z:%.*]]) {
634; CHECK-NEXT:    [[XX:%.*]] = zext i1 [[X]] to i16
635; CHECK-NEXT:    [[Y:%.*]] = or i16 [[Y0]], [[Z]]
636; CHECK-NEXT:    [[R:%.*]] = or i16 [[Y]], [[XX]]
637; CHECK-NEXT:    ret i16 [[R]]
638;
639  %xx = zext i1 %x to i16
640  %y = or i16 %y0, %z
641  %yy = xor i16 %y, %xx
642  %r = call i16 @llvm.umax.i16(i16 %yy, i16 %y)
643  ret i16 %r
644}
645