Revert "[InstCombine] Support gep nuw in icmp folds" (#118698)
[llvm-project.git] / llvm / test / Analysis / ValueTracking / known-power-of-two.ll
blob7cfb6af0d7b95d1012ac0b2dcf39e13bbde68176
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
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.
9 declare i16 @llvm.bitreverse.i16(i16)
10 declare i16 @llvm.bswap.i16(i16)
11 declare i16 @llvm.ctpop.i16(i16)
12 declare i16 @llvm.fshl.i16(i16, i16, i16)
13 declare i16 @llvm.fshr.i16(i16, i16, i16)
14 declare i16 @llvm.umax.i16(i16, i16)
16 define 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]]
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
34 define 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]]
43   %xp2 = shl i16 4, %x
44   %xx = trunc i16 %xp2 to i8
46   %r = urem i8 %y, %xx
47   ret i8 %r
50 define 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]]
58   %xp2 = shl i16 5, %x
59   %xx = trunc i16 %xp2 to i8
61   %r = urem i8 %y, %xx
62   ret i8 %r
65 define 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]]
74   %xp2 = shl i16 4, %x
75   %xx = trunc i16 %xp2 to i8
77   %and = and i8 %y, %xx
78   %r = icmp eq i8 %and, %xx
79   ret i1 %r
82 define 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]]
91   %xp2 = shl i16 4, %x
92   %xx = call i16 @llvm.bswap.i16(i16 %xp2)
94   %r = urem i16 %y, %xx
95   ret i16 %r
98 define 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]]
106   %xp2 = shl i16 5, %x
107   %xx = call i16 @llvm.bswap.i16(i16 %xp2)
109   %r = urem i16 %y, %xx
110   ret i16 %r
113 define 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]]
122   %xp2 = shl i16 1, %x
123   %xx = call i16 @llvm.bswap.i16(i16 %xp2)
125   %and = and i16 %y, %xx
126   %r = icmp eq i16 %and, %xx
127   ret i1 %r
130 define 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]]
139   %xp2 = shl i16 2, %x
140   %xx = call i16 @llvm.bswap.i16(i16 %xp2)
142   %and = and i16 %y, %xx
143   %r = icmp eq i16 %and, %xx
144   ret i1 %r
147 define 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]]
156   %xp2 = shl i16 4, %x
157   %xx = call i16 @llvm.bitreverse.i16(i16 %xp2)
159   %r = urem i16 %y, %xx
160   ret i16 %r
163 define 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]]
171   %xp2 = shl i16 5, %x
172   %xx = call i16 @llvm.bitreverse.i16(i16 %xp2)
174   %r = urem i16 %y, %xx
175   ret i16 %r
178 define 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]]
187   %xp2 = shl i16 1, %x
188   %xx = call i16 @llvm.bitreverse.i16(i16 %xp2)
190   %and = and i16 %y, %xx
191   %r = icmp eq i16 %and, %xx
192   ret i1 %r
195 define 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]]
204   %xp2 = shl i16 2, %x
205   %xx = call i16 @llvm.bitreverse.i16(i16 %xp2)
207   %and = and i16 %y, %xx
208   %r = icmp eq i16 %and, %xx
209   ret i1 %r
212 define 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]]
221   %xp2 = shl i16 4, %x
222   %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z)
224   %r = urem i16 %y, %xx
225   ret i16 %r
228 define 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]]
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)
241   %r = urem i16 %y, %xx
242   ret i16 %r
245 define 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]]
253   %xp2 = shl i16 5, %x
254   %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z)
256   %r = urem i16 %y, %xx
257   ret i16 %r
260 define 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]]
269   %xp2 = shl i16 1, %x
270   %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z)
272   %and = and i16 %y, %xx
273   %r = icmp eq i16 %and, %xx
274   ret i1 %r
277 define 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]]
286   %xp2 = shl i16 2, %x
287   %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z)
289   %and = and i16 %y, %xx
290   %r = icmp eq i16 %and, %xx
291   ret i1 %r
294 define 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]]
303   %xp2 = shl i16 4, %x
304   %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z)
306   %r = urem i16 %y, %xx
307   ret i16 %r
310 define 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]]
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)
323   %r = urem i16 %y, %xx
324   ret i16 %r
327 define 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]]
335   %xp2 = shl i16 5, %x
336   %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z)
338   %r = urem i16 %y, %xx
339   ret i16 %r
342 define 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]]
351   %xp2 = shl i16 1, %x
352   %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z)
354   %and = and i16 %y, %xx
355   %r = icmp eq i16 %and, %xx
356   ret i1 %r
359 define 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]]
368   %xp2 = shl i16 2, %x
369   %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z)
371   %and = and i16 %y, %xx
372   %r = icmp eq i16 %and, %xx
373   ret i1 %r
376 define 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]]
386   %xp2 = shl i16 4, %x
387   %zp2 = shl i16 2, %z
388   %xx = mul i16 %xp2, %zp2
390   %r = urem i16 %y, %xx
391   ret i16 %r
394 define 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]]
403   %xp2 = shl i16 4, %x
404   %zp2 = shl i16 5, %z
405   %xx = mul i16 %xp2, %zp2
407   %r = urem i16 %y, %xx
408   ret i16 %r
411 define 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]]
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
429   %and = and i16 %y, %xx
430   %r = icmp eq i16 %and, %xx
431   ret i1 %r
434 define 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]]
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
452   %and = and i16 %y, %xx
453   %r = icmp eq i16 %and, %xx
454   ret i1 %r
457 define 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]]
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
475   %and = and i16 %y, %xx
476   %r = icmp eq i16 %and, %xx
477   ret i1 %r
480 define 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]]
489   %xsmall = and i16 %x, 7
490   %xx = shl i16 4, %xsmall
492   %and = and i16 %y, %xx
493   %r = icmp eq i16 %and, %xx
494   ret i1 %r
497 define 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]]
506   %xsmall = and i16 %x, 7
507   %xx = shl i16 512, %xsmall
509   %and = and i16 %y, %xx
510   %r = icmp eq i16 %and, %xx
511   ret i1 %r
514 define 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]]
523   %xsmall = and i16 %x, 7
524   %xx = shl i16 5, %xsmall
526   %and = and i16 %y, %xx
527   %r = icmp eq i16 %and, %xx
528   ret i1 %r
531 define 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]]
540   %xsmall = and i16 %x, 7
541   %xx = lshr i16 512, %xsmall
543   %and = and i16 %y, %xx
544   %r = icmp eq i16 %and, %xx
545   ret i1 %r
548 define 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]]
557   %xsmall = and i16 %x, 7
558   %xx = lshr i16 4, %xsmall
560   %and = and i16 %y, %xx
561   %r = icmp eq i16 %and, %xx
562   ret i1 %r
565 define 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]]
574   %xsmall = and i16 %x, 7
575   %xx = lshr i16 513, %xsmall
577   %and = and i16 %y, %xx
578   %r = icmp eq i16 %and, %xx
579   ret i1 %r
582 define 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]]
592   %xnz = or i16 %x, 4
593   %x_neg = sub i16 0, %xnz
594   %xx = and i16 %xnz, %x_neg
596   %and = and i16 %y, %xx
597   %r = icmp eq i16 %and, %xx
598   ret i1 %r
601 define 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]]
610   %x_neg = sub i16 0, %x
611   %xx = and i16 %x, %x_neg
613   %and = and i16 %y, %xx
614   %r = icmp eq i16 %and, %xx
615   ret i1 %r
618 define 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]]
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
631 define 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]]
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