Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / InstSimplify / shift-knownbits.ll
blob6bf03779379ec731fba97b3a7d68b9cfd5360153
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instsimplify -S -data-layout="E" | FileCheck %s --check-prefixes=CHECK,BIGENDIAN
3 ; RUN: opt < %s -passes=instsimplify -S -data-layout="e" | FileCheck %s --check-prefixes=CHECK,LITTLEENDIAN
5 ; If any bits of the shift amount are known to make it exceed or equal
6 ; the number of bits in the type, the shift causes undefined behavior.
8 define i32 @shl_amount_is_known_bogus(i32 %a, i32 %b) {
9 ; CHECK-LABEL: @shl_amount_is_known_bogus(
10 ; CHECK-NEXT:    ret i32 poison
12   %or = or i32 %b, 32
13   %shl = shl i32 %a, %or
14   ret i32 %shl
17 define i32 @shl_amount_is_known_bogus_range_attr(i32 %a, i32 range(i32 32, 64) %b) {
18 ; CHECK-LABEL: @shl_amount_is_known_bogus_range_attr(
19 ; CHECK-NEXT:    ret i32 poison
21   %shl = shl i32 %a, %b
22   ret i32 %shl
25 define i32 @neg_shl_amount_is_known_bogus_range_attr(i32 %a, i32 range(i32 0, 32) %b) {
26 ; CHECK-LABEL: @neg_shl_amount_is_known_bogus_range_attr(
27 ; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[A:%.*]], [[B:%.*]]
28 ; CHECK-NEXT:    ret i32 [[SHL]]
30   %shl = shl i32 %a, %b
31   ret i32 %shl
34 declare range(i32 32, 64) i32 @returns_out_of_range_helper()
35 declare range(i32 0, 32) i32 @returns_in_range_helper()
37 define i32 @shl_amount_is_known_bogus_range_return(i32 %a) {
38 ; CHECK-LABEL: @shl_amount_is_known_bogus_range_return(
39 ; CHECK-NEXT:    [[B:%.*]] = call i32 @returns_out_of_range_helper()
40 ; CHECK-NEXT:    ret i32 poison
42   %b = call i32 @returns_out_of_range_helper()
43   %shl = shl i32 %a, %b
44   ret i32 %shl
47 define i32 @neg_shl_amount_is_known_bogus_range_return(i32 %a) {
48 ; CHECK-LABEL: @neg_shl_amount_is_known_bogus_range_return(
49 ; CHECK-NEXT:    [[B:%.*]] = call i32 @returns_in_range_helper()
50 ; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[A:%.*]], [[B]]
51 ; CHECK-NEXT:    ret i32 [[SHL]]
53   %b = call i32 @returns_in_range_helper()
54   %shl = shl i32 %a, %b
55   ret i32 %shl
58 declare i32 @returns_i32_helper()
60 define i32 @shl_amount_is_known_bogus_range_call(i32 %a) {
61 ; CHECK-LABEL: @shl_amount_is_known_bogus_range_call(
62 ; CHECK-NEXT:    [[B:%.*]] = call range(i32 32, 64) i32 @returns_i32_helper()
63 ; CHECK-NEXT:    ret i32 poison
65   %b = call range(i32 32, 64) i32 @returns_i32_helper()
66   %shl = shl i32 %a, %b
67   ret i32 %shl
70 define i32 @neg_shl_amount_is_known_bogus_range_call(i32 %a) {
71 ; CHECK-LABEL: @neg_shl_amount_is_known_bogus_range_call(
72 ; CHECK-NEXT:    [[B:%.*]] = call range(i32 0, 32) i32 @returns_i32_helper()
73 ; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[A:%.*]], [[B]]
74 ; CHECK-NEXT:    ret i32 [[SHL]]
76   %b = call range(i32 0, 32) i32 @returns_i32_helper()
77   %shl = shl i32 %a, %b
78   ret i32 %shl
81 define <2 x i32> @shl_amount_is_known_bogus_range_attr_vec(<2 x i32> %a, <2 x i32> range(i32 32, 64) %b) {
82 ; CHECK-LABEL: @shl_amount_is_known_bogus_range_attr_vec(
83 ; CHECK-NEXT:    ret <2 x i32> poison
85   %shl = shl <2 x i32> %a, %b
86   ret <2 x i32> %shl
89 define <2 x i32> @neg_shl_amount_is_known_bogus_range_attr_vec(<2 x i32> %a, <2 x i32> range(i32 0, 32) %b) {
90 ; CHECK-LABEL: @neg_shl_amount_is_known_bogus_range_attr_vec(
91 ; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i32> [[A:%.*]], [[B:%.*]]
92 ; CHECK-NEXT:    ret <2 x i32> [[SHL]]
94   %shl = shl <2 x i32> %a, %b
95   ret <2 x i32> %shl
98 declare range(i32 32, 64) <2 x i32> @returns_out_of_range_helper_vec()
99 declare range(i32 0, 32) <2 x i32> @returns_in_range_helper_vec()
101 define <2 x i32> @shl_amount_is_known_bogus_range_return_vec(<2 x i32> %a) {
102 ; CHECK-LABEL: @shl_amount_is_known_bogus_range_return_vec(
103 ; CHECK-NEXT:    [[B:%.*]] = call <2 x i32> @returns_out_of_range_helper_vec()
104 ; CHECK-NEXT:    ret <2 x i32> poison
106   %b = call <2 x i32> @returns_out_of_range_helper_vec()
107   %shl = shl <2 x i32> %a, %b
108   ret <2 x i32> %shl
111 define <2 x i32> @neg_shl_amount_is_known_bogus_range_return_vec(<2 x i32> %a) {
112 ; CHECK-LABEL: @neg_shl_amount_is_known_bogus_range_return_vec(
113 ; CHECK-NEXT:    [[B:%.*]] = call <2 x i32> @returns_in_range_helper_vec()
114 ; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i32> [[A:%.*]], [[B]]
115 ; CHECK-NEXT:    ret <2 x i32> [[SHL]]
117   %b = call <2 x i32> @returns_in_range_helper_vec()
118   %shl = shl <2 x i32> %a, %b
119   ret <2 x i32> %shl
122 declare <2 x i32> @returns_i32_helper_vec()
124 define <2 x i32> @shl_amount_is_known_bogus_range_call_vec(<2 x i32> %a) {
125 ; CHECK-LABEL: @shl_amount_is_known_bogus_range_call_vec(
126 ; CHECK-NEXT:    [[B:%.*]] = call range(i32 32, 64) <2 x i32> @returns_i32_helper_vec()
127 ; CHECK-NEXT:    ret <2 x i32> poison
129   %b = call range(i32 32, 64) <2 x i32> @returns_i32_helper_vec()
130   %shl = shl <2 x i32> %a, %b
131   ret <2 x i32> %shl
134 define <2 x i32> @neg_shl_amount_is_known_bogus_range_call_vec(<2 x i32> %a) {
135 ; CHECK-LABEL: @neg_shl_amount_is_known_bogus_range_call_vec(
136 ; CHECK-NEXT:    [[B:%.*]] = call range(i32 0, 32) <2 x i32> @returns_i32_helper_vec()
137 ; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i32> [[A:%.*]], [[B]]
138 ; CHECK-NEXT:    ret <2 x i32> [[SHL]]
140   %b = call range(i32 0, 32) <2 x i32> @returns_i32_helper_vec()
141   %shl = shl <2 x i32> %a, %b
142   ret <2 x i32> %shl
145 define i32 @shl_amount_is_not_known_bogus_range_call_and_range_metadata(i32 %a) {
146 ; CHECK-LABEL: @shl_amount_is_not_known_bogus_range_call_and_range_metadata(
147 ; CHECK-NEXT:    [[B:%.*]] = call range(i32 0, 32) i32 @returns_i32_helper(), !range [[RNG0:![0-9]+]]
148 ; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[A:%.*]], [[B]]
149 ; CHECK-NEXT:    ret i32 [[SHL]]
151   %b = call range(i32 0, 32) i32 @returns_i32_helper(), !range !{ i32 32, i32 64 }
152   %shl = shl i32 %a, %b
153   ret i32 %shl
156 ; Check some weird types and the other shift ops.
158 define i31 @lshr_amount_is_known_bogus(i31 %a, i31 %b) {
159 ; CHECK-LABEL: @lshr_amount_is_known_bogus(
160 ; CHECK-NEXT:    ret i31 poison
162   %or = or i31 %b, 31
163   %shr = lshr i31 %a, %or
164   ret i31 %shr
167 define i33 @ashr_amount_is_known_bogus(i33 %a, i33 %b) {
168 ; CHECK-LABEL: @ashr_amount_is_known_bogus(
169 ; CHECK-NEXT:    ret i33 poison
171   %or = or i33 %b, 33
172   %shr = ashr i33 %a, %or
173   ret i33 %shr
177 ; If all valid bits of the shift amount are known 0, there's no shift.
178 ; It doesn't matter if high bits are set because that would be undefined.
179 ; Therefore, the only possible valid result of these shifts is %a.
181 define i16 @ashr_amount_is_zero(i16 %a, i16 %b) {
182 ; CHECK-LABEL: @ashr_amount_is_zero(
183 ; CHECK-NEXT:    ret i16 [[A:%.*]]
185   %and = and i16 %b, 65520 ; 0xfff0
186   %shr = ashr i16 %a, %and
187   ret i16 %shr
190 define i300 @lshr_amount_is_zero(i300 %a, i300 %b) {
191 ; CHECK-LABEL: @lshr_amount_is_zero(
192 ; CHECK-NEXT:    ret i300 [[A:%.*]]
194   %and = and i300 %b, 2048
195   %shr = lshr i300 %a, %and
196   ret i300 %shr
199 define i9 @shl_amount_is_zero(i9 %a, i9 %b) {
200 ; CHECK-LABEL: @shl_amount_is_zero(
201 ; CHECK-NEXT:    ret i9 [[A:%.*]]
203   %and = and i9 %b, 496 ; 0x1f0
204   %shl = shl i9 %a, %and
205   ret i9 %shl
209 ; Verify that we've calculated the log2 boundary of valid bits correctly for a weird type.
211 define i9 @shl_amount_is_not_known_zero(i9 %a, i9 %b) {
212 ; CHECK-LABEL: @shl_amount_is_not_known_zero(
213 ; CHECK-NEXT:    [[AND:%.*]] = and i9 [[B:%.*]], -8
214 ; CHECK-NEXT:    [[SHL:%.*]] = shl i9 [[A:%.*]], [[AND]]
215 ; CHECK-NEXT:    ret i9 [[SHL]]
217   %and = and i9 %b, 504 ; 0x1f8
218   %shl = shl i9 %a, %and
219   ret i9 %shl
223 ; For vectors, we need all scalar elements to meet the requirements to optimize.
225 define <2 x i32> @ashr_vector_bogus(<2 x i32> %a, <2 x i32> %b) {
226 ; CHECK-LABEL: @ashr_vector_bogus(
227 ; CHECK-NEXT:    ret <2 x i32> poison
229   %or = or <2 x i32> %b, <i32 32, i32 32>
230   %shr = ashr <2 x i32> %a, %or
231   ret <2 x i32> %shr
234 ; FIXME: This is undef, but computeKnownBits doesn't handle the union.
235 define <2 x i32> @shl_vector_bogus(<2 x i32> %a, <2 x i32> %b) {
236 ; CHECK-LABEL: @shl_vector_bogus(
237 ; CHECK-NEXT:    [[OR:%.*]] = or <2 x i32> [[B:%.*]], <i32 32, i32 64>
238 ; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i32> [[A:%.*]], [[OR]]
239 ; CHECK-NEXT:    ret <2 x i32> [[SHL]]
241   %or = or <2 x i32> %b, <i32 32, i32 64>
242   %shl = shl <2 x i32> %a, %or
243   ret <2 x i32> %shl
246 define <2 x i32> @lshr_vector_zero(<2 x i32> %a, <2 x i32> %b) {
247 ; CHECK-LABEL: @lshr_vector_zero(
248 ; CHECK-NEXT:    ret <2 x i32> [[A:%.*]]
250   %and = and <2 x i32> %b, <i32 64, i32 256>
251   %shr = lshr <2 x i32> %a, %and
252   ret <2 x i32> %shr
255 ; Make sure that weird vector types work too.
256 define <2 x i15> @shl_vector_zero(<2 x i15> %a, <2 x i15> %b) {
257 ; CHECK-LABEL: @shl_vector_zero(
258 ; CHECK-NEXT:    ret <2 x i15> [[A:%.*]]
260   %and = and <2 x i15> %b, <i15 1024, i15 1024>
261   %shl = shl <2 x i15> %a, %and
262   ret <2 x i15> %shl
265 define <2 x i32> @shl_vector_for_real(<2 x i32> %a, <2 x i32> %b) {
266 ; CHECK-LABEL: @shl_vector_for_real(
267 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i32> [[B:%.*]], <i32 3, i32 3>
268 ; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i32> [[A:%.*]], [[AND]]
269 ; CHECK-NEXT:    ret <2 x i32> [[SHL]]
271   %and = and <2 x i32> %b, <i32 3, i32 3> ; a necessary mask op
272   %shl = shl <2 x i32> %a, %and
273   ret <2 x i32> %shl
277 ; We calculate the valid bits of the shift using log2, and log2 of 1 (the type width) is 0.
278 ; That should be ok. Either the shift amount is 0 or invalid (1), so we can always return %a.
280 define i1 @shl_i1(i1 %a, i1 %b) {
281 ; CHECK-LABEL: @shl_i1(
282 ; CHECK-NEXT:    ret i1 [[A:%.*]]
284   %shl = shl i1 %a, %b
285   ret i1 %shl
288 ; The following cases only get folded by InstCombine,
289 ; see InstCombine/lshr.ll.
291 declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone
292 declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone
293 declare <2 x i8> @llvm.cttz.v2i8(<2 x i8>, i1) nounwind readnone
294 declare <2 x i8> @llvm.ctlz.v2i8(<2 x i8>, i1) nounwind readnone
296 define i32 @lshr_ctlz_zero_is_undef(i32 %x) {
297 ; CHECK-LABEL: @lshr_ctlz_zero_is_undef(
298 ; CHECK-NEXT:    [[CT:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 true)
299 ; CHECK-NEXT:    [[SH:%.*]] = lshr i32 [[CT]], 5
300 ; CHECK-NEXT:    ret i32 [[SH]]
302   %ct = call i32 @llvm.ctlz.i32(i32 %x, i1 true)
303   %sh = lshr i32 %ct, 5
304   ret i32 %sh
307 define i32 @lshr_cttz_zero_is_undef(i32 %x) {
308 ; CHECK-LABEL: @lshr_cttz_zero_is_undef(
309 ; CHECK-NEXT:    [[CT:%.*]] = call i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
310 ; CHECK-NEXT:    [[SH:%.*]] = lshr i32 [[CT]], 5
311 ; CHECK-NEXT:    ret i32 [[SH]]
313   %ct = call i32 @llvm.cttz.i32(i32 %x, i1 true)
314   %sh = lshr i32 %ct, 5
315   ret i32 %sh
318 define <2 x i8> @lshr_ctlz_zero_is_undef_splat_vec(<2 x i8> %x) {
319 ; CHECK-LABEL: @lshr_ctlz_zero_is_undef_splat_vec(
320 ; CHECK-NEXT:    [[CT:%.*]] = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> [[X:%.*]], i1 true)
321 ; CHECK-NEXT:    [[SH:%.*]] = lshr <2 x i8> [[CT]], <i8 3, i8 3>
322 ; CHECK-NEXT:    ret <2 x i8> [[SH]]
324   %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 true)
325   %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
326   ret <2 x i8> %sh
329 define i8 @lshr_ctlz_zero_is_undef_vec(<2 x i8> %x) {
330 ; CHECK-LABEL: @lshr_ctlz_zero_is_undef_vec(
331 ; CHECK-NEXT:    [[CT:%.*]] = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> [[X:%.*]], i1 true)
332 ; CHECK-NEXT:    [[SH:%.*]] = lshr <2 x i8> [[CT]], <i8 3, i8 0>
333 ; CHECK-NEXT:    [[EX:%.*]] = extractelement <2 x i8> [[SH]], i32 0
334 ; CHECK-NEXT:    ret i8 [[EX]]
336   %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 true)
337   %sh = lshr <2 x i8> %ct, <i8 3, i8 0>
338   %ex = extractelement <2 x i8> %sh, i32 0
339   ret i8 %ex
342 define <2 x i8> @lshr_cttz_zero_is_undef_splat_vec(<2 x i8> %x) {
343 ; CHECK-LABEL: @lshr_cttz_zero_is_undef_splat_vec(
344 ; CHECK-NEXT:    [[CT:%.*]] = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> [[X:%.*]], i1 true)
345 ; CHECK-NEXT:    [[SH:%.*]] = lshr <2 x i8> [[CT]], <i8 3, i8 3>
346 ; CHECK-NEXT:    ret <2 x i8> [[SH]]
348   %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 true)
349   %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
350   ret <2 x i8> %sh
353 define i8 @lshr_cttz_zero_is_undef_vec(<2 x i8> %x) {
354 ; CHECK-LABEL: @lshr_cttz_zero_is_undef_vec(
355 ; CHECK-NEXT:    [[CT:%.*]] = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> [[X:%.*]], i1 true)
356 ; CHECK-NEXT:    [[SH:%.*]] = lshr <2 x i8> [[CT]], <i8 3, i8 0>
357 ; CHECK-NEXT:    [[EX:%.*]] = extractelement <2 x i8> [[SH]], i32 0
358 ; CHECK-NEXT:    ret i8 [[EX]]
360   %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 true)
361   %sh = lshr <2 x i8> %ct, <i8 3, i8 0>
362   %ex = extractelement <2 x i8> %sh, i32 0
363   ret i8 %ex
366 ; The shift amount is 0 on either of high/low bytes. The middle byte doesn't matter.
368 define i24 @bitcast_noshift_scalar(<3 x i8> %v1, i24 %v2) {
369 ; CHECK-LABEL: @bitcast_noshift_scalar(
370 ; CHECK-NEXT:    ret i24 [[V2:%.*]]
372   %c = insertelement <3 x i8> poison, i8 0, i64 0
373   %s = shufflevector <3 x i8> %v1, <3 x i8> %c, <3 x i32> <i32 3, i32 1, i32 3>
374   %b = bitcast <3 x i8> %s to i24
375   %r = shl i24 %v2, %b
376   ret i24 %r
379 ; The shift amount is 0 on low byte of big-endian and unknown on little-endian.
381 define i24 @bitcast_noshift_scalar_bigend(<3 x i8> %v1, i24 %v2) {
382 ; BIGENDIAN-LABEL: @bitcast_noshift_scalar_bigend(
383 ; BIGENDIAN-NEXT:    ret i24 [[V2:%.*]]
385 ; LITTLEENDIAN-LABEL: @bitcast_noshift_scalar_bigend(
386 ; LITTLEENDIAN-NEXT:    [[S:%.*]] = shufflevector <3 x i8> [[V1:%.*]], <3 x i8> <i8 0, i8 poison, i8 poison>, <3 x i32> <i32 0, i32 1, i32 3>
387 ; LITTLEENDIAN-NEXT:    [[B:%.*]] = bitcast <3 x i8> [[S]] to i24
388 ; LITTLEENDIAN-NEXT:    [[R:%.*]] = shl i24 [[V2:%.*]], [[B]]
389 ; LITTLEENDIAN-NEXT:    ret i24 [[R]]
391   %c = insertelement <3 x i8> poison, i8 0, i64 0
392   %s = shufflevector <3 x i8> %v1, <3 x i8> %c, <3 x i32> <i32 0, i32 1, i32 3>
393   %b = bitcast <3 x i8> %s to i24
394   %r = shl i24 %v2, %b
395   ret i24 %r
398 ; The shift amount is 0 on low byte of little-endian and unknown on big-endian.
400 define i24 @bitcast_noshift_scalar_littleend(<3 x i8> %v1, i24 %v2) {
401 ; BIGENDIAN-LABEL: @bitcast_noshift_scalar_littleend(
402 ; BIGENDIAN-NEXT:    [[S:%.*]] = shufflevector <3 x i8> [[V1:%.*]], <3 x i8> <i8 0, i8 poison, i8 poison>, <3 x i32> <i32 3, i32 1, i32 2>
403 ; BIGENDIAN-NEXT:    [[B:%.*]] = bitcast <3 x i8> [[S]] to i24
404 ; BIGENDIAN-NEXT:    [[R:%.*]] = shl i24 [[V2:%.*]], [[B]]
405 ; BIGENDIAN-NEXT:    ret i24 [[R]]
407 ; LITTLEENDIAN-LABEL: @bitcast_noshift_scalar_littleend(
408 ; LITTLEENDIAN-NEXT:    ret i24 [[V2:%.*]]
410   %c = insertelement <3 x i8> poison, i8 0, i64 0
411   %s = shufflevector <3 x i8> %v1, <3 x i8> %c, <3 x i32> <i32 3, i32 1, i32 2>
412   %b = bitcast <3 x i8> %s to i24
413   %r = shl i24 %v2, %b
414   ret i24 %r
417 ; The shift amount is known 24 on little-endian and known 24<<16 on big-endian
418 ; across all vector elements, so it's an overshift either way.
420 define <3 x i24> @bitcast_overshift_vector(<9 x i8> %v1, <3 x i24> %v2) {
421 ; CHECK-LABEL: @bitcast_overshift_vector(
422 ; CHECK-NEXT:    ret <3 x i24> poison
424   %c = insertelement <9 x i8> poison, i8 24, i64 0
425   %s = shufflevector <9 x i8> %v1, <9 x i8> %c, <9 x i32> <i32 9, i32 1, i32 2, i32 9, i32 4, i32 5, i32 9, i32 7, i32 8>
426   %b = bitcast <9 x i8> %s to <3 x i24>
427   %r = shl <3 x i24> %v2, %b
428   ret <3 x i24> %r
431 ; The shift amount is known 23 on little-endian and known 23<<16 on big-endian
432 ; across all vector elements, so it's an overshift for big-endian.
434 define <3 x i24> @bitcast_overshift_vector_bigend(<9 x i8> %v1, <3 x i24> %v2) {
435 ; BIGENDIAN-LABEL: @bitcast_overshift_vector_bigend(
436 ; BIGENDIAN-NEXT:    ret <3 x i24> poison
438 ; LITTLEENDIAN-LABEL: @bitcast_overshift_vector_bigend(
439 ; LITTLEENDIAN-NEXT:    [[S:%.*]] = shufflevector <9 x i8> [[V1:%.*]], <9 x i8> <i8 23, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison>, <9 x i32> <i32 9, i32 1, i32 2, i32 9, i32 4, i32 5, i32 9, i32 7, i32 8>
440 ; LITTLEENDIAN-NEXT:    [[B:%.*]] = bitcast <9 x i8> [[S]] to <3 x i24>
441 ; LITTLEENDIAN-NEXT:    [[R:%.*]] = shl <3 x i24> [[V2:%.*]], [[B]]
442 ; LITTLEENDIAN-NEXT:    ret <3 x i24> [[R]]
444   %c = insertelement <9 x i8> poison, i8 23, i64 0
445   %s = shufflevector <9 x i8> %v1, <9 x i8> %c, <9 x i32> <i32 9, i32 1, i32 2, i32 9, i32 4, i32 5, i32 9, i32 7, i32 8>
446   %b = bitcast <9 x i8> %s to <3 x i24>
447   %r = shl <3 x i24> %v2, %b
448   ret <3 x i24> %r
451 ; The shift amount is known 23 on big-endian and known 23<<16 on little-endian
452 ; across all vector elements, so it's an overshift for little-endian.
454 define <3 x i24> @bitcast_overshift_vector_littleend(<9 x i8> %v1, <3 x i24> %v2) {
455 ; BIGENDIAN-LABEL: @bitcast_overshift_vector_littleend(
456 ; BIGENDIAN-NEXT:    [[S:%.*]] = shufflevector <9 x i8> [[V1:%.*]], <9 x i8> <i8 23, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison>, <9 x i32> <i32 0, i32 1, i32 9, i32 3, i32 4, i32 9, i32 6, i32 7, i32 9>
457 ; BIGENDIAN-NEXT:    [[B:%.*]] = bitcast <9 x i8> [[S]] to <3 x i24>
458 ; BIGENDIAN-NEXT:    [[R:%.*]] = shl <3 x i24> [[V2:%.*]], [[B]]
459 ; BIGENDIAN-NEXT:    ret <3 x i24> [[R]]
461 ; LITTLEENDIAN-LABEL: @bitcast_overshift_vector_littleend(
462 ; LITTLEENDIAN-NEXT:    ret <3 x i24> poison
464   %c = insertelement <9 x i8> poison, i8 23, i64 0
465   %s = shufflevector <9 x i8> %v1, <9 x i8> %c, <9 x i32> <i32 0, i32 1, i32 9, i32 3, i32 4, i32 9, i32 6, i32 7, i32 9>
466   %b = bitcast <9 x i8> %s to <3 x i24>
467   %r = shl <3 x i24> %v2, %b
468   ret <3 x i24> %r
471 ; Negative test - the shift amount is known 24 or 24<<16 on only 2 out of 3 elements.
473 define <3 x i24> @bitcast_partial_overshift_vector(<9 x i8> %v1, <3 x i24> %v2) {
474 ; CHECK-LABEL: @bitcast_partial_overshift_vector(
475 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <9 x i8> [[V1:%.*]], <9 x i8> <i8 24, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison>, <9 x i32> <i32 9, i32 1, i32 2, i32 9, i32 4, i32 5, i32 6, i32 7, i32 8>
476 ; CHECK-NEXT:    [[B:%.*]] = bitcast <9 x i8> [[S]] to <3 x i24>
477 ; CHECK-NEXT:    [[R:%.*]] = shl <3 x i24> [[V2:%.*]], [[B]]
478 ; CHECK-NEXT:    ret <3 x i24> [[R]]
480   %c = insertelement <9 x i8> poison, i8 24, i64 0
481   %s = shufflevector <9 x i8> %v1, <9 x i8> %c, <9 x i32> <i32 9, i32 1, i32 2, i32 9, i32 4, i32 5, i32 6, i32 7, i32 8>
482   %b = bitcast <9 x i8> %s to <3 x i24>
483   %r = shl <3 x i24> %v2, %b
484   ret <3 x i24> %r
487 ; Negative test - don't know how to look through a cast with non-integer type (but we could handle this...).
489 define <1 x i64> @bitcast_noshift_vector_wrong_type(<2 x float> %v1, <1 x i64> %v2) {
490 ; CHECK-LABEL: @bitcast_noshift_vector_wrong_type(
491 ; CHECK-NEXT:    [[S:%.*]] = shufflevector <2 x float> [[V1:%.*]], <2 x float> <float 0.000000e+00, float poison>, <2 x i32> <i32 2, i32 1>
492 ; CHECK-NEXT:    [[B:%.*]] = bitcast <2 x float> [[S]] to <1 x i64>
493 ; CHECK-NEXT:    [[R:%.*]] = shl <1 x i64> [[V2:%.*]], [[B]]
494 ; CHECK-NEXT:    ret <1 x i64> [[R]]
496   %c = insertelement <2 x float> poison, float 0.0, i64 0
497   %s = shufflevector <2 x float> %v1, <2 x float> %c, <2 x i32> <i32 2, i32 1>
498   %b = bitcast <2 x float> %s to <1 x i64>
499   %r = shl <1 x i64> %v2, %b
500   ret <1 x i64> %r