1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -instcombine -S < %s | FileCheck %s
4 target datalayout = "e-m:e-i64:64-n8:16:32:64"
6 declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone
7 declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone
8 declare i32 @llvm.ctpop.i32(i32) nounwind readnone
9 declare <2 x i8> @llvm.cttz.v2i8(<2 x i8>, i1) nounwind readnone
10 declare <2 x i8> @llvm.ctlz.v2i8(<2 x i8>, i1) nounwind readnone
11 declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) nounwind readnone
13 declare void @use(i32)
14 declare void @usevec(<3 x i14>)
16 define i32 @lshr_ctlz_zero_is_not_undef(i32 %x) {
17 ; CHECK-LABEL: @lshr_ctlz_zero_is_not_undef(
18 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0
19 ; CHECK-NEXT: [[SH:%.*]] = zext i1 [[TMP1]] to i32
20 ; CHECK-NEXT: ret i32 [[SH]]
22 %ct = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
27 define i32 @lshr_cttz_zero_is_not_undef(i32 %x) {
28 ; CHECK-LABEL: @lshr_cttz_zero_is_not_undef(
29 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0
30 ; CHECK-NEXT: [[SH:%.*]] = zext i1 [[TMP1]] to i32
31 ; CHECK-NEXT: ret i32 [[SH]]
33 %ct = call i32 @llvm.cttz.i32(i32 %x, i1 false)
38 define i32 @lshr_ctpop(i32 %x) {
39 ; CHECK-LABEL: @lshr_ctpop(
40 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], -1
41 ; CHECK-NEXT: [[SH:%.*]] = zext i1 [[TMP1]] to i32
42 ; CHECK-NEXT: ret i32 [[SH]]
44 %ct = call i32 @llvm.ctpop.i32(i32 %x)
49 define <2 x i8> @lshr_ctlz_zero_is_not_undef_splat_vec(<2 x i8> %x) {
50 ; CHECK-LABEL: @lshr_ctlz_zero_is_not_undef_splat_vec(
51 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
52 ; CHECK-NEXT: [[SH:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>
53 ; CHECK-NEXT: ret <2 x i8> [[SH]]
55 %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 false)
56 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
60 define <2 x i8> @lshr_cttz_zero_is_not_undef_splat_vec(<2 x i8> %x) {
61 ; CHECK-LABEL: @lshr_cttz_zero_is_not_undef_splat_vec(
62 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
63 ; CHECK-NEXT: [[SH:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>
64 ; CHECK-NEXT: ret <2 x i8> [[SH]]
66 %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 false)
67 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
71 define <2 x i8> @lshr_ctpop_splat_vec(<2 x i8> %x) {
72 ; CHECK-LABEL: @lshr_ctpop_splat_vec(
73 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
74 ; CHECK-NEXT: [[SH:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>
75 ; CHECK-NEXT: ret <2 x i8> [[SH]]
77 %ct = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
78 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
82 define i32 @lshr_ctlz_zero_is_undef(i32 %x) {
83 ; CHECK-LABEL: @lshr_ctlz_zero_is_undef(
84 ; CHECK-NEXT: ret i32 0
86 %ct = call i32 @llvm.ctlz.i32(i32 %x, i1 true)
91 define i32 @lshr_cttz_zero_is_undef(i32 %x) {
92 ; CHECK-LABEL: @lshr_cttz_zero_is_undef(
93 ; CHECK-NEXT: ret i32 0
95 %ct = call i32 @llvm.cttz.i32(i32 %x, i1 true)
100 define <2 x i8> @lshr_ctlz_zero_is_undef_splat_vec(<2 x i8> %x) {
101 ; CHECK-LABEL: @lshr_ctlz_zero_is_undef_splat_vec(
102 ; CHECK-NEXT: ret <2 x i8> zeroinitializer
104 %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 true)
105 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
109 define i8 @lshr_ctlz_zero_is_undef_vec(<2 x i8> %x) {
110 ; CHECK-LABEL: @lshr_ctlz_zero_is_undef_vec(
111 ; CHECK-NEXT: ret i8 0
113 %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 true)
114 %sh = lshr <2 x i8> %ct, <i8 3, i8 0>
115 %ex = extractelement <2 x i8> %sh, i32 0
119 define <2 x i8> @lshr_cttz_zero_is_undef_splat_vec(<2 x i8> %x) {
120 ; CHECK-LABEL: @lshr_cttz_zero_is_undef_splat_vec(
121 ; CHECK-NEXT: ret <2 x i8> zeroinitializer
123 %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 true)
124 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
128 define i8 @lshr_cttz_zero_is_undef_vec(<2 x i8> %x) {
129 ; CHECK-LABEL: @lshr_cttz_zero_is_undef_vec(
130 ; CHECK-NEXT: ret i8 0
132 %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 true)
133 %sh = lshr <2 x i8> %ct, <i8 3, i8 0>
134 %ex = extractelement <2 x i8> %sh, i32 0
139 define i8 @lshr_exact(i8 %x) {
140 ; CHECK-LABEL: @lshr_exact(
141 ; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X:%.*]], 1
142 ; CHECK-NEXT: [[LSHR:%.*]] = and i8 [[TMP1]], 63
143 ; CHECK-NEXT: ret i8 [[LSHR]]
146 %add = add i8 %shl, 4
147 %lshr = lshr i8 %add, 2
151 define <2 x i8> @lshr_exact_splat_vec(<2 x i8> %x) {
152 ; CHECK-LABEL: @lshr_exact_splat_vec(
153 ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 1, i8 1>
154 ; CHECK-NEXT: [[LSHR:%.*]] = and <2 x i8> [[TMP1]], <i8 63, i8 63>
155 ; CHECK-NEXT: ret <2 x i8> [[LSHR]]
157 %shl = shl <2 x i8> %x, <i8 2, i8 2>
158 %add = add <2 x i8> %shl, <i8 4, i8 4>
159 %lshr = lshr <2 x i8> %add, <i8 2, i8 2>
163 define i8 @shl_add(i8 %x, i8 %y) {
164 ; CHECK-LABEL: @shl_add(
165 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[Y:%.*]], 2
166 ; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], [[X:%.*]]
167 ; CHECK-NEXT: [[R:%.*]] = and i8 [[TMP2]], 63
168 ; CHECK-NEXT: ret i8 [[R]]
176 define <2 x i8> @shl_add_commute_vec(<2 x i8> %x, <2 x i8> %py) {
177 ; CHECK-LABEL: @shl_add_commute_vec(
178 ; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[PY:%.*]], [[PY]]
179 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i8> [[Y]], <i8 3, i8 3>
180 ; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i8> [[TMP1]], [[X:%.*]]
181 ; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[TMP2]], <i8 31, i8 31>
182 ; CHECK-NEXT: ret <2 x i8> [[R]]
184 %y = mul <2 x i8> %py, %py ; thwart complexity-based canonicalization
185 %l = shl <2 x i8> %x, <i8 3, i8 3>
186 %a = add <2 x i8> %y, %l
187 %r = lshr <2 x i8> %a, <i8 3, i8 3>
191 define i32 @shl_add_use1(i32 %x, i32 %y) {
192 ; CHECK-LABEL: @shl_add_use1(
193 ; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 2
194 ; CHECK-NEXT: call void @use(i32 [[L]])
195 ; CHECK-NEXT: [[A:%.*]] = add i32 [[L]], [[Y:%.*]]
196 ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[A]], 2
197 ; CHECK-NEXT: ret i32 [[R]]
200 call void @use(i32 %l)
206 define i32 @shl_add_use2(i32 %x, i32 %y) {
207 ; CHECK-LABEL: @shl_add_use2(
208 ; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 2
209 ; CHECK-NEXT: [[A:%.*]] = add i32 [[L]], [[Y:%.*]]
210 ; CHECK-NEXT: call void @use(i32 [[A]])
211 ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[A]], 2
212 ; CHECK-NEXT: ret i32 [[R]]
216 call void @use(i32 %a)
221 define i16 @bool_zext(i1 %x) {
222 ; CHECK-LABEL: @bool_zext(
223 ; CHECK-NEXT: [[HIBIT:%.*]] = zext i1 [[X:%.*]] to i16
224 ; CHECK-NEXT: ret i16 [[HIBIT]]
226 %sext = sext i1 %x to i16
227 %hibit = lshr i16 %sext, 15
231 define i32 @bool_zext_use(i1 %x) {
232 ; CHECK-LABEL: @bool_zext_use(
233 ; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[X:%.*]] to i32
234 ; CHECK-NEXT: call void @use(i32 [[SEXT]])
235 ; CHECK-NEXT: [[HIBIT:%.*]] = zext i1 [[X]] to i32
236 ; CHECK-NEXT: ret i32 [[HIBIT]]
238 %sext = sext i1 %x to i32
239 call void @use(i32 %sext)
240 %hibit = lshr i32 %sext, 31
244 define <2 x i8> @bool_zext_splat(<2 x i1> %x) {
245 ; CHECK-LABEL: @bool_zext_splat(
246 ; CHECK-NEXT: [[HIBIT:%.*]] = zext <2 x i1> [[X:%.*]] to <2 x i8>
247 ; CHECK-NEXT: ret <2 x i8> [[HIBIT]]
249 %sext = sext <2 x i1> %x to <2 x i8>
250 %hibit = lshr <2 x i8> %sext, <i8 7, i8 7>
254 define i32 @smear_sign_and_widen(i8 %x) {
255 ; CHECK-LABEL: @smear_sign_and_widen(
256 ; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 [[X:%.*]], 7
257 ; CHECK-NEXT: [[HIBIT:%.*]] = zext i8 [[TMP1]] to i32
258 ; CHECK-NEXT: ret i32 [[HIBIT]]
260 %sext = sext i8 %x to i32
261 %hibit = lshr i32 %sext, 24
265 define i16 @smear_sign_and_widen_should_not_change_type(i4 %x) {
266 ; CHECK-LABEL: @smear_sign_and_widen_should_not_change_type(
267 ; CHECK-NEXT: [[SEXT:%.*]] = sext i4 [[X:%.*]] to i16
268 ; CHECK-NEXT: [[HIBIT:%.*]] = lshr i16 [[SEXT]], 12
269 ; CHECK-NEXT: ret i16 [[HIBIT]]
271 %sext = sext i4 %x to i16
272 %hibit = lshr i16 %sext, 12
276 define <2 x i8> @smear_sign_and_widen_splat(<2 x i6> %x) {
277 ; CHECK-LABEL: @smear_sign_and_widen_splat(
278 ; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i6> [[X:%.*]], <i6 2, i6 2>
279 ; CHECK-NEXT: [[HIBIT:%.*]] = zext <2 x i6> [[TMP1]] to <2 x i8>
280 ; CHECK-NEXT: ret <2 x i8> [[HIBIT]]
282 %sext = sext <2 x i6> %x to <2 x i8>
283 %hibit = lshr <2 x i8> %sext, <i8 2, i8 2>
287 define i18 @fake_sext(i3 %x) {
288 ; CHECK-LABEL: @fake_sext(
289 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i3 [[X:%.*]], 2
290 ; CHECK-NEXT: [[SH:%.*]] = zext i3 [[TMP1]] to i18
291 ; CHECK-NEXT: ret i18 [[SH]]
293 %sext = sext i3 %x to i18
294 %sh = lshr i18 %sext, 17
298 ; Avoid the transform if it would change the shift from a legal to illegal type.
300 define i32 @fake_sext_but_should_not_change_type(i3 %x) {
301 ; CHECK-LABEL: @fake_sext_but_should_not_change_type(
302 ; CHECK-NEXT: [[SEXT:%.*]] = sext i3 [[X:%.*]] to i32
303 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[SEXT]], 31
304 ; CHECK-NEXT: ret i32 [[SH]]
306 %sext = sext i3 %x to i32
307 %sh = lshr i32 %sext, 31
311 define <2 x i8> @fake_sext_splat(<2 x i3> %x) {
312 ; CHECK-LABEL: @fake_sext_splat(
313 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i3> [[X:%.*]], <i3 2, i3 2>
314 ; CHECK-NEXT: [[SH:%.*]] = zext <2 x i3> [[TMP1]] to <2 x i8>
315 ; CHECK-NEXT: ret <2 x i8> [[SH]]
317 %sext = sext <2 x i3> %x to <2 x i8>
318 %sh = lshr <2 x i8> %sext, <i8 7, i8 7>
322 ; Use a narrow shift: lshr (zext iM X to iN), C --> zext (lshr X, C) to iN
324 define <2 x i32> @narrow_lshr_constant(<2 x i8> %x, <2 x i8> %y) {
325 ; CHECK-LABEL: @narrow_lshr_constant(
326 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 3, i8 3>
327 ; CHECK-NEXT: [[SH:%.*]] = zext <2 x i8> [[TMP1]] to <2 x i32>
328 ; CHECK-NEXT: ret <2 x i32> [[SH]]
330 %zx = zext <2 x i8> %x to <2 x i32>
331 %sh = lshr <2 x i32> %zx, <i32 3, i32 3>
335 define i32 @mul_splat_fold(i32 %x) {
336 ; CHECK-LABEL: @mul_splat_fold(
337 ; CHECK-NEXT: [[T:%.*]] = and i32 [[X:%.*]], 65535
338 ; CHECK-NEXT: ret i32 [[T]]
340 %m = mul nuw i32 %x, 65537
345 ; Vector type, extra use, weird types are all ok.
347 define <3 x i14> @mul_splat_fold_vec(<3 x i14> %x) {
348 ; CHECK-LABEL: @mul_splat_fold_vec(
349 ; CHECK-NEXT: [[M:%.*]] = mul nuw <3 x i14> [[X:%.*]], <i14 129, i14 129, i14 129>
350 ; CHECK-NEXT: call void @usevec(<3 x i14> [[M]])
351 ; CHECK-NEXT: [[T:%.*]] = and <3 x i14> [[X]], <i14 127, i14 127, i14 127>
352 ; CHECK-NEXT: ret <3 x i14> [[T]]
354 %m = mul nuw <3 x i14> %x, <i14 129, i14 129, i14 129>
355 call void @usevec(<3 x i14> %m)
356 %t = lshr <3 x i14> %m, <i14 7, i14 7, i14 7>
362 define i32 @mul_splat_fold_wrong_mul_const(i32 %x) {
363 ; CHECK-LABEL: @mul_splat_fold_wrong_mul_const(
364 ; CHECK-NEXT: [[M:%.*]] = mul nuw i32 [[X:%.*]], 65538
365 ; CHECK-NEXT: [[T:%.*]] = lshr i32 [[M]], 16
366 ; CHECK-NEXT: ret i32 [[T]]
368 %m = mul nuw i32 %x, 65538
375 define i32 @mul_splat_fold_wrong_lshr_const(i32 %x) {
376 ; CHECK-LABEL: @mul_splat_fold_wrong_lshr_const(
377 ; CHECK-NEXT: [[M:%.*]] = mul nuw i32 [[X:%.*]], 65537
378 ; CHECK-NEXT: [[T:%.*]] = lshr i32 [[M]], 15
379 ; CHECK-NEXT: ret i32 [[T]]
381 %m = mul nuw i32 %x, 65537
388 define i32 @mul_splat_fold_no_nuw(i32 %x) {
389 ; CHECK-LABEL: @mul_splat_fold_no_nuw(
390 ; CHECK-NEXT: [[M:%.*]] = mul nsw i32 [[X:%.*]], 65537
391 ; CHECK-NEXT: [[T:%.*]] = lshr i32 [[M]], 16
392 ; CHECK-NEXT: ret i32 [[T]]
394 %m = mul nsw i32 %x, 65537
399 define i32 @negative_and_odd(i32 %x) {
400 ; CHECK-LABEL: @negative_and_odd(
401 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 31
402 ; CHECK-NEXT: [[R:%.*]] = and i32 [[TMP1]], [[X]]
403 ; CHECK-NEXT: ret i32 [[R]]
410 define <2 x i7> @negative_and_odd_vec(<2 x i7> %x) {
411 ; CHECK-LABEL: @negative_and_odd_vec(
412 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i7> [[X:%.*]], <i7 6, i7 6>
413 ; CHECK-NEXT: [[R:%.*]] = and <2 x i7> [[TMP1]], [[X]]
414 ; CHECK-NEXT: ret <2 x i7> [[R]]
416 %s = srem <2 x i7> %x, <i7 2, i7 2>
417 %r = lshr <2 x i7> %s, <i7 6, i7 6>
421 ; Negative test - this is still worth trying to avoid srem?
423 define i32 @negative_and_odd_uses(i32 %x, i32* %p) {
424 ; CHECK-LABEL: @negative_and_odd_uses(
425 ; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 2
426 ; CHECK-NEXT: store i32 [[S]], i32* [[P:%.*]], align 4
427 ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 31
428 ; CHECK-NEXT: ret i32 [[R]]
431 store i32 %s, i32* %p
436 ; Negative test - wrong divisor
438 define i32 @srem3(i32 %x) {
439 ; CHECK-LABEL: @srem3(
440 ; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 3
441 ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 31
442 ; CHECK-NEXT: ret i32 [[R]]
449 ; Negative test - wrong shift amount
451 define i32 @srem2_lshr30(i32 %x) {
452 ; CHECK-LABEL: @srem2_lshr30(
453 ; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 2
454 ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 30
455 ; CHECK-NEXT: ret i32 [[R]]
462 define i12 @trunc_sandwich(i32 %x) {
463 ; CHECK-LABEL: @trunc_sandwich(
464 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 30
465 ; CHECK-NEXT: [[R1:%.*]] = trunc i32 [[SUM_SHIFT]] to i12
466 ; CHECK-NEXT: ret i12 [[R1]]
468 %sh = lshr i32 %x, 28
469 %tr = trunc i32 %sh to i12
474 define <2 x i12> @trunc_sandwich_splat_vec(<2 x i32> %x) {
475 ; CHECK-LABEL: @trunc_sandwich_splat_vec(
476 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 30, i32 30>
477 ; CHECK-NEXT: [[R1:%.*]] = trunc <2 x i32> [[SUM_SHIFT]] to <2 x i12>
478 ; CHECK-NEXT: ret <2 x i12> [[R1]]
480 %sh = lshr <2 x i32> %x, <i32 22, i32 22>
481 %tr = trunc <2 x i32> %sh to <2 x i12>
482 %r = lshr <2 x i12> %tr, <i12 8, i12 8>
486 define i12 @trunc_sandwich_min_shift1(i32 %x) {
487 ; CHECK-LABEL: @trunc_sandwich_min_shift1(
488 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 21
489 ; CHECK-NEXT: [[R1:%.*]] = trunc i32 [[SUM_SHIFT]] to i12
490 ; CHECK-NEXT: ret i12 [[R1]]
492 %sh = lshr i32 %x, 20
493 %tr = trunc i32 %sh to i12
498 define i12 @trunc_sandwich_small_shift1(i32 %x) {
499 ; CHECK-LABEL: @trunc_sandwich_small_shift1(
500 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 20
501 ; CHECK-NEXT: [[R1:%.*]] = trunc i32 [[SUM_SHIFT]] to i12
502 ; CHECK-NEXT: [[R:%.*]] = and i12 [[R1]], 2047
503 ; CHECK-NEXT: ret i12 [[R]]
505 %sh = lshr i32 %x, 19
506 %tr = trunc i32 %sh to i12
511 define i12 @trunc_sandwich_max_sum_shift(i32 %x) {
512 ; CHECK-LABEL: @trunc_sandwich_max_sum_shift(
513 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 31
514 ; CHECK-NEXT: [[R1:%.*]] = trunc i32 [[SUM_SHIFT]] to i12
515 ; CHECK-NEXT: ret i12 [[R1]]
517 %sh = lshr i32 %x, 20
518 %tr = trunc i32 %sh to i12
519 %r = lshr i12 %tr, 11
523 define i12 @trunc_sandwich_max_sum_shift2(i32 %x) {
524 ; CHECK-LABEL: @trunc_sandwich_max_sum_shift2(
525 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 31
526 ; CHECK-NEXT: [[R1:%.*]] = trunc i32 [[SUM_SHIFT]] to i12
527 ; CHECK-NEXT: ret i12 [[R1]]
529 %sh = lshr i32 %x, 30
530 %tr = trunc i32 %sh to i12
535 define i12 @trunc_sandwich_big_sum_shift1(i32 %x) {
536 ; CHECK-LABEL: @trunc_sandwich_big_sum_shift1(
537 ; CHECK-NEXT: ret i12 0
539 %sh = lshr i32 %x, 21
540 %tr = trunc i32 %sh to i12
541 %r = lshr i12 %tr, 11
545 define i12 @trunc_sandwich_big_sum_shift2(i32 %x) {
546 ; CHECK-LABEL: @trunc_sandwich_big_sum_shift2(
547 ; CHECK-NEXT: ret i12 0
549 %sh = lshr i32 %x, 31
550 %tr = trunc i32 %sh to i12
555 define i12 @trunc_sandwich_use1(i32 %x) {
556 ; CHECK-LABEL: @trunc_sandwich_use1(
557 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 28
558 ; CHECK-NEXT: call void @use(i32 [[SH]])
559 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 30
560 ; CHECK-NEXT: [[R1:%.*]] = trunc i32 [[SUM_SHIFT]] to i12
561 ; CHECK-NEXT: ret i12 [[R1]]
563 %sh = lshr i32 %x, 28
564 call void @use(i32 %sh)
565 %tr = trunc i32 %sh to i12
570 define <3 x i9> @trunc_sandwich_splat_vec_use1(<3 x i14> %x) {
571 ; CHECK-LABEL: @trunc_sandwich_splat_vec_use1(
572 ; CHECK-NEXT: [[SH:%.*]] = lshr <3 x i14> [[X:%.*]], <i14 6, i14 6, i14 6>
573 ; CHECK-NEXT: call void @usevec(<3 x i14> [[SH]])
574 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr <3 x i14> [[X]], <i14 11, i14 11, i14 11>
575 ; CHECK-NEXT: [[R1:%.*]] = trunc <3 x i14> [[SUM_SHIFT]] to <3 x i9>
576 ; CHECK-NEXT: ret <3 x i9> [[R1]]
578 %sh = lshr <3 x i14> %x, <i14 6, i14 6, i14 6>
579 call void @usevec(<3 x i14> %sh)
580 %tr = trunc <3 x i14> %sh to <3 x i9>
581 %r = lshr <3 x i9> %tr, <i9 5, i9 5, i9 5>
585 define i12 @trunc_sandwich_min_shift1_use1(i32 %x) {
586 ; CHECK-LABEL: @trunc_sandwich_min_shift1_use1(
587 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 20
588 ; CHECK-NEXT: call void @use(i32 [[SH]])
589 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 21
590 ; CHECK-NEXT: [[R1:%.*]] = trunc i32 [[SUM_SHIFT]] to i12
591 ; CHECK-NEXT: ret i12 [[R1]]
593 %sh = lshr i32 %x, 20
594 call void @use(i32 %sh)
595 %tr = trunc i32 %sh to i12
600 ; negative test - trunc is bigger than first shift
602 define i12 @trunc_sandwich_small_shift1_use1(i32 %x) {
603 ; CHECK-LABEL: @trunc_sandwich_small_shift1_use1(
604 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 19
605 ; CHECK-NEXT: call void @use(i32 [[SH]])
606 ; CHECK-NEXT: [[TR:%.*]] = trunc i32 [[SH]] to i12
607 ; CHECK-NEXT: [[R:%.*]] = lshr i12 [[TR]], 1
608 ; CHECK-NEXT: ret i12 [[R]]
610 %sh = lshr i32 %x, 19
611 call void @use(i32 %sh)
612 %tr = trunc i32 %sh to i12
617 define i12 @trunc_sandwich_max_sum_shift_use1(i32 %x) {
618 ; CHECK-LABEL: @trunc_sandwich_max_sum_shift_use1(
619 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 20
620 ; CHECK-NEXT: call void @use(i32 [[SH]])
621 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 31
622 ; CHECK-NEXT: [[R1:%.*]] = trunc i32 [[SUM_SHIFT]] to i12
623 ; CHECK-NEXT: ret i12 [[R1]]
625 %sh = lshr i32 %x, 20
626 call void @use(i32 %sh)
627 %tr = trunc i32 %sh to i12
628 %r = lshr i12 %tr, 11
632 define i12 @trunc_sandwich_max_sum_shift2_use1(i32 %x) {
633 ; CHECK-LABEL: @trunc_sandwich_max_sum_shift2_use1(
634 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 30
635 ; CHECK-NEXT: call void @use(i32 [[SH]])
636 ; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 31
637 ; CHECK-NEXT: [[R1:%.*]] = trunc i32 [[SUM_SHIFT]] to i12
638 ; CHECK-NEXT: ret i12 [[R1]]
640 %sh = lshr i32 %x, 30
641 call void @use(i32 %sh)
642 %tr = trunc i32 %sh to i12
647 ; negative test - but overshift is simplified to zero by another fold
649 define i12 @trunc_sandwich_big_sum_shift1_use1(i32 %x) {
650 ; CHECK-LABEL: @trunc_sandwich_big_sum_shift1_use1(
651 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 21
652 ; CHECK-NEXT: call void @use(i32 [[SH]])
653 ; CHECK-NEXT: ret i12 0
655 %sh = lshr i32 %x, 21
656 call void @use(i32 %sh)
657 %tr = trunc i32 %sh to i12
658 %r = lshr i12 %tr, 11
662 ; negative test - but overshift is simplified to zero by another fold
664 define i12 @trunc_sandwich_big_sum_shift2_use1(i32 %x) {
665 ; CHECK-LABEL: @trunc_sandwich_big_sum_shift2_use1(
666 ; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 31
667 ; CHECK-NEXT: call void @use(i32 [[SH]])
668 ; CHECK-NEXT: ret i12 0
670 %sh = lshr i32 %x, 31
671 call void @use(i32 %sh)
672 %tr = trunc i32 %sh to i12
677 define i16 @lshr_sext_i1_to_i16(i1 %a) {
678 ; CHECK-LABEL: @lshr_sext_i1_to_i16(
679 ; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A:%.*]], i16 4095, i16 0
680 ; CHECK-NEXT: ret i16 [[LSHR]]
682 %sext = sext i1 %a to i16
683 %lshr = lshr i16 %sext, 4
687 define i128 @lshr_sext_i1_to_i128(i1 %a) {
688 ; CHECK-LABEL: @lshr_sext_i1_to_i128(
689 ; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A:%.*]], i128 77371252455336267181195263, i128 0
690 ; CHECK-NEXT: ret i128 [[LSHR]]
692 %sext = sext i1 %a to i128
693 %lshr = lshr i128 %sext, 42
697 define i32 @lshr_sext_i1_to_i32_use(i1 %a) {
698 ; CHECK-LABEL: @lshr_sext_i1_to_i32_use(
699 ; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[A:%.*]] to i32
700 ; CHECK-NEXT: call void @use(i32 [[SEXT]])
701 ; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A]], i32 262143, i32 0
702 ; CHECK-NEXT: ret i32 [[LSHR]]
704 %sext = sext i1 %a to i32
705 call void @use(i32 %sext)
706 %lshr = lshr i32 %sext, 14
710 define <3 x i14> @lshr_sext_i1_to_i14_splat_vec_use1(<3 x i1> %a) {
711 ; CHECK-LABEL: @lshr_sext_i1_to_i14_splat_vec_use1(
712 ; CHECK-NEXT: [[SEXT:%.*]] = sext <3 x i1> [[A:%.*]] to <3 x i14>
713 ; CHECK-NEXT: call void @usevec(<3 x i14> [[SEXT]])
714 ; CHECK-NEXT: [[LSHR:%.*]] = select <3 x i1> [[A]], <3 x i14> <i14 1023, i14 1023, i14 1023>, <3 x i14> zeroinitializer
715 ; CHECK-NEXT: ret <3 x i14> [[LSHR]]
717 %sext = sext <3 x i1> %a to <3 x i14>
718 call void @usevec(<3 x i14> %sext)
719 %lshr = lshr <3 x i14> %sext, <i14 4, i14 4, i14 4>
723 define i1 @icmp_ule(i32 %x, i32 %y) {
724 ; CHECK-LABEL: @icmp_ule(
725 ; CHECK-NEXT: ret i1 true
727 %x.shifted = lshr i32 %x, %y
728 %cmp = icmp ule i32 %x.shifted, %x
732 define i1 @icmp_ult(i32 %x, i32 %y) {
733 ; CHECK-LABEL: @icmp_ult(
734 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
735 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X_SHIFTED]], [[X]]
736 ; CHECK-NEXT: ret i1 [[CMP]]
738 %x.shifted = lshr i32 %x, %y
739 %cmp = icmp ult i32 %x.shifted, %x
743 define i1 @icmp_eq(i32 %x, i32 %y) {
744 ; CHECK-LABEL: @icmp_eq(
745 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
746 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X_SHIFTED]], [[X]]
747 ; CHECK-NEXT: ret i1 [[CMP]]
749 %x.shifted = lshr i32 %x, %y
750 %cmp = icmp eq i32 %x.shifted, %x
754 define i1 @icmp_ne(i32 %x, i32 %y) {
755 ; CHECK-LABEL: @icmp_ne(
756 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
757 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X_SHIFTED]], [[X]]
758 ; CHECK-NEXT: ret i1 [[CMP]]
760 %x.shifted = lshr i32 %x, %y
761 %cmp = icmp ne i32 %x.shifted, %x
765 define i1 @icmp_ugt(i32 %x, i32 %y) {
766 ; CHECK-LABEL: @icmp_ugt(
767 ; CHECK-NEXT: ret i1 false
769 %x.shifted = lshr i32 %x, %y
770 %cmp = icmp ugt i32 %x.shifted, %x
774 define i1 @icmp_uge(i32 %x, i32 %y) {
775 ; CHECK-LABEL: @icmp_uge(
776 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
777 ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[X_SHIFTED]], [[X]]
778 ; CHECK-NEXT: ret i1 [[CMP]]
780 %x.shifted = lshr i32 %x, %y
781 %cmp = icmp uge i32 %x.shifted, %x
785 define i1 @icmp_sle(i32 %x, i32 %y) {
786 ; CHECK-LABEL: @icmp_sle(
787 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
788 ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[X_SHIFTED]], [[X]]
789 ; CHECK-NEXT: ret i1 [[CMP]]
791 %x.shifted = lshr i32 %x, %y
792 %cmp = icmp sle i32 %x.shifted, %x
796 define i1 @icmp_slt(i32 %x, i32 %y) {
797 ; CHECK-LABEL: @icmp_slt(
798 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
799 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X_SHIFTED]], [[X]]
800 ; CHECK-NEXT: ret i1 [[CMP]]
802 %x.shifted = lshr i32 %x, %y
803 %cmp = icmp slt i32 %x.shifted, %x
807 define i1 @icmp_sgt(i32 %x, i32 %y) {
808 ; CHECK-LABEL: @icmp_sgt(
809 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
810 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X_SHIFTED]], [[X]]
811 ; CHECK-NEXT: ret i1 [[CMP]]
813 %x.shifted = lshr i32 %x, %y
814 %cmp = icmp sgt i32 %x.shifted, %x
818 define i1 @icmp_sge(i32 %x, i32 %y) {
819 ; CHECK-LABEL: @icmp_sge(
820 ; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
821 ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X_SHIFTED]], [[X]]
822 ; CHECK-NEXT: ret i1 [[CMP]]
824 %x.shifted = lshr i32 %x, %y
825 %cmp = icmp sge i32 %x.shifted, %x