1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=instcombine -S < %s | FileCheck %s
4 target datalayout = "e-m:e-i64:64-n8:16:32:64"
6 declare i32 @llvm.bswap.i32(i32)
7 declare i128 @llvm.bswap.i128(i128)
8 declare <2 x i64> @llvm.bswap.v2i64(<2 x i64>)
9 declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone
10 declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone
11 declare i32 @llvm.ctpop.i32(i32) nounwind readnone
12 declare <2 x i8> @llvm.cttz.v2i8(<2 x i8>, i1) nounwind readnone
13 declare <2 x i8> @llvm.ctlz.v2i8(<2 x i8>, i1) nounwind readnone
14 declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) nounwind readnone
16 declare void @use(i32)
17 declare void @usevec(<3 x i14>)
19 define i32 @lshr_ctlz_zero_is_not_undef(i32 %x) {
20 ; CHECK-LABEL: @lshr_ctlz_zero_is_not_undef(
21 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0
22 ; CHECK-NEXT: [[SH:%.*]] = zext i1 [[TMP1]] to i32
23 ; CHECK-NEXT: ret i32 [[SH]]
25 %ct = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
30 define i32 @lshr_cttz_zero_is_not_undef(i32 %x) {
31 ; CHECK-LABEL: @lshr_cttz_zero_is_not_undef(
32 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0
33 ; CHECK-NEXT: [[SH:%.*]] = zext i1 [[TMP1]] to i32
34 ; CHECK-NEXT: ret i32 [[SH]]
36 %ct = call i32 @llvm.cttz.i32(i32 %x, i1 false)
41 define i32 @lshr_ctpop(i32 %x) {
42 ; CHECK-LABEL: @lshr_ctpop(
43 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], -1
44 ; CHECK-NEXT: [[SH:%.*]] = zext i1 [[TMP1]] to i32
45 ; CHECK-NEXT: ret i32 [[SH]]
47 %ct = call i32 @llvm.ctpop.i32(i32 %x)
52 define <2 x i8> @lshr_ctlz_zero_is_not_undef_splat_vec(<2 x i8> %x) {
53 ; CHECK-LABEL: @lshr_ctlz_zero_is_not_undef_splat_vec(
54 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
55 ; CHECK-NEXT: [[SH:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>
56 ; CHECK-NEXT: ret <2 x i8> [[SH]]
58 %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 false)
59 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
63 define <2 x i8> @lshr_cttz_zero_is_not_undef_splat_vec(<2 x i8> %x) {
64 ; CHECK-LABEL: @lshr_cttz_zero_is_not_undef_splat_vec(
65 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
66 ; CHECK-NEXT: [[SH:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>
67 ; CHECK-NEXT: ret <2 x i8> [[SH]]
69 %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 false)
70 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
74 define <2 x i8> @lshr_ctpop_splat_vec(<2 x i8> %x) {
75 ; CHECK-LABEL: @lshr_ctpop_splat_vec(
76 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], splat (i8 -1)
77 ; CHECK-NEXT: [[SH:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>
78 ; CHECK-NEXT: ret <2 x i8> [[SH]]
80 %ct = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
81 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
85 define i32 @lshr_ctlz_zero_is_undef(i32 %x) {
86 ; CHECK-LABEL: @lshr_ctlz_zero_is_undef(
87 ; CHECK-NEXT: ret i32 0
89 %ct = call i32 @llvm.ctlz.i32(i32 %x, i1 true)
94 define i32 @lshr_cttz_zero_is_undef(i32 %x) {
95 ; CHECK-LABEL: @lshr_cttz_zero_is_undef(
96 ; CHECK-NEXT: ret i32 0
98 %ct = call i32 @llvm.cttz.i32(i32 %x, i1 true)
103 define <2 x i8> @lshr_ctlz_zero_is_undef_splat_vec(<2 x i8> %x) {
104 ; CHECK-LABEL: @lshr_ctlz_zero_is_undef_splat_vec(
105 ; CHECK-NEXT: ret <2 x i8> zeroinitializer
107 %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 true)
108 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
112 define i8 @lshr_ctlz_zero_is_undef_vec(<2 x i8> %x) {
113 ; CHECK-LABEL: @lshr_ctlz_zero_is_undef_vec(
114 ; CHECK-NEXT: ret i8 0
116 %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 true)
117 %sh = lshr <2 x i8> %ct, <i8 3, i8 0>
118 %ex = extractelement <2 x i8> %sh, i32 0
122 define <2 x i8> @lshr_cttz_zero_is_undef_splat_vec(<2 x i8> %x) {
123 ; CHECK-LABEL: @lshr_cttz_zero_is_undef_splat_vec(
124 ; CHECK-NEXT: ret <2 x i8> zeroinitializer
126 %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 true)
127 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
131 define i8 @lshr_cttz_zero_is_undef_vec(<2 x i8> %x) {
132 ; CHECK-LABEL: @lshr_cttz_zero_is_undef_vec(
133 ; CHECK-NEXT: ret i8 0
135 %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 true)
136 %sh = lshr <2 x i8> %ct, <i8 3, i8 0>
137 %ex = extractelement <2 x i8> %sh, i32 0
142 define i8 @lshr_exact(i8 %x) {
143 ; CHECK-LABEL: @lshr_exact(
144 ; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X:%.*]], 1
145 ; CHECK-NEXT: [[LSHR:%.*]] = and i8 [[TMP1]], 63
146 ; CHECK-NEXT: ret i8 [[LSHR]]
149 %add = add i8 %shl, 4
150 %lshr = lshr i8 %add, 2
154 define <2 x i8> @lshr_exact_splat_vec(<2 x i8> %x) {
155 ; CHECK-LABEL: @lshr_exact_splat_vec(
156 ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], splat (i8 1)
157 ; CHECK-NEXT: [[LSHR:%.*]] = and <2 x i8> [[TMP1]], splat (i8 63)
158 ; CHECK-NEXT: ret <2 x i8> [[LSHR]]
160 %shl = shl <2 x i8> %x, <i8 2, i8 2>
161 %add = add <2 x i8> %shl, <i8 4, i8 4>
162 %lshr = lshr <2 x i8> %add, <i8 2, i8 2>
166 define <2 x i8> @lshr_exact_splat_vec_nuw(<2 x i8> %x) {
167 ; CHECK-LABEL: @lshr_exact_splat_vec_nuw(
168 ; CHECK-NEXT: [[LSHR:%.*]] = add nuw <2 x i8> [[X:%.*]], splat (i8 1)
169 ; CHECK-NEXT: ret <2 x i8> [[LSHR]]
171 %shl = shl nuw <2 x i8> %x, <i8 2, i8 2>
172 %add = add nuw <2 x i8> %shl, <i8 4, i8 4>
173 %lshr = lshr <2 x i8> %add, <i8 2, i8 2>
177 define i8 @shl_add(i8 %x, i8 %y) {
178 ; CHECK-LABEL: @shl_add(
179 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[Y:%.*]], 2
180 ; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], [[X:%.*]]
181 ; CHECK-NEXT: [[R:%.*]] = and i8 [[TMP2]], 63
182 ; CHECK-NEXT: ret i8 [[R]]
190 define <2 x i8> @shl_add_commute_vec(<2 x i8> %x, <2 x i8> %py) {
191 ; CHECK-LABEL: @shl_add_commute_vec(
192 ; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[PY:%.*]], [[PY]]
193 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i8> [[Y]], splat (i8 3)
194 ; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i8> [[TMP1]], [[X:%.*]]
195 ; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[TMP2]], splat (i8 31)
196 ; CHECK-NEXT: ret <2 x i8> [[R]]
198 %y = mul <2 x i8> %py, %py ; thwart complexity-based canonicalization
199 %l = shl <2 x i8> %x, <i8 3, i8 3>
200 %a = add <2 x i8> %y, %l
201 %r = lshr <2 x i8> %a, <i8 3, i8 3>
205 define i32 @shl_add_use1(i32 %x, i32 %y) {
206 ; CHECK-LABEL: @shl_add_use1(
207 ; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 2
208 ; CHECK-NEXT: call void @use(i32 [[L]])
209 ; CHECK-NEXT: [[A:%.*]] = add i32 [[L]], [[Y:%.*]]
210 ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[A]], 2
211 ; CHECK-NEXT: ret i32 [[R]]
214 call void @use(i32 %l)
220 define i32 @shl_add_use2(i32 %x, i32 %y) {
221 ; CHECK-LABEL: @shl_add_use2(
222 ; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 2
223 ; CHECK-NEXT: [[A:%.*]] = add i32 [[L]], [[Y:%.*]]
224 ; CHECK-NEXT: call void @use(i32 [[A]])
225 ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[A]], 2
226 ; CHECK-NEXT: ret i32 [[R]]
230 call void @use(i32 %a)
235 define i16 @bool_zext(i1 %x) {
236 ; CHECK-LABEL: @bool_zext(
237 ; CHECK-NEXT: [[HIBIT:%.*]] = zext i1 [[X:%.*]] to i16
238 ; CHECK-NEXT: ret i16 [[HIBIT]]
240 %sext = sext i1 %x to i16
241 %hibit = lshr i16 %sext, 15
245 define i32 @bool_zext_use(i1 %x) {
246 ; CHECK-LABEL: @bool_zext_use(
247 ; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[X:%.*]] to i32
248 ; CHECK-NEXT: call void @use(i32 [[SEXT]])
249 ; CHECK-NEXT: [[HIBIT:%.*]] = zext i1 [[X]] to i32
250 ; CHECK-NEXT: ret i32 [[HIBIT]]
252 %sext = sext i1 %x to i32
253 call void @use(i32 %sext)
254 %hibit = lshr i32 %sext, 31
258 define <2 x i8> @bool_zext_splat(<2 x i1> %x) {
259 ; CHECK-LABEL: @bool_zext_splat(
260 ; CHECK-NEXT: [[HIBIT:%.*]] = zext <2 x i1> [[X:%.*]] to <2 x i8>
261 ; CHECK-NEXT: ret <2 x i8> [[HIBIT]]
263 %sext = sext <2 x i1> %x to <2 x i8>
264 %hibit = lshr <2 x i8> %sext, <i8 7, i8 7>
268 define i32 @smear_sign_and_widen(i8 %x) {
269 ; CHECK-LABEL: @smear_sign_and_widen(
270 ; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 [[X:%.*]], 7
271 ; CHECK-NEXT: [[HIBIT:%.*]] = zext i8 [[TMP1]] to i32
272 ; CHECK-NEXT: ret i32 [[HIBIT]]
274 %sext = sext i8 %x to i32
275 %hibit = lshr i32 %sext, 24
279 define i16 @smear_sign_and_widen_should_not_change_type(i4 %x) {
280 ; CHECK-LABEL: @smear_sign_and_widen_should_not_change_type(
281 ; CHECK-NEXT: [[SEXT:%.*]] = sext i4 [[X:%.*]] to i16
282 ; CHECK-NEXT: [[HIBIT:%.*]] = lshr i16 [[SEXT]], 12
283 ; CHECK-NEXT: ret i16 [[HIBIT]]
285 %sext = sext i4 %x to i16
286 %hibit = lshr i16 %sext, 12
290 define <2 x i8> @smear_sign_and_widen_splat(<2 x i6> %x) {
291 ; CHECK-LABEL: @smear_sign_and_widen_splat(
292 ; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i6> [[X:%.*]], splat (i6 2)
293 ; CHECK-NEXT: [[HIBIT:%.*]] = zext <2 x i6> [[TMP1]] to <2 x i8>
294 ; CHECK-NEXT: ret <2 x i8> [[HIBIT]]
296 %sext = sext <2 x i6> %x to <2 x i8>
297 %hibit = lshr <2 x i8> %sext, <i8 2, i8 2>
301 define i18 @fake_sext(i3 %x) {
302 ; CHECK-LABEL: @fake_sext(
303 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i3 [[X:%.*]], 2
304 ; CHECK-NEXT: [[SH:%.*]] = zext nneg i3 [[TMP1]] to i18
305 ; CHECK-NEXT: ret i18 [[SH]]
307 %sext = sext i3 %x to i18
308 %sh = lshr i18 %sext, 17
312 ; Avoid the transform if it would change the shift from a legal to illegal type.
314 define i32 @fake_sext_but_should_not_change_type(i3 %x) {
315 ; CHECK-LABEL: @fake_sext_but_should_not_change_type(
316 ; CHECK-NEXT: [[SEXT:%.*]] = sext i3 [[X:%.*]] to i32
317 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[SEXT]], 31
318 ; CHECK-NEXT: ret i32 [[SH]]
320 %sext = sext i3 %x to i32
321 %sh = lshr i32 %sext, 31
325 define <2 x i8> @fake_sext_splat(<2 x i3> %x) {
326 ; CHECK-LABEL: @fake_sext_splat(
327 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i3> [[X:%.*]], splat (i3 2)
328 ; CHECK-NEXT: [[SH:%.*]] = zext nneg <2 x i3> [[TMP1]] to <2 x i8>
329 ; CHECK-NEXT: ret <2 x i8> [[SH]]
331 %sext = sext <2 x i3> %x to <2 x i8>
332 %sh = lshr <2 x i8> %sext, <i8 7, i8 7>
336 ; Use a narrow shift: lshr (zext iM X to iN), C --> zext (lshr X, C) to iN
338 define <2 x i32> @narrow_lshr_constant(<2 x i8> %x, <2 x i8> %y) {
339 ; CHECK-LABEL: @narrow_lshr_constant(
340 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i8> [[X:%.*]], splat (i8 3)
341 ; CHECK-NEXT: [[SH:%.*]] = zext nneg <2 x i8> [[TMP1]] to <2 x i32>
342 ; CHECK-NEXT: ret <2 x i32> [[SH]]
344 %zx = zext <2 x i8> %x to <2 x i32>
345 %sh = lshr <2 x i32> %zx, <i32 3, i32 3>
349 define i32 @mul_splat_fold(i32 %x) {
350 ; CHECK-LABEL: @mul_splat_fold(
351 ; CHECK-NEXT: ret i32 [[X:%.*]]
353 %m = mul nuw i32 %x, 65537
358 ; Vector type, extra use, weird types are all ok.
360 define <3 x i14> @mul_splat_fold_vec(<3 x i14> %x) {
361 ; CHECK-LABEL: @mul_splat_fold_vec(
362 ; CHECK-NEXT: [[M:%.*]] = mul nuw <3 x i14> [[X:%.*]], splat (i14 129)
363 ; CHECK-NEXT: call void @usevec(<3 x i14> [[M]])
364 ; CHECK-NEXT: ret <3 x i14> [[X]]
366 %m = mul nuw <3 x i14> %x, <i14 129, i14 129, i14 129>
367 call void @usevec(<3 x i14> %m)
368 %t = lshr <3 x i14> %m, <i14 7, i14 7, i14 7>
372 define i32 @shl_add_lshr_flag_preservation(i32 %x, i32 %c, i32 %y) {
373 ; CHECK-LABEL: @shl_add_lshr_flag_preservation(
374 ; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]
375 ; CHECK-NEXT: [[LSHR:%.*]] = add nuw nsw i32 [[TMP1]], [[X:%.*]]
376 ; CHECK-NEXT: ret i32 [[LSHR]]
378 %shl = shl nuw i32 %x, %c
379 %add = add nuw nsw i32 %shl, %y
380 %lshr = lshr exact i32 %add, %c
384 define i32 @shl_add_lshr(i32 %x, i32 %c, i32 %y) {
385 ; CHECK-LABEL: @shl_add_lshr(
386 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]
387 ; CHECK-NEXT: [[LSHR:%.*]] = add nuw i32 [[TMP1]], [[X:%.*]]
388 ; CHECK-NEXT: ret i32 [[LSHR]]
390 %shl = shl nuw i32 %x, %c
391 %add = add nuw i32 %shl, %y
392 %lshr = lshr i32 %add, %c
396 define i32 @shl_add_lshr_comm(i32 %x, i32 %c, i32 %y) {
397 ; CHECK-LABEL: @shl_add_lshr_comm(
398 ; CHECK-NEXT: [[Y2:%.*]] = mul i32 [[Y:%.*]], [[Y]]
399 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y2]], [[C:%.*]]
400 ; CHECK-NEXT: [[LSHR:%.*]] = add nuw i32 [[TMP1]], [[X:%.*]]
401 ; CHECK-NEXT: ret i32 [[LSHR]]
403 %shl = shl nuw i32 %x, %c
404 %y2 = mul i32 %y, %y ; thwart complexity-based canonicalization
405 %add = add nuw i32 %y2, %shl
406 %lshr = lshr i32 %add, %c
412 define i32 @shl_add_lshr_no_nuw(i32 %x, i32 %c, i32 %y) {
413 ; CHECK-LABEL: @shl_add_lshr_no_nuw(
414 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
415 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SHL]], [[Y:%.*]]
416 ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[ADD]], [[C]]
417 ; CHECK-NEXT: ret i32 [[LSHR]]
419 %shl = shl nuw i32 %x, %c
420 %add = add i32 %shl, %y
421 %lshr = lshr i32 %add, %c
427 define i32 @shl_sub_lshr_not_exact(i32 %x, i32 %c, i32 %y) {
428 ; CHECK-LABEL: @shl_sub_lshr_not_exact(
429 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
430 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[SHL]], [[Y:%.*]]
431 ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[SUB]], [[C]]
432 ; CHECK-NEXT: ret i32 [[LSHR]]
434 %shl = shl nuw i32 %x, %c
435 %sub = sub nuw i32 %shl, %y
436 %lshr = lshr i32 %sub, %c
442 define i32 @shl_sub_lshr_no_nuw(i32 %x, i32 %c, i32 %y) {
443 ; CHECK-LABEL: @shl_sub_lshr_no_nuw(
444 ; CHECK-NEXT: [[SHL:%.*]] = shl nsw i32 [[X:%.*]], [[C:%.*]]
445 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[SHL]], [[Y:%.*]]
446 ; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]
447 ; CHECK-NEXT: ret i32 [[LSHR]]
449 %shl = shl nsw i32 %x, %c
450 %sub = sub nsw i32 %shl, %y
451 %lshr = lshr exact i32 %sub, %c
455 define i32 @shl_sub_lshr(i32 %x, i32 %c, i32 %y) {
456 ; CHECK-LABEL: @shl_sub_lshr(
457 ; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]
458 ; CHECK-NEXT: [[LSHR:%.*]] = sub nuw nsw i32 [[X:%.*]], [[TMP1]]
459 ; CHECK-NEXT: ret i32 [[LSHR]]
461 %shl = shl nuw i32 %x, %c
462 %sub = sub nuw nsw i32 %shl, %y
463 %lshr = lshr exact i32 %sub, %c
467 define i32 @shl_sub_lshr_reverse(i32 %x, i32 %c, i32 %y) {
468 ; CHECK-LABEL: @shl_sub_lshr_reverse(
469 ; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]
470 ; CHECK-NEXT: [[LSHR:%.*]] = sub nuw nsw i32 [[TMP1]], [[X:%.*]]
471 ; CHECK-NEXT: ret i32 [[LSHR]]
473 %shl = shl nuw i32 %x, %c
474 %sub = sub nuw nsw i32 %y, %shl
475 %lshr = lshr exact i32 %sub, %c
479 define i32 @shl_sub_lshr_reverse_no_nsw(i32 %x, i32 %c, i32 %y) {
480 ; CHECK-LABEL: @shl_sub_lshr_reverse_no_nsw(
481 ; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]
482 ; CHECK-NEXT: [[LSHR:%.*]] = sub nuw i32 [[TMP1]], [[X:%.*]]
483 ; CHECK-NEXT: ret i32 [[LSHR]]
485 %shl = shl nuw i32 %x, %c
486 %sub = sub nuw i32 %y, %shl
487 %lshr = lshr exact i32 %sub, %c
491 define i32 @shl_sub_lshr_reverse_nsw_on_op1(i32 %x, i32 %c, i32 %y) {
492 ; CHECK-LABEL: @shl_sub_lshr_reverse_nsw_on_op1(
493 ; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]
494 ; CHECK-NEXT: [[LSHR:%.*]] = sub nuw i32 [[TMP1]], [[X:%.*]]
495 ; CHECK-NEXT: ret i32 [[LSHR]]
497 %shl = shl nuw nsw i32 %x, %c
498 %sub = sub nuw i32 %y, %shl
499 %lshr = lshr exact i32 %sub, %c
505 define i32 @shl_sub_lshr_reverse_no_exact(i32 %x, i32 %c, i32 %y) {
506 ; CHECK-LABEL: @shl_sub_lshr_reverse_no_exact(
507 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
508 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[Y:%.*]], [[SHL]]
509 ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[SUB]], [[C]]
510 ; CHECK-NEXT: ret i32 [[LSHR]]
512 %shl = shl nuw i32 %x, %c
513 %sub = sub nuw nsw i32 %y, %shl
514 %lshr = lshr i32 %sub, %c
520 define i32 @shl_sub_lshr_reverse_multiuse(i32 %x, i32 %c, i32 %y) {
521 ; CHECK-LABEL: @shl_sub_lshr_reverse_multiuse(
522 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
523 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[Y:%.*]], [[SHL]]
524 ; CHECK-NEXT: call void @use(i32 [[SUB]])
525 ; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]
526 ; CHECK-NEXT: ret i32 [[LSHR]]
528 %shl = shl nuw i32 %x, %c
529 %sub = sub nuw i32 %y, %shl
530 call void @use(i32 %sub)
531 %lshr = lshr exact i32 %sub, %c
535 define i32 @shl_sub_lshr_reverse_multiuse2(i32 %x, i32 %c, i32 %y) {
536 ; CHECK-LABEL: @shl_sub_lshr_reverse_multiuse2(
537 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
538 ; CHECK-NEXT: call void @use(i32 [[SHL]])
539 ; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C]]
540 ; CHECK-NEXT: [[LSHR:%.*]] = sub nuw i32 [[TMP1]], [[X]]
541 ; CHECK-NEXT: ret i32 [[LSHR]]
543 %shl = shl nuw i32 %x, %c
544 call void @use(i32 %shl)
545 %sub = sub nuw i32 %y, %shl
546 %lshr = lshr exact i32 %sub, %c
552 define i32 @shl_sub_lshr_reverse_no_nuw(i32 %x, i32 %c, i32 %y) {
553 ; CHECK-LABEL: @shl_sub_lshr_reverse_no_nuw(
554 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], [[C:%.*]]
555 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[Y:%.*]], [[SHL]]
556 ; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]
557 ; CHECK-NEXT: ret i32 [[LSHR]]
559 %shl = shl i32 %x, %c
560 %sub = sub nuw i32 %y, %shl
561 %lshr = lshr exact i32 %sub, %c
567 define i32 @shl_sub_lshr_reverse_no_nsw_2(i32 %x, i32 %c, i32 %y) {
568 ; CHECK-LABEL: @shl_sub_lshr_reverse_no_nsw_2(
569 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[X:%.*]], [[C:%.*]]
570 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[Y:%.*]], [[SHL]]
571 ; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]
572 ; CHECK-NEXT: ret i32 [[LSHR]]
574 %shl = shl nuw nsw i32 %x, %c
575 %sub = sub i32 %y, %shl
576 %lshr = lshr exact i32 %sub, %c
580 define i32 @shl_or_lshr(i32 %x, i32 %c, i32 %y) {
581 ; CHECK-LABEL: @shl_or_lshr(
582 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]
583 ; CHECK-NEXT: [[LSHR:%.*]] = or i32 [[TMP1]], [[X:%.*]]
584 ; CHECK-NEXT: ret i32 [[LSHR]]
586 %shl = shl nuw i32 %x, %c
587 %or = or i32 %shl, %y
588 %lshr = lshr i32 %or, %c
592 define i32 @shl_or_disjoint_lshr(i32 %x, i32 %c, i32 %y) {
593 ; CHECK-LABEL: @shl_or_disjoint_lshr(
594 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]
595 ; CHECK-NEXT: [[LSHR:%.*]] = or disjoint i32 [[TMP1]], [[X:%.*]]
596 ; CHECK-NEXT: ret i32 [[LSHR]]
598 %shl = shl nuw i32 %x, %c
599 %or = or disjoint i32 %shl, %y
600 %lshr = lshr i32 %or, %c
604 define i32 @shl_or_lshr_comm(i32 %x, i32 %c, i32 %y) {
605 ; CHECK-LABEL: @shl_or_lshr_comm(
606 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]
607 ; CHECK-NEXT: [[LSHR:%.*]] = or i32 [[TMP1]], [[X:%.*]]
608 ; CHECK-NEXT: ret i32 [[LSHR]]
610 %shl = shl nuw i32 %x, %c
611 %or = or i32 %y, %shl
612 %lshr = lshr i32 %or, %c
616 define i32 @shl_or_disjoint_lshr_comm(i32 %x, i32 %c, i32 %y) {
617 ; CHECK-LABEL: @shl_or_disjoint_lshr_comm(
618 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]
619 ; CHECK-NEXT: [[LSHR:%.*]] = or disjoint i32 [[TMP1]], [[X:%.*]]
620 ; CHECK-NEXT: ret i32 [[LSHR]]
622 %shl = shl nuw i32 %x, %c
623 %or = or disjoint i32 %y, %shl
624 %lshr = lshr i32 %or, %c
628 define i32 @shl_xor_lshr(i32 %x, i32 %c, i32 %y) {
629 ; CHECK-LABEL: @shl_xor_lshr(
630 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]
631 ; CHECK-NEXT: [[LSHR:%.*]] = xor i32 [[TMP1]], [[X:%.*]]
632 ; CHECK-NEXT: ret i32 [[LSHR]]
634 %shl = shl nuw i32 %x, %c
635 %xor = xor i32 %shl, %y
636 %lshr = lshr i32 %xor, %c
640 define i32 @shl_xor_lshr_comm(i32 %x, i32 %c, i32 %y) {
641 ; CHECK-LABEL: @shl_xor_lshr_comm(
642 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]
643 ; CHECK-NEXT: [[LSHR:%.*]] = xor i32 [[TMP1]], [[X:%.*]]
644 ; CHECK-NEXT: ret i32 [[LSHR]]
646 %shl = shl nuw i32 %x, %c
647 %xor = xor i32 %y, %shl
648 %lshr = lshr i32 %xor, %c
652 define i32 @shl_and_lshr(i32 %x, i32 %c, i32 %y) {
653 ; CHECK-LABEL: @shl_and_lshr(
654 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]
655 ; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[TMP1]], [[X:%.*]]
656 ; CHECK-NEXT: ret i32 [[LSHR]]
658 %shl = shl nuw i32 %x, %c
659 %and = and i32 %shl, %y
660 %lshr = lshr i32 %and, %c
664 define i32 @shl_and_lshr_comm(i32 %x, i32 %c, i32 %y) {
665 ; CHECK-LABEL: @shl_and_lshr_comm(
666 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]
667 ; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[TMP1]], [[X:%.*]]
668 ; CHECK-NEXT: ret i32 [[LSHR]]
670 %shl = shl nuw i32 %x, %c
671 %and = and i32 %y, %shl
672 %lshr = lshr i32 %and, %c
676 define i32 @shl_lshr_and_exact(i32 %x, i32 %c, i32 %y) {
677 ; CHECK-LABEL: @shl_lshr_and_exact(
678 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]
679 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]]
680 ; CHECK-NEXT: ret i32 [[TMP2]]
682 %2 = shl nuw i32 %x, %c
684 %4 = lshr exact i32 %3, %c
690 define i32 @shl_add_lshr_neg(i32 %x, i32 %y, i32 %z) {
691 ; CHECK-LABEL: @shl_add_lshr_neg(
692 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[Y:%.*]]
693 ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[SHL]], [[Z:%.*]]
694 ; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[ADD]], [[Z]]
695 ; CHECK-NEXT: ret i32 [[RES]]
697 %shl = shl nuw i32 %x, %y
698 %add = add nuw nsw i32 %shl, %z
699 %res = lshr exact i32 %add, %z
703 define i32 @mul_splat_fold_wrong_mul_const(i32 %x) {
704 ; CHECK-LABEL: @mul_splat_fold_wrong_mul_const(
705 ; CHECK-NEXT: [[M:%.*]] = mul nuw i32 [[X:%.*]], 65538
706 ; CHECK-NEXT: [[T:%.*]] = lshr i32 [[M]], 16
707 ; CHECK-NEXT: ret i32 [[T]]
709 %m = mul nuw i32 %x, 65538
716 define i32 @shl_add_lshr_multiuse(i32 %x, i32 %y, i32 %z) {
717 ; CHECK-LABEL: @shl_add_lshr_multiuse(
718 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[Y:%.*]]
719 ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[SHL]], [[Z:%.*]]
720 ; CHECK-NEXT: call void @use(i32 [[ADD]])
721 ; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[ADD]], [[Z]]
722 ; CHECK-NEXT: ret i32 [[RES]]
724 %shl = shl nuw i32 %x, %y
725 %add = add nuw nsw i32 %shl, %z
726 call void @use (i32 %add)
727 %res = lshr exact i32 %add, %z
731 define i32 @mul_splat_fold_wrong_lshr_const(i32 %x) {
732 ; CHECK-LABEL: @mul_splat_fold_wrong_lshr_const(
733 ; CHECK-NEXT: [[M:%.*]] = mul nuw i32 [[X:%.*]], 65537
734 ; CHECK-NEXT: [[T:%.*]] = lshr i32 [[M]], 15
735 ; CHECK-NEXT: ret i32 [[T]]
737 %m = mul nuw i32 %x, 65537
742 define i32 @mul_splat_fold_no_nuw(i32 %x) {
743 ; CHECK-LABEL: @mul_splat_fold_no_nuw(
744 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 16
745 ; CHECK-NEXT: [[T:%.*]] = add nsw i32 [[X]], [[TMP1]]
746 ; CHECK-NEXT: ret i32 [[T]]
748 %m = mul nsw i32 %x, 65537
755 define i32 @mul_splat_fold_no_flags(i32 %x) {
756 ; CHECK-LABEL: @mul_splat_fold_no_flags(
757 ; CHECK-NEXT: [[M:%.*]] = mul i32 [[X:%.*]], 65537
758 ; CHECK-NEXT: [[T:%.*]] = lshr i32 [[M]], 16
759 ; CHECK-NEXT: ret i32 [[T]]
761 %m = mul i32 %x, 65537
766 ; Negative test (but simplifies before we reach the mul_splat transform)- need more than 2 bits
768 define i2 @mul_splat_fold_too_narrow(i2 %x) {
769 ; CHECK-LABEL: @mul_splat_fold_too_narrow(
770 ; CHECK-NEXT: ret i2 [[X:%.*]]
772 %m = mul nuw i2 %x, 2
777 define i32 @negative_and_odd(i32 %x) {
778 ; CHECK-LABEL: @negative_and_odd(
779 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 31
780 ; CHECK-NEXT: [[R:%.*]] = and i32 [[TMP1]], [[X]]
781 ; CHECK-NEXT: ret i32 [[R]]
788 define <2 x i7> @negative_and_odd_vec(<2 x i7> %x) {
789 ; CHECK-LABEL: @negative_and_odd_vec(
790 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i7> [[X:%.*]], splat (i7 6)
791 ; CHECK-NEXT: [[R:%.*]] = and <2 x i7> [[TMP1]], [[X]]
792 ; CHECK-NEXT: ret <2 x i7> [[R]]
794 %s = srem <2 x i7> %x, <i7 2, i7 2>
795 %r = lshr <2 x i7> %s, <i7 6, i7 6>
799 ; Negative test - this is still worth trying to avoid srem?
801 define i32 @negative_and_odd_uses(i32 %x, ptr %p) {
802 ; CHECK-LABEL: @negative_and_odd_uses(
803 ; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 2
804 ; CHECK-NEXT: store i32 [[S]], ptr [[P:%.*]], align 4
805 ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 31
806 ; CHECK-NEXT: ret i32 [[R]]
814 ; Negative test - wrong divisor
816 define i32 @srem3(i32 %x) {
817 ; CHECK-LABEL: @srem3(
818 ; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 3
819 ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 31
820 ; CHECK-NEXT: ret i32 [[R]]
827 ; Negative test - wrong shift amount
829 define i32 @srem2_lshr30(i32 %x) {
830 ; CHECK-LABEL: @srem2_lshr30(
831 ; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 2
832 ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 30
833 ; CHECK-NEXT: ret i32 [[R]]
840 define i12 @trunc_sandwich(i32 %x) {
841 ; CHECK-LABEL: @trunc_sandwich(
842 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 30
843 ; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12
844 ; CHECK-NEXT: ret i12 [[R1]]
846 %sh = lshr i32 %x, 28
847 %tr = trunc i32 %sh to i12
852 define <2 x i12> @trunc_sandwich_splat_vec(<2 x i32> %x) {
853 ; CHECK-LABEL: @trunc_sandwich_splat_vec(
854 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr <2 x i32> [[X:%.*]], splat (i32 30)
855 ; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw <2 x i32> [[SUM_SHIFT]] to <2 x i12>
856 ; CHECK-NEXT: ret <2 x i12> [[R1]]
858 %sh = lshr <2 x i32> %x, <i32 22, i32 22>
859 %tr = trunc <2 x i32> %sh to <2 x i12>
860 %r = lshr <2 x i12> %tr, <i12 8, i12 8>
864 define i12 @trunc_sandwich_min_shift1(i32 %x) {
865 ; CHECK-LABEL: @trunc_sandwich_min_shift1(
866 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 21
867 ; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12
868 ; CHECK-NEXT: ret i12 [[R1]]
870 %sh = lshr i32 %x, 20
871 %tr = trunc i32 %sh to i12
876 define i12 @trunc_sandwich_small_shift1(i32 %x) {
877 ; CHECK-LABEL: @trunc_sandwich_small_shift1(
878 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 20
879 ; CHECK-NEXT: [[R1:%.*]] = trunc nuw i32 [[SUM_SHIFT]] to i12
880 ; CHECK-NEXT: [[R:%.*]] = and i12 [[R1]], 2047
881 ; CHECK-NEXT: ret i12 [[R]]
883 %sh = lshr i32 %x, 19
884 %tr = trunc i32 %sh to i12
889 define i12 @trunc_sandwich_max_sum_shift(i32 %x) {
890 ; CHECK-LABEL: @trunc_sandwich_max_sum_shift(
891 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 31
892 ; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12
893 ; CHECK-NEXT: ret i12 [[R1]]
895 %sh = lshr i32 %x, 20
896 %tr = trunc i32 %sh to i12
897 %r = lshr i12 %tr, 11
901 define i12 @trunc_sandwich_max_sum_shift2(i32 %x) {
902 ; CHECK-LABEL: @trunc_sandwich_max_sum_shift2(
903 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 31
904 ; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12
905 ; CHECK-NEXT: ret i12 [[R1]]
907 %sh = lshr i32 %x, 30
908 %tr = trunc i32 %sh to i12
913 define i12 @trunc_sandwich_big_sum_shift1(i32 %x) {
914 ; CHECK-LABEL: @trunc_sandwich_big_sum_shift1(
915 ; CHECK-NEXT: ret i12 0
917 %sh = lshr i32 %x, 21
918 %tr = trunc i32 %sh to i12
919 %r = lshr i12 %tr, 11
923 define i12 @trunc_sandwich_big_sum_shift2(i32 %x) {
924 ; CHECK-LABEL: @trunc_sandwich_big_sum_shift2(
925 ; CHECK-NEXT: ret i12 0
927 %sh = lshr i32 %x, 31
928 %tr = trunc i32 %sh to i12
933 define i12 @trunc_sandwich_use1(i32 %x) {
934 ; CHECK-LABEL: @trunc_sandwich_use1(
935 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 28
936 ; CHECK-NEXT: call void @use(i32 [[SH]])
937 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 30
938 ; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12
939 ; CHECK-NEXT: ret i12 [[R1]]
941 %sh = lshr i32 %x, 28
942 call void @use(i32 %sh)
943 %tr = trunc i32 %sh to i12
948 define <3 x i9> @trunc_sandwich_splat_vec_use1(<3 x i14> %x) {
949 ; CHECK-LABEL: @trunc_sandwich_splat_vec_use1(
950 ; CHECK-NEXT: [[SH:%.*]] = lshr <3 x i14> [[X:%.*]], splat (i14 6)
951 ; CHECK-NEXT: call void @usevec(<3 x i14> [[SH]])
952 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr <3 x i14> [[X]], splat (i14 11)
953 ; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw <3 x i14> [[SUM_SHIFT]] to <3 x i9>
954 ; CHECK-NEXT: ret <3 x i9> [[R1]]
956 %sh = lshr <3 x i14> %x, <i14 6, i14 6, i14 6>
957 call void @usevec(<3 x i14> %sh)
958 %tr = trunc <3 x i14> %sh to <3 x i9>
959 %r = lshr <3 x i9> %tr, <i9 5, i9 5, i9 5>
963 define i12 @trunc_sandwich_min_shift1_use1(i32 %x) {
964 ; CHECK-LABEL: @trunc_sandwich_min_shift1_use1(
965 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 20
966 ; CHECK-NEXT: call void @use(i32 [[SH]])
967 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 21
968 ; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12
969 ; CHECK-NEXT: ret i12 [[R1]]
971 %sh = lshr i32 %x, 20
972 call void @use(i32 %sh)
973 %tr = trunc i32 %sh to i12
978 ; negative test - trunc is bigger than first shift
980 define i12 @trunc_sandwich_small_shift1_use1(i32 %x) {
981 ; CHECK-LABEL: @trunc_sandwich_small_shift1_use1(
982 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 19
983 ; CHECK-NEXT: call void @use(i32 [[SH]])
984 ; CHECK-NEXT: [[TR:%.*]] = trunc i32 [[SH]] to i12
985 ; CHECK-NEXT: [[R:%.*]] = lshr i12 [[TR]], 1
986 ; CHECK-NEXT: ret i12 [[R]]
988 %sh = lshr i32 %x, 19
989 call void @use(i32 %sh)
990 %tr = trunc i32 %sh to i12
995 define i12 @trunc_sandwich_max_sum_shift_use1(i32 %x) {
996 ; CHECK-LABEL: @trunc_sandwich_max_sum_shift_use1(
997 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 20
998 ; CHECK-NEXT: call void @use(i32 [[SH]])
999 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 31
1000 ; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12
1001 ; CHECK-NEXT: ret i12 [[R1]]
1003 %sh = lshr i32 %x, 20
1004 call void @use(i32 %sh)
1005 %tr = trunc i32 %sh to i12
1006 %r = lshr i12 %tr, 11
1010 define i12 @trunc_sandwich_max_sum_shift2_use1(i32 %x) {
1011 ; CHECK-LABEL: @trunc_sandwich_max_sum_shift2_use1(
1012 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 30
1013 ; CHECK-NEXT: call void @use(i32 [[SH]])
1014 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 31
1015 ; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12
1016 ; CHECK-NEXT: ret i12 [[R1]]
1018 %sh = lshr i32 %x, 30
1019 call void @use(i32 %sh)
1020 %tr = trunc i32 %sh to i12
1021 %r = lshr i12 %tr, 1
1025 ; negative test - but overshift is simplified to zero by another fold
1027 define i12 @trunc_sandwich_big_sum_shift1_use1(i32 %x) {
1028 ; CHECK-LABEL: @trunc_sandwich_big_sum_shift1_use1(
1029 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 21
1030 ; CHECK-NEXT: call void @use(i32 [[SH]])
1031 ; CHECK-NEXT: ret i12 0
1033 %sh = lshr i32 %x, 21
1034 call void @use(i32 %sh)
1035 %tr = trunc i32 %sh to i12
1036 %r = lshr i12 %tr, 11
1040 ; negative test - but overshift is simplified to zero by another fold
1042 define i12 @trunc_sandwich_big_sum_shift2_use1(i32 %x) {
1043 ; CHECK-LABEL: @trunc_sandwich_big_sum_shift2_use1(
1044 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 31
1045 ; CHECK-NEXT: call void @use(i32 [[SH]])
1046 ; CHECK-NEXT: ret i12 0
1048 %sh = lshr i32 %x, 31
1049 call void @use(i32 %sh)
1050 %tr = trunc i32 %sh to i12
1051 %r = lshr i12 %tr, 1
1055 define i16 @lshr_sext_i1_to_i16(i1 %a) {
1056 ; CHECK-LABEL: @lshr_sext_i1_to_i16(
1057 ; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A:%.*]], i16 4095, i16 0
1058 ; CHECK-NEXT: ret i16 [[LSHR]]
1060 %sext = sext i1 %a to i16
1061 %lshr = lshr i16 %sext, 4
1065 define i128 @lshr_sext_i1_to_i128(i1 %a) {
1066 ; CHECK-LABEL: @lshr_sext_i1_to_i128(
1067 ; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A:%.*]], i128 77371252455336267181195263, i128 0
1068 ; CHECK-NEXT: ret i128 [[LSHR]]
1070 %sext = sext i1 %a to i128
1071 %lshr = lshr i128 %sext, 42
1075 define i32 @lshr_sext_i1_to_i32_use(i1 %a) {
1076 ; CHECK-LABEL: @lshr_sext_i1_to_i32_use(
1077 ; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[A:%.*]] to i32
1078 ; CHECK-NEXT: call void @use(i32 [[SEXT]])
1079 ; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A]], i32 262143, i32 0
1080 ; CHECK-NEXT: ret i32 [[LSHR]]
1082 %sext = sext i1 %a to i32
1083 call void @use(i32 %sext)
1084 %lshr = lshr i32 %sext, 14
1088 define <3 x i14> @lshr_sext_i1_to_i14_splat_vec_use1(<3 x i1> %a) {
1089 ; CHECK-LABEL: @lshr_sext_i1_to_i14_splat_vec_use1(
1090 ; CHECK-NEXT: [[SEXT:%.*]] = sext <3 x i1> [[A:%.*]] to <3 x i14>
1091 ; CHECK-NEXT: call void @usevec(<3 x i14> [[SEXT]])
1092 ; CHECK-NEXT: [[LSHR:%.*]] = select <3 x i1> [[A]], <3 x i14> splat (i14 1023), <3 x i14> zeroinitializer
1093 ; CHECK-NEXT: ret <3 x i14> [[LSHR]]
1095 %sext = sext <3 x i1> %a to <3 x i14>
1096 call void @usevec(<3 x i14> %sext)
1097 %lshr = lshr <3 x i14> %sext, <i14 4, i14 4, i14 4>
1101 define i1 @icmp_ule(i32 %x, i32 %y) {
1102 ; CHECK-LABEL: @icmp_ule(
1103 ; CHECK-NEXT: ret i1 true
1105 %x.shifted = lshr i32 %x, %y
1106 %cmp = icmp ule i32 %x.shifted, %x
1110 define i1 @icmp_ult(i32 %x, i32 %y) {
1111 ; CHECK-LABEL: @icmp_ult(
1112 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
1113 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X_SHIFTED]], [[X]]
1114 ; CHECK-NEXT: ret i1 [[CMP]]
1116 %x.shifted = lshr i32 %x, %y
1117 %cmp = icmp ult i32 %x.shifted, %x
1121 define i1 @icmp_eq(i32 %x, i32 %y) {
1122 ; CHECK-LABEL: @icmp_eq(
1123 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
1124 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X_SHIFTED]], [[X]]
1125 ; CHECK-NEXT: ret i1 [[CMP]]
1127 %x.shifted = lshr i32 %x, %y
1128 %cmp = icmp eq i32 %x.shifted, %x
1132 define i1 @icmp_ne(i32 %x, i32 %y) {
1133 ; CHECK-LABEL: @icmp_ne(
1134 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
1135 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X_SHIFTED]], [[X]]
1136 ; CHECK-NEXT: ret i1 [[CMP]]
1138 %x.shifted = lshr i32 %x, %y
1139 %cmp = icmp ne i32 %x.shifted, %x
1143 define i1 @icmp_ugt(i32 %x, i32 %y) {
1144 ; CHECK-LABEL: @icmp_ugt(
1145 ; CHECK-NEXT: ret i1 false
1147 %x.shifted = lshr i32 %x, %y
1148 %cmp = icmp ugt i32 %x.shifted, %x
1152 define i1 @icmp_uge(i32 %x, i32 %y) {
1153 ; CHECK-LABEL: @icmp_uge(
1154 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
1155 ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[X_SHIFTED]], [[X]]
1156 ; CHECK-NEXT: ret i1 [[CMP]]
1158 %x.shifted = lshr i32 %x, %y
1159 %cmp = icmp uge i32 %x.shifted, %x
1163 define i1 @icmp_sle(i32 %x, i32 %y) {
1164 ; CHECK-LABEL: @icmp_sle(
1165 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
1166 ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[X_SHIFTED]], [[X]]
1167 ; CHECK-NEXT: ret i1 [[CMP]]
1169 %x.shifted = lshr i32 %x, %y
1170 %cmp = icmp sle i32 %x.shifted, %x
1174 define i1 @icmp_slt(i32 %x, i32 %y) {
1175 ; CHECK-LABEL: @icmp_slt(
1176 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
1177 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X_SHIFTED]], [[X]]
1178 ; CHECK-NEXT: ret i1 [[CMP]]
1180 %x.shifted = lshr i32 %x, %y
1181 %cmp = icmp slt i32 %x.shifted, %x
1185 define i1 @icmp_sgt(i32 %x, i32 %y) {
1186 ; CHECK-LABEL: @icmp_sgt(
1187 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
1188 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X_SHIFTED]], [[X]]
1189 ; CHECK-NEXT: ret i1 [[CMP]]
1191 %x.shifted = lshr i32 %x, %y
1192 %cmp = icmp sgt i32 %x.shifted, %x
1196 define i1 @icmp_sge(i32 %x, i32 %y) {
1197 ; CHECK-LABEL: @icmp_sge(
1198 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
1199 ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X_SHIFTED]], [[X]]
1200 ; CHECK-NEXT: ret i1 [[CMP]]
1202 %x.shifted = lshr i32 %x, %y
1203 %cmp = icmp sge i32 %x.shifted, %x
1207 define i32 @narrow_bswap(i16 %x) {
1208 ; CHECK-LABEL: @narrow_bswap(
1209 ; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.bswap.i16(i16 [[X:%.*]])
1210 ; CHECK-NEXT: [[S:%.*]] = zext i16 [[TMP1]] to i32
1211 ; CHECK-NEXT: ret i32 [[S]]
1213 %z = zext i16 %x to i32
1214 %b = call i32 @llvm.bswap.i32(i32 %z)
1215 %s = lshr i32 %b, 16
1219 define i128 @narrow_bswap_extra_wide(i16 %x) {
1220 ; CHECK-LABEL: @narrow_bswap_extra_wide(
1221 ; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.bswap.i16(i16 [[X:%.*]])
1222 ; CHECK-NEXT: [[S:%.*]] = zext i16 [[TMP1]] to i128
1223 ; CHECK-NEXT: ret i128 [[S]]
1225 %z = zext i16 %x to i128
1226 %b = call i128 @llvm.bswap.i128(i128 %z)
1227 %s = lshr i128 %b, 112
1231 define i32 @narrow_bswap_undershift(i16 %x) {
1232 ; CHECK-LABEL: @narrow_bswap_undershift(
1233 ; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.bswap.i16(i16 [[X:%.*]])
1234 ; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[TMP1]] to i32
1235 ; CHECK-NEXT: [[S:%.*]] = shl nuw nsw i32 [[TMP2]], 7
1236 ; CHECK-NEXT: ret i32 [[S]]
1238 %z = zext i16 %x to i32
1239 %b = call i32 @llvm.bswap.i32(i32 %z)
1244 define <2 x i64> @narrow_bswap_splat(<2 x i16> %x) {
1245 ; CHECK-LABEL: @narrow_bswap_splat(
1246 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i16> @llvm.bswap.v2i16(<2 x i16> [[X:%.*]])
1247 ; CHECK-NEXT: [[S:%.*]] = zext <2 x i16> [[TMP1]] to <2 x i64>
1248 ; CHECK-NEXT: ret <2 x i64> [[S]]
1250 %z = zext <2 x i16> %x to <2 x i64>
1251 %b = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> %z)
1252 %s = lshr <2 x i64> %b, <i64 48, i64 48>
1256 define <2 x i64> @narrow_bswap_splat_poison_elt(<2 x i16> %x) {
1257 ; CHECK-LABEL: @narrow_bswap_splat_poison_elt(
1258 ; CHECK-NEXT: [[Z:%.*]] = zext <2 x i16> [[X:%.*]] to <2 x i64>
1259 ; CHECK-NEXT: [[B:%.*]] = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> [[Z]])
1260 ; CHECK-NEXT: [[S:%.*]] = lshr exact <2 x i64> [[B]], <i64 48, i64 poison>
1261 ; CHECK-NEXT: ret <2 x i64> [[S]]
1263 %z = zext <2 x i16> %x to <2 x i64>
1264 %b = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> %z)
1265 %s = lshr <2 x i64> %b, <i64 48, i64 poison>
1269 define <2 x i64> @narrow_bswap_overshift(<2 x i32> %x) {
1270 ; CHECK-LABEL: @narrow_bswap_overshift(
1271 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.bswap.v2i32(<2 x i32> [[X:%.*]])
1272 ; CHECK-NEXT: [[TMP2:%.*]] = lshr <2 x i32> [[TMP1]], splat (i32 16)
1273 ; CHECK-NEXT: [[S:%.*]] = zext nneg <2 x i32> [[TMP2]] to <2 x i64>
1274 ; CHECK-NEXT: ret <2 x i64> [[S]]
1276 %z = zext <2 x i32> %x to <2 x i64>
1277 %b = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> %z)
1278 %s = lshr <2 x i64> %b, <i64 48, i64 48>
1282 define i128 @narrow_bswap_overshift2(i96 %x) {
1283 ; CHECK-LABEL: @narrow_bswap_overshift2(
1284 ; CHECK-NEXT: [[TMP1:%.*]] = call i96 @llvm.bswap.i96(i96 [[X:%.*]])
1285 ; CHECK-NEXT: [[TMP2:%.*]] = lshr i96 [[TMP1]], 29
1286 ; CHECK-NEXT: [[S:%.*]] = zext nneg i96 [[TMP2]] to i128
1287 ; CHECK-NEXT: ret i128 [[S]]
1289 %z = zext i96 %x to i128
1290 %b = call i128 @llvm.bswap.i128(i128 %z)
1291 %s = lshr i128 %b, 61
1295 ; negative test - can't make a bswap with an odd number of bytes
1297 define i32 @not_narrow_bswap(i24 %x) {
1298 ; CHECK-LABEL: @not_narrow_bswap(
1299 ; CHECK-NEXT: [[Z:%.*]] = zext i24 [[X:%.*]] to i32
1300 ; CHECK-NEXT: [[B:%.*]] = call i32 @llvm.bswap.i32(i32 [[Z]])
1301 ; CHECK-NEXT: [[R:%.*]] = lshr exact i32 [[B]], 8
1302 ; CHECK-NEXT: ret i32 [[R]]
1304 %z = zext i24 %x to i32
1305 %b = call i32 @llvm.bswap.i32(i32 %z)
1310 define i8 @not_signbit(i8 %x) {
1311 ; CHECK-LABEL: @not_signbit(
1312 ; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
1313 ; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i8
1314 ; CHECK-NEXT: ret i8 [[R]]
1321 define <2 x i6> @not_signbit_vec(<2 x i6> %x) {
1322 ; CHECK-LABEL: @not_signbit_vec(
1323 ; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt <2 x i6> [[X:%.*]], splat (i6 -1)
1324 ; CHECK-NEXT: [[R:%.*]] = zext <2 x i1> [[ISNOTNEG]] to <2 x i6>
1325 ; CHECK-NEXT: ret <2 x i6> [[R]]
1327 %a = xor <2 x i6> %x, <i6 -1, i6 poison>
1328 %r = lshr <2 x i6> %a, <i6 5, i6 poison>
1332 define i8 @not_signbit_alt_xor(i8 %x) {
1333 ; CHECK-LABEL: @not_signbit_alt_xor(
1334 ; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
1335 ; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i8
1336 ; CHECK-NEXT: ret i8 [[R]]
1343 define i8 @not_not_signbit(i8 %x) {
1344 ; CHECK-LABEL: @not_not_signbit(
1345 ; CHECK-NEXT: [[A:%.*]] = xor i8 [[X:%.*]], -1
1346 ; CHECK-NEXT: [[R:%.*]] = lshr i8 [[A]], 6
1347 ; CHECK-NEXT: ret i8 [[R]]
1354 define i32 @not_signbit_use(i32 %x) {
1355 ; CHECK-LABEL: @not_signbit_use(
1356 ; CHECK-NEXT: [[A:%.*]] = xor i32 [[X:%.*]], -1
1357 ; CHECK-NEXT: call void @use(i32 [[A]])
1358 ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[A]], 31
1359 ; CHECK-NEXT: ret i32 [[R]]
1362 call void @use(i32 %a)
1363 %r = lshr i32 %a, 31
1367 define i32 @not_signbit_zext(i16 %x) {
1368 ; CHECK-LABEL: @not_signbit_zext(
1369 ; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i16 [[X:%.*]], -1
1370 ; CHECK-NEXT: [[R2:%.*]] = zext i1 [[ISNOTNEG]] to i32
1371 ; CHECK-NEXT: ret i32 [[R2]]
1374 %r = lshr i16 %a, 15
1375 %r2 = zext i16 %r to i32
1379 define i8 @not_signbit_trunc(i16 %x) {
1380 ; CHECK-LABEL: @not_signbit_trunc(
1381 ; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i16 [[X:%.*]], -1
1382 ; CHECK-NEXT: [[R2:%.*]] = zext i1 [[ISNOTNEG]] to i8
1383 ; CHECK-NEXT: ret i8 [[R2]]
1386 %r = lshr i16 %a, 15
1387 %r2 = trunc i16 %r to i8
1391 define i2 @bool_add_lshr(i1 %a, i1 %b) {
1392 ; CHECK-LABEL: @bool_add_lshr(
1393 ; CHECK-NEXT: [[LSHR1:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
1394 ; CHECK-NEXT: [[LSHR:%.*]] = zext i1 [[LSHR1]] to i2
1395 ; CHECK-NEXT: ret i2 [[LSHR]]
1397 %zext.a = zext i1 %a to i2
1398 %zext.b = zext i1 %b to i2
1399 %add = add i2 %zext.a, %zext.b
1400 %lshr = lshr i2 %add, 1
1404 ; negative test - need bools
1406 define i4 @not_bool_add_lshr(i2 %a, i2 %b) {
1407 ; CHECK-LABEL: @not_bool_add_lshr(
1408 ; CHECK-NEXT: [[TMP1:%.*]] = xor i2 [[A:%.*]], -1
1409 ; CHECK-NEXT: [[ADD_NARROWED_OVERFLOW:%.*]] = icmp ugt i2 [[B:%.*]], [[TMP1]]
1410 ; CHECK-NEXT: [[LSHR:%.*]] = zext i1 [[ADD_NARROWED_OVERFLOW]] to i4
1411 ; CHECK-NEXT: ret i4 [[LSHR]]
1413 %zext.a = zext i2 %a to i4
1414 %zext.b = zext i2 %b to i4
1415 %add = add i4 %zext.a, %zext.b
1416 %lshr = lshr i4 %add, 2
1420 ; TODO: This could be sext(and a, b).
1422 define i2 @bool_add_ashr(i1 %a, i1 %b) {
1423 ; CHECK-LABEL: @bool_add_ashr(
1424 ; CHECK-NEXT: [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i2
1425 ; CHECK-NEXT: [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i2
1426 ; CHECK-NEXT: [[ADD:%.*]] = add nuw i2 [[ZEXT_A]], [[ZEXT_B]]
1427 ; CHECK-NEXT: [[ASHR:%.*]] = ashr i2 [[ADD]], 1
1428 ; CHECK-NEXT: ret i2 [[ASHR]]
1430 %zext.a = zext i1 %a to i2
1431 %zext.b = zext i1 %b to i2
1432 %add = add i2 %zext.a, %zext.b
1433 %ashr = ashr i2 %add, 1
1437 define <2 x i8> @bool_add_lshr_vec(<2 x i1> %a, <2 x i1> %b) {
1438 ; CHECK-LABEL: @bool_add_lshr_vec(
1439 ; CHECK-NEXT: [[LSHR1:%.*]] = and <2 x i1> [[A:%.*]], [[B:%.*]]
1440 ; CHECK-NEXT: [[LSHR:%.*]] = zext <2 x i1> [[LSHR1]] to <2 x i8>
1441 ; CHECK-NEXT: ret <2 x i8> [[LSHR]]
1443 %zext.a = zext <2 x i1> %a to <2 x i8>
1444 %zext.b = zext <2 x i1> %b to <2 x i8>
1445 %add = add <2 x i8> %zext.a, %zext.b
1446 %lshr = lshr <2 x i8> %add, <i8 1, i8 1>
1450 define i32 @bool_add_lshr_uses(i1 %a, i1 %b) {
1451 ; CHECK-LABEL: @bool_add_lshr_uses(
1452 ; CHECK-NEXT: [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i32
1453 ; CHECK-NEXT: call void @use(i32 [[ZEXT_A]])
1454 ; CHECK-NEXT: [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i32
1455 ; CHECK-NEXT: call void @use(i32 [[ZEXT_B]])
1456 ; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[ZEXT_A]], [[ZEXT_B]]
1457 ; CHECK-NEXT: ret i32 [[LSHR]]
1459 %zext.a = zext i1 %a to i32
1460 call void @use(i32 %zext.a)
1461 %zext.b = zext i1 %b to i32
1462 call void @use(i32 %zext.b)
1463 %add = add i32 %zext.a, %zext.b
1464 %lshr = lshr i32 %add, 1
1468 define i32 @bool_add_lshr_uses2(i1 %a, i1 %b) {
1469 ; CHECK-LABEL: @bool_add_lshr_uses2(
1470 ; CHECK-NEXT: [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i32
1471 ; CHECK-NEXT: [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i32
1472 ; CHECK-NEXT: call void @use(i32 [[ZEXT_B]])
1473 ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[ZEXT_A]], [[ZEXT_B]]
1474 ; CHECK-NEXT: call void @use(i32 [[ADD]])
1475 ; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[ZEXT_A]], [[ZEXT_B]]
1476 ; CHECK-NEXT: ret i32 [[LSHR]]
1478 %zext.a = zext i1 %a to i32
1479 %zext.b = zext i1 %b to i32
1480 call void @use(i32 %zext.b)
1481 %add = add i32 %zext.a, %zext.b
1482 call void @use(i32 %add)
1483 %lshr = lshr i32 %add, 1
1487 ; negative test - too many extra uses
1489 define i32 @bool_add_lshr_uses3(i1 %a, i1 %b) {
1490 ; CHECK-LABEL: @bool_add_lshr_uses3(
1491 ; CHECK-NEXT: [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i32
1492 ; CHECK-NEXT: call void @use(i32 [[ZEXT_A]])
1493 ; CHECK-NEXT: [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i32
1494 ; CHECK-NEXT: call void @use(i32 [[ZEXT_B]])
1495 ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[ZEXT_A]], [[ZEXT_B]]
1496 ; CHECK-NEXT: call void @use(i32 [[ADD]])
1497 ; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[ZEXT_A]], [[ZEXT_B]]
1498 ; CHECK-NEXT: ret i32 [[LSHR]]
1500 %zext.a = zext i1 %a to i32
1501 call void @use(i32 %zext.a)
1502 %zext.b = zext i1 %b to i32
1503 call void @use(i32 %zext.b)
1504 %add = add i32 %zext.a, %zext.b
1505 call void @use(i32 %add)
1506 %lshr = lshr i32 %add, 1
1512 define <2 x i8> @bool_add_lshr_vec_wrong_shift_amt(<2 x i1> %a, <2 x i1> %b) {
1513 ; CHECK-LABEL: @bool_add_lshr_vec_wrong_shift_amt(
1514 ; CHECK-NEXT: [[ZEXT_A:%.*]] = zext <2 x i1> [[A:%.*]] to <2 x i8>
1515 ; CHECK-NEXT: [[ZEXT_B:%.*]] = zext <2 x i1> [[B:%.*]] to <2 x i8>
1516 ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw <2 x i8> [[ZEXT_A]], [[ZEXT_B]]
1517 ; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i8> [[ADD]], <i8 1, i8 2>
1518 ; CHECK-NEXT: ret <2 x i8> [[LSHR]]
1520 %zext.a = zext <2 x i1> %a to <2 x i8>
1521 %zext.b = zext <2 x i1> %b to <2 x i8>
1522 %add = add <2 x i8> %zext.a, %zext.b
1523 %lshr = lshr <2 x i8> %add, <i8 1, i8 2>
1527 define i32 @lowbits_of_lshr_mul(i64 %x) {
1528 ; CHECK-LABEL: @lowbits_of_lshr_mul(
1529 ; CHECK-NEXT: entry:
1530 ; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[X:%.*]] to i32
1531 ; CHECK-NEXT: [[CONV:%.*]] = mul i32 [[TMP0]], 15
1532 ; CHECK-NEXT: ret i32 [[CONV]]
1535 %mul = mul i64 %x, 64424509440
1536 %shift = lshr i64 %mul, 32
1537 %conv = trunc i64 %shift to i32
1541 define i32 @lowbits_of_lshr_mul_mask(i32 %x) {
1542 ; CHECK-LABEL: @lowbits_of_lshr_mul_mask(
1543 ; CHECK-NEXT: entry:
1544 ; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[X:%.*]], 1600
1545 ; CHECK-NEXT: [[CONV:%.*]] = and i32 [[TMP0]], 32704
1546 ; CHECK-NEXT: ret i32 [[CONV]]
1549 %mul = mul i32 %x, 104857600
1550 %shift = lshr i32 %mul, 16
1551 %conv = and i32 %shift, 32767
1557 define i32 @lowbits_of_lshr_mul_mask_multiuse(i32 %x) {
1558 ; CHECK-LABEL: @lowbits_of_lshr_mul_mask_multiuse(
1559 ; CHECK-NEXT: entry:
1560 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], 104857600
1561 ; CHECK-NEXT: call void @use(i32 [[MUL]])
1562 ; CHECK-NEXT: [[SHIFT:%.*]] = lshr exact i32 [[MUL]], 16
1563 ; CHECK-NEXT: [[CONV:%.*]] = and i32 [[SHIFT]], 32704
1564 ; CHECK-NEXT: ret i32 [[CONV]]
1567 %mul = mul i32 %x, 104857600
1568 call void @use(i32 %mul)
1569 %shift = lshr i32 %mul, 16
1570 %conv = and i32 %shift, 32767
1574 define i32 @lowbits_of_lshr_mul_mask_indivisible(i32 %x) {
1575 ; CHECK-LABEL: @lowbits_of_lshr_mul_mask_indivisible(
1576 ; CHECK-NEXT: entry:
1577 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], 25600
1578 ; CHECK-NEXT: [[SHIFT:%.*]] = lshr i32 [[MUL]], 16
1579 ; CHECK-NEXT: [[CONV:%.*]] = and i32 [[SHIFT]], 32767
1580 ; CHECK-NEXT: ret i32 [[CONV]]
1583 %mul = mul i32 %x, 25600
1584 %shift = lshr i32 %mul, 16
1585 %conv = and i32 %shift, 32767