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: [[AND:%.*]] = ashr i32 [[D]], 31
20 ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 4, [[AND]]
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
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 [[TMP1]], [[Y]]
41 ; CHECK-NEXT: ret i8 [[R]]
44 %xx = trunc i16 %xp2 to i8
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]]
59 %xx = trunc i16 %xp2 to i8
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 [[XX]], [[Y]]
71 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[XX]]
72 ; CHECK-NEXT: ret i1 [[R]]
75 %xx = trunc i16 %xp2 to i8
78 %r = icmp eq i8 %and, %xx
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 [[TMP1]], [[Y]]
89 ; CHECK-NEXT: ret i16 [[R]]
92 %xx = call i16 @llvm.bswap.i16(i16 %xp2)
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]]
107 %xx = call i16 @llvm.bswap.i16(i16 %xp2)
109 %r = urem i16 %y, %xx
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 [[XX]], [[Y]]
119 ; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0
120 ; CHECK-NEXT: ret i1 [[R]]
123 %xx = call i16 @llvm.bswap.i16(i16 %xp2)
125 %and = and i16 %y, %xx
126 %r = icmp eq i16 %and, %xx
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 [[XX]], [[Y]]
136 ; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
137 ; CHECK-NEXT: ret i1 [[R]]
140 %xx = call i16 @llvm.bswap.i16(i16 %xp2)
142 %and = and i16 %y, %xx
143 %r = icmp eq i16 %and, %xx
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 [[TMP1]], [[Y]]
154 ; CHECK-NEXT: ret i16 [[R]]
157 %xx = call i16 @llvm.bitreverse.i16(i16 %xp2)
159 %r = urem i16 %y, %xx
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]]
172 %xx = call i16 @llvm.bitreverse.i16(i16 %xp2)
174 %r = urem i16 %y, %xx
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 [[XX]], [[Y]]
184 ; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0
185 ; CHECK-NEXT: ret i1 [[R]]
188 %xx = call i16 @llvm.bitreverse.i16(i16 %xp2)
190 %and = and i16 %y, %xx
191 %r = icmp eq i16 %and, %xx
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 [[XX]], [[Y]]
201 ; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
202 ; CHECK-NEXT: ret i1 [[R]]
205 %xx = call i16 @llvm.bitreverse.i16(i16 %xp2)
207 %and = and i16 %y, %xx
208 %r = icmp eq i16 %and, %xx
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 [[TMP1]], [[Y]]
219 ; CHECK-NEXT: ret i16 [[R]]
222 %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z)
224 %r = urem i16 %y, %xx
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]]
239 %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %wp2, i16 %z)
241 %r = urem i16 %y, %xx
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]]
254 %xx = call i16 @llvm.fshl.i16(i16 %xp2, i16 %xp2, i16 %z)
256 %r = urem i16 %y, %xx
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 [[XX]], [[Y]]
266 ; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0
267 ; CHECK-NEXT: ret i1 [[R]]
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
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 [[XX]], [[Y]]
283 ; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
284 ; CHECK-NEXT: ret i1 [[R]]
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
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 [[TMP1]], [[Y]]
301 ; CHECK-NEXT: ret i16 [[R]]
304 %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z)
306 %r = urem i16 %y, %xx
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]]
321 %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %wp2, i16 %z)
323 %r = urem i16 %y, %xx
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]]
336 %xx = call i16 @llvm.fshr.i16(i16 %xp2, i16 %xp2, i16 %z)
338 %r = urem i16 %y, %xx
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 [[XX]], [[Y]]
348 ; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0
349 ; CHECK-NEXT: ret i1 [[R]]
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
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 [[XX]], [[Y]]
365 ; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]]
366 ; CHECK-NEXT: ret i1 [[R]]
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
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 [[TMP1]], [[Y]]
384 ; CHECK-NEXT: ret i16 [[R]]
388 %xx = mul i16 %xp2, %zp2
390 %r = urem i16 %y, %xx
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]]
405 %xx = mul i16 %xp2, %zp2
407 %r = urem i16 %y, %xx
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 [[XX]], [[Y]]
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
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 [[XX]], [[Y]]
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
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 [[XX]], [[Y]]
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
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 [[XX]], [[Y]]
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
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 [[XX]], [[Y]]
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
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 [[XX]], [[Y]]
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
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 [[XX]], [[Y]]
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
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 [[XX]], [[Y]]
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
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 [[XX]], [[Y]]
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
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 [[X_NEG]], [[Y]]
588 ; CHECK-NEXT: [[AND:%.*]] = and i16 [[TMP1]], [[XNZ]]
589 ; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0
590 ; CHECK-NEXT: ret i1 [[R]]
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
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_NEG]], [[X]]
606 ; CHECK-NEXT: [[AND:%.*]] = and i16 [[XX]], [[Y]]
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
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 [[XX]], [[Y]]
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)
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
641 %yy = xor i16 %y, %xx
642 %r = call i16 @llvm.umax.i16(i16 %yy, i16 %y)