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
13 %shl = shl i32 %a, %or
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
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]]
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()
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()
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()
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()
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
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
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
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
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
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
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
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
163 %shr = lshr i31 %a, %or
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
172 %shr = ashr i33 %a, %or
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
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
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
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
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
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
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
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
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
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:%.*]]
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
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
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>
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
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>
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
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
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
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
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
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
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
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
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