[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / llvm / test / Transforms / InstCombine / lshr.ll
blob1862975975e6290681fe482b874a1f3d5e41f620
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)
23   %sh = lshr i32 %ct, 5
24   ret i32 %sh
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)
34   %sh = lshr i32 %ct, 5
35   ret i32 %sh
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)
45   %sh = lshr i32 %ct, 5
46   ret i32 %sh
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>
57   ret <2 x i8> %sh
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>
68   ret <2 x i8> %sh
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>
79   ret <2 x i8> %sh
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)
87   %sh = lshr i32 %ct, 5
88   ret i32 %sh
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)
96   %sh = lshr i32 %ct, 5
97   ret i32 %sh
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>
106   ret <2 x i8> %sh
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
116   ret i8 %ex
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>
125   ret <2 x i8> %sh
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
135   ret i8 %ex
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]]
145   %shl = shl i8 %x, 2
146   %add = add i8 %shl, 4
147   %lshr = lshr i8 %add, 2
148   ret i8 %lshr
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>
160   ret <2 x i8> %lshr
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]]
170   %l = shl i8 %x, 2
171   %a = add i8 %l, %y
172   %r = lshr i8 %a, 2
173   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>
188   ret <2 x i8> %r
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]]
199   %l = shl i32 %x, 2
200   call void @use(i32 %l)
201   %a = add i32 %l, %y
202   %r = lshr i32 %a, 2
203   ret i32 %r
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]]
214   %l = shl i32 %x, 2
215   %a = add i32 %l, %y
216   call void @use(i32 %a)
217   %r = lshr i32 %a, 2
218   ret i32 %r
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
228   ret i16 %hibit
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
241   ret i32 %hibit
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>
251   ret <2 x i8> %hibit
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
262   ret i32 %hibit
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
273   ret i16 %hibit
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>
284   ret <2 x i8> %hibit
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
295   ret i18 %sh
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
308   ret i32 %sh
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>
319   ret <2 x i8> %sh
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>
332   ret <2 x i32> %sh
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
341   %t = lshr i32 %m, 16
342   ret i32 %t
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>
357   ret <3 x i14> %t
360 ; Negative test
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
369   %t = lshr i32 %m, 16
370   ret i32 %t
373 ; Negative test
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
382   %t = lshr i32 %m, 15
383   ret i32 %t
386 ; Negative test
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
395   %t = lshr i32 %m, 16
396   ret i32 %t
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]]
405   %s = srem i32 %x, 2
406   %r = lshr i32 %s, 31
407   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>
418   ret <2 x i7> %r
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]]
430   %s = srem i32 %x, 2
431   store i32 %s, i32* %p
432   %r = lshr i32 %s, 31
433   ret i32 %r
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]]
444   %s = srem i32 %x, 3
445   %r = lshr i32 %s, 31
446   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]]
457   %s = srem i32 %x, 2
458   %r = lshr i32 %s, 30
459   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
470   %r = lshr i12 %tr, 2
471   ret i12 %r
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>
483   ret <2 x i12> %r
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
494   %r = lshr i12 %tr, 1
495   ret i12 %r
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
507   %r = lshr i12 %tr, 1
508   ret i12 %r
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
520   ret i12 %r
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
531   %r = lshr i12 %tr, 1
532   ret i12 %r
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
542   ret i12 %r
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
551   %r = lshr i12 %tr, 1
552   ret i12 %r
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
566   %r = lshr i12 %tr, 2
567   ret i12 %r
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>
582   ret <3 x i9> %r
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
596   %r = lshr i12 %tr, 1
597   ret i12 %r
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
613   %r = lshr i12 %tr, 1
614   ret i12 %r
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
629   ret i12 %r
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
643   %r = lshr i12 %tr, 1
644   ret i12 %r
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
659   ret i12 %r
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
673   %r = lshr i12 %tr, 1
674   ret i12 %r
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
684   ret i16 %lshr
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
694   ret i128 %lshr
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
707   ret i32 %lshr
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>
720   ret <3 x i14> %lshr
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
729   ret i1 %cmp
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
740   ret i1 %cmp
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
751   ret i1 %cmp
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
762   ret i1 %cmp
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
771   ret i1 %cmp
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
782   ret i1 %cmp
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
793   ret i1 %cmp
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
804   ret i1 %cmp
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
815   ret i1 %cmp
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
826   ret i1 %cmp