[rtsan] Add fork/execve interceptors (#117198)
[llvm-project.git] / llvm / test / Transforms / InstCombine / lshr.ll
blobff358c6bc772a7fce2cb31d56e9aec81c9e367a6
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)
26   %sh = lshr i32 %ct, 5
27   ret i32 %sh
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)
37   %sh = lshr i32 %ct, 5
38   ret i32 %sh
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)
48   %sh = lshr i32 %ct, 5
49   ret i32 %sh
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>
60   ret <2 x i8> %sh
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>
71   ret <2 x i8> %sh
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>
82   ret <2 x i8> %sh
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)
90   %sh = lshr i32 %ct, 5
91   ret i32 %sh
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)
99   %sh = lshr i32 %ct, 5
100   ret i32 %sh
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>
109   ret <2 x i8> %sh
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
119   ret i8 %ex
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>
128   ret <2 x i8> %sh
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
138   ret i8 %ex
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]]
148   %shl = shl i8 %x, 2
149   %add = add i8 %shl, 4
150   %lshr = lshr i8 %add, 2
151   ret i8 %lshr
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>
163   ret <2 x i8> %lshr
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>
174   ret <2 x i8> %lshr
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]]
184   %l = shl i8 %x, 2
185   %a = add i8 %l, %y
186   %r = lshr i8 %a, 2
187   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>
202   ret <2 x i8> %r
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]]
213   %l = shl i32 %x, 2
214   call void @use(i32 %l)
215   %a = add i32 %l, %y
216   %r = lshr i32 %a, 2
217   ret i32 %r
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]]
228   %l = shl i32 %x, 2
229   %a = add i32 %l, %y
230   call void @use(i32 %a)
231   %r = lshr i32 %a, 2
232   ret i32 %r
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
242   ret i16 %hibit
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
255   ret i32 %hibit
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>
265   ret <2 x i8> %hibit
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
276   ret i32 %hibit
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
287   ret i16 %hibit
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>
298   ret <2 x i8> %hibit
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
309   ret i18 %sh
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
322   ret i32 %sh
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>
333   ret <2 x i8> %sh
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>
346   ret <2 x i32> %sh
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
354   %t = lshr i32 %m, 16
355   ret i32 %t
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>
369   ret <3 x i14> %t
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
381   ret i32 %lshr
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
393   ret i32 %lshr
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
407   ret i32 %lshr
410 ; Negative test
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
422   ret i32 %lshr
425 ; Negative test
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
437   ret i32 %lshr
440 ; Negative test
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
452   ret i32 %lshr
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
464   ret i32 %lshr
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
476   ret i32 %lshr
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
488   ret i32 %lshr
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
500   ret i32 %lshr
503 ; Negative test
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
515   ret i32 %lshr
518 ; Negative test
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
532   ret i32 %lshr
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
547   ret i32 %lshr
550 ; Negative test
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
562   ret i32 %lshr
565 ; Negative test
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
577   ret i32 %lshr
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
589   ret i32 %lshr
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
601   ret i32 %lshr
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
613   ret i32 %lshr
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
625   ret i32 %lshr
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
637   ret i32 %lshr
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
649   ret i32 %lshr
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
661   ret i32 %lshr
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
673   ret i32 %lshr
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
683   %3 = and i32 %2, %y
684   %4 = lshr exact i32 %3, %c
685   ret i32 %4
688 ; Negative test
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
700   ret i32 %res
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
710   %t = lshr i32 %m, 16
711   ret i32 %t
714 ; Negative test
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
728   ret i32 %res
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
738   %t = lshr i32 %m, 15
739   ret i32 %t
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
749   %t = lshr i32 %m, 16
750   ret i32 %t
753 ; Negative test
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
762   %t = lshr i32 %m, 16
763   ret i32 %t
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
773   %t = lshr i2 %m, 1
774   ret i2 %t
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]]
783   %s = srem i32 %x, 2
784   %r = lshr i32 %s, 31
785   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>
796   ret <2 x i7> %r
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]]
808   %s = srem i32 %x, 2
809   store i32 %s, ptr %p
810   %r = lshr i32 %s, 31
811   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]]
822   %s = srem i32 %x, 3
823   %r = lshr i32 %s, 31
824   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]]
835   %s = srem i32 %x, 2
836   %r = lshr i32 %s, 30
837   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
848   %r = lshr i12 %tr, 2
849   ret i12 %r
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>
861   ret <2 x i12> %r
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
872   %r = lshr i12 %tr, 1
873   ret i12 %r
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
885   %r = lshr i12 %tr, 1
886   ret i12 %r
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
898   ret i12 %r
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
909   %r = lshr i12 %tr, 1
910   ret i12 %r
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
920   ret i12 %r
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
929   %r = lshr i12 %tr, 1
930   ret i12 %r
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
944   %r = lshr i12 %tr, 2
945   ret i12 %r
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>
960   ret <3 x i9> %r
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
974   %r = lshr i12 %tr, 1
975   ret i12 %r
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
991   %r = lshr i12 %tr, 1
992   ret i12 %r
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
1007   ret i12 %r
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
1022   ret i12 %r
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
1037   ret i12 %r
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
1052   ret i12 %r
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
1062   ret i16 %lshr
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
1072   ret i128 %lshr
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
1085   ret i32 %lshr
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>
1098   ret <3 x i14> %lshr
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
1107   ret i1 %cmp
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
1118   ret i1 %cmp
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
1129   ret i1 %cmp
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
1140   ret i1 %cmp
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
1149   ret i1 %cmp
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
1160   ret i1 %cmp
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
1171   ret i1 %cmp
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
1182   ret i1 %cmp
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
1193   ret i1 %cmp
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
1204   ret i1 %cmp
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
1216   ret i32 %s
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
1228   ret i128 %s
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)
1240   %s = lshr i32 %b, 9
1241   ret i32 %s
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>
1253   ret <2 x i64> %s
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>
1266   ret <2 x i64> %s
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>
1279   ret <2 x i64> %s
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
1292   ret i128 %s
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)
1306   %r = lshr i32 %b, 8
1307   ret i32 %r
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]]
1316   %a = xor i8 %x, -1
1317   %r = lshr i8 %a, 7
1318   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>
1329   ret <2 x i6> %r
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]]
1338   %a = xor i8 %x, -2
1339   %r = lshr i8 %a, 7
1340   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]]
1349   %a = xor i8 %x, -1
1350   %r = lshr i8 %a, 6
1351   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]]
1361   %a = xor i32 %x, -1
1362   call void @use(i32 %a)
1363   %r = lshr i32 %a, 31
1364   ret i32 %r
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]]
1373   %a = xor i16 %x, -1
1374   %r = lshr i16 %a, 15
1375   %r2 = zext i16 %r to i32
1376   ret i32 %r2
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]]
1385   %a = xor i16 %x, -1
1386   %r = lshr i16 %a, 15
1387   %r2 = trunc i16 %r to i8
1388   ret i8 %r2
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
1401   ret i2 %lshr
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
1417   ret i4 %lshr
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
1434   ret i2 %ashr
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>
1447   ret <2 x i8> %lshr
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
1465   ret i32 %lshr
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
1484   ret i32 %lshr
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
1507   ret i32 %lshr
1510 ; negative test
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>
1524   ret <2 x i8> %lshr
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]]
1534 entry:
1535   %mul = mul i64 %x, 64424509440
1536   %shift = lshr i64 %mul, 32
1537   %conv = trunc i64 %shift to i32
1538   ret i32 %conv
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]]
1548 entry:
1549   %mul = mul i32 %x, 104857600
1550   %shift = lshr i32 %mul, 16
1551   %conv = and i32 %shift, 32767
1552   ret i32 %conv
1555 ; Negative tests
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]]
1566 entry:
1567   %mul = mul i32 %x, 104857600
1568   call void @use(i32 %mul)
1569   %shift = lshr i32 %mul, 16
1570   %conv = and i32 %shift, 32767
1571   ret i32 %conv
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]]
1582 entry:
1583   %mul = mul i32 %x, 25600
1584   %shift = lshr i32 %mul, 16
1585   %conv = and i32 %shift, 32767
1586   ret i32 %conv