blob: ba145ecf02cb1f39cc3a6f4fcf293441caec5161 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes=vector-combine -S %s -mtriple=x86_64-- -mattr=+sse2 | FileCheck %s --check-prefixes=CHECK,SSE
; RUN: opt -passes=vector-combine -S %s -mtriple=x86_64-- -mattr=+avx2 | FileCheck %s --check-prefixes=CHECK,AVX
; Tests for foldShuffleToIdentity handling of bitcasts that change element count.
; Motivated by issue #96884: SSE/AVX code uses vXi64 for __m128i/__m256i types,
; requiring bitcasts to different element-count types for operations.
; Narrowing bitcast: split <4 x i32> through <2 x i64> bitcasts and rejoin.
define <4 x i32> @bitcast_i32_to_i64_add(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: @bitcast_i32_to_i64_add(
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x i64>
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i32> [[B:%.*]] to <2 x i64>
; CHECK-NEXT: [[TMP3:%.*]] = add <2 x i64> [[TMP1]], [[TMP2]]
; CHECK-NEXT: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <4 x i32>
; CHECK-NEXT: ret <4 x i32> [[TMP4]]
;
%a_lo = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
%a_hi = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 2, i32 3>
%b_lo = shufflevector <4 x i32> %b, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
%b_hi = shufflevector <4 x i32> %b, <4 x i32> poison, <2 x i32> <i32 2, i32 3>
%bc_a_lo = bitcast <2 x i32> %a_lo to <1 x i64>
%bc_a_hi = bitcast <2 x i32> %a_hi to <1 x i64>
%bc_b_lo = bitcast <2 x i32> %b_lo to <1 x i64>
%bc_b_hi = bitcast <2 x i32> %b_hi to <1 x i64>
%add_lo = add <1 x i64> %bc_a_lo, %bc_b_lo
%add_hi = add <1 x i64> %bc_a_hi, %bc_b_hi
%bc_lo = bitcast <1 x i64> %add_lo to <2 x i32>
%bc_hi = bitcast <1 x i64> %add_hi to <2 x i32>
%result = shufflevector <2 x i32> %bc_lo, <2 x i32> %bc_hi, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i32> %result
}
; Widening bitcast: split <2 x i64> through <4 x i32> bitcasts and rejoin.
; This is the typical SSE pattern: __m128i is <2 x i64>, operations on <4 x i32>.
define <2 x i64> @bitcast_i64_to_i32_xor(<2 x i64> %a, <2 x i64> %b) {
; CHECK-LABEL: @bitcast_i64_to_i32_xor(
; CHECK-NEXT: [[B:%.*]] = xor <2 x i64> [[A:%.*]], [[B1:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i64> [[B]] to <4 x i32>
; CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP2]] to <2 x i64>
; CHECK-NEXT: ret <2 x i64> [[TMP4]]
;
%a_lo = shufflevector <2 x i64> %a, <2 x i64> poison, <1 x i32> <i32 0>
%a_hi = shufflevector <2 x i64> %a, <2 x i64> poison, <1 x i32> <i32 1>
%b_lo = shufflevector <2 x i64> %b, <2 x i64> poison, <1 x i32> <i32 0>
%b_hi = shufflevector <2 x i64> %b, <2 x i64> poison, <1 x i32> <i32 1>
%bc_a_lo = bitcast <1 x i64> %a_lo to <2 x i32>
%bc_a_hi = bitcast <1 x i64> %a_hi to <2 x i32>
%bc_b_lo = bitcast <1 x i64> %b_lo to <2 x i32>
%bc_b_hi = bitcast <1 x i64> %b_hi to <2 x i32>
%xor_lo = xor <2 x i32> %bc_a_lo, %bc_b_lo
%xor_hi = xor <2 x i32> %bc_a_hi, %bc_b_hi
%bc_lo = bitcast <2 x i32> %xor_lo to <1 x i64>
%bc_hi = bitcast <2 x i32> %xor_hi to <1 x i64>
%result = shufflevector <1 x i64> %bc_lo, <1 x i64> %bc_hi, <2 x i32> <i32 0, i32 1>
ret <2 x i64> %result
}
; i64 -> i16: wider ratio (4x), split and rejoin through <8 x i16> operations.
define <2 x i64> @bitcast_i64_to_i16_shl(<2 x i64> %a) {
; CHECK-LABEL: @bitcast_i64_to_i16_shl(
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[A:%.*]] to <8 x i16>
; CHECK-NEXT: [[TMP2:%.*]] = shl <8 x i16> [[TMP1]], splat (i16 3)
; CHECK-NEXT: [[RESULT:%.*]] = bitcast <8 x i16> [[TMP2]] to <2 x i64>
; CHECK-NEXT: ret <2 x i64> [[RESULT]]
;
%a_lo = shufflevector <2 x i64> %a, <2 x i64> poison, <1 x i32> <i32 0>
%a_hi = shufflevector <2 x i64> %a, <2 x i64> poison, <1 x i32> <i32 1>
%bc_lo = bitcast <1 x i64> %a_lo to <4 x i16>
%bc_hi = bitcast <1 x i64> %a_hi to <4 x i16>
%shl_lo = shl <4 x i16> %bc_lo, splat (i16 3)
%shl_hi = shl <4 x i16> %bc_hi, splat (i16 3)
%res_lo = bitcast <4 x i16> %shl_lo to <1 x i64>
%res_hi = bitcast <4 x i16> %shl_hi to <1 x i64>
%result = shufflevector <1 x i64> %res_lo, <1 x i64> %res_hi, <2 x i32> <i32 0, i32 1>
ret <2 x i64> %result
}
; i64 -> i8: ratio of 8, split __m128i into halves, byte-shift, rejoin.
define <2 x i64> @bitcast_i64_to_i8_add(<2 x i64> %a, <2 x i64> %b) {
; CHECK-LABEL: @bitcast_i64_to_i8_add(
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[A:%.*]] to <16 x i8>
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i64> [[B:%.*]] to <16 x i8>
; CHECK-NEXT: [[TMP3:%.*]] = add <16 x i8> [[TMP1]], [[TMP2]]
; CHECK-NEXT: [[RESULT:%.*]] = bitcast <16 x i8> [[TMP3]] to <2 x i64>
; CHECK-NEXT: ret <2 x i64> [[RESULT]]
;
%a_lo = shufflevector <2 x i64> %a, <2 x i64> poison, <1 x i32> <i32 0>
%a_hi = shufflevector <2 x i64> %a, <2 x i64> poison, <1 x i32> <i32 1>
%b_lo = shufflevector <2 x i64> %b, <2 x i64> poison, <1 x i32> <i32 0>
%b_hi = shufflevector <2 x i64> %b, <2 x i64> poison, <1 x i32> <i32 1>
%bc_a_lo = bitcast <1 x i64> %a_lo to <8 x i8>
%bc_a_hi = bitcast <1 x i64> %a_hi to <8 x i8>
%bc_b_lo = bitcast <1 x i64> %b_lo to <8 x i8>
%bc_b_hi = bitcast <1 x i64> %b_hi to <8 x i8>
%add_lo = add <8 x i8> %bc_a_lo, %bc_b_lo
%add_hi = add <8 x i8> %bc_a_hi, %bc_b_hi
%bc_lo = bitcast <8 x i8> %add_lo to <1 x i64>
%bc_hi = bitcast <8 x i8> %add_hi to <1 x i64>
%result = shufflevector <1 x i64> %bc_lo, <1 x i64> %bc_hi, <2 x i32> <i32 0, i32 1>
ret <2 x i64> %result
}
; AVX pattern: <4 x i64> (__m256i) split into two <2 x i64> halves,
; bitcast to <4 x i32>, operate, bitcast back, rejoin.
define <4 x i64> @avx_bitcast_i64_to_i32_and(<4 x i64> %a, <4 x i64> %b) {
; CHECK-LABEL: @avx_bitcast_i64_to_i32_and(
; CHECK-NEXT: [[B:%.*]] = and <4 x i64> [[A:%.*]], [[B1:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i64> [[B]] to <8 x i32>
; CHECK-NEXT: [[TMP4:%.*]] = bitcast <8 x i32> [[TMP2]] to <4 x i64>
; CHECK-NEXT: ret <4 x i64> [[TMP4]]
;
%a_lo = shufflevector <4 x i64> %a, <4 x i64> poison, <2 x i32> <i32 0, i32 1>
%a_hi = shufflevector <4 x i64> %a, <4 x i64> poison, <2 x i32> <i32 2, i32 3>
%b_lo = shufflevector <4 x i64> %b, <4 x i64> poison, <2 x i32> <i32 0, i32 1>
%b_hi = shufflevector <4 x i64> %b, <4 x i64> poison, <2 x i32> <i32 2, i32 3>
%bc_a_lo = bitcast <2 x i64> %a_lo to <4 x i32>
%bc_a_hi = bitcast <2 x i64> %a_hi to <4 x i32>
%bc_b_lo = bitcast <2 x i64> %b_lo to <4 x i32>
%bc_b_hi = bitcast <2 x i64> %b_hi to <4 x i32>
%and_lo = and <4 x i32> %bc_a_lo, %bc_b_lo
%and_hi = and <4 x i32> %bc_a_hi, %bc_b_hi
%bc_lo = bitcast <4 x i32> %and_lo to <2 x i64>
%bc_hi = bitcast <4 x i32> %and_hi to <2 x i64>
%result = shufflevector <2 x i64> %bc_lo, <2 x i64> %bc_hi, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i64> %result
}
; Compare through bitcast: split, bitcast, icmp, select, bitcast back, rejoin.
define <4 x i64> @avx_bitcast_select(<4 x i64> %a, <4 x i64> %b) {
; SSE-LABEL: @avx_bitcast_select(
; SSE-NEXT: [[TMP1:%.*]] = bitcast <4 x i64> [[A:%.*]] to <8 x i32>
; SSE-NEXT: [[TMP2:%.*]] = bitcast <4 x i64> [[B:%.*]] to <8 x i32>
; SSE-NEXT: [[TMP3:%.*]] = icmp sgt <8 x i32> [[TMP1]], [[TMP2]]
; SSE-NEXT: [[TMP4:%.*]] = select <8 x i1> [[TMP3]], <8 x i32> [[TMP1]], <8 x i32> [[TMP2]]
; SSE-NEXT: [[RESULT:%.*]] = bitcast <8 x i32> [[TMP4]] to <4 x i64>
; SSE-NEXT: ret <4 x i64> [[RESULT]]
;
; AVX-LABEL: @avx_bitcast_select(
; AVX-NEXT: [[TMP1:%.*]] = bitcast <4 x i64> [[A:%.*]] to <8 x i32>
; AVX-NEXT: [[TMP2:%.*]] = bitcast <4 x i64> [[B:%.*]] to <8 x i32>
; AVX-NEXT: [[TMP3:%.*]] = icmp sgt <8 x i32> [[TMP1]], [[TMP2]]
; AVX-NEXT: [[TMP4:%.*]] = bitcast <4 x i64> [[A]] to <8 x i32>
; AVX-NEXT: [[TMP5:%.*]] = bitcast <4 x i64> [[B]] to <8 x i32>
; AVX-NEXT: [[TMP6:%.*]] = select <8 x i1> [[TMP3]], <8 x i32> [[TMP4]], <8 x i32> [[TMP5]]
; AVX-NEXT: [[RESULT:%.*]] = bitcast <8 x i32> [[TMP6]] to <4 x i64>
; AVX-NEXT: ret <4 x i64> [[RESULT]]
;
%a_lo = shufflevector <4 x i64> %a, <4 x i64> poison, <2 x i32> <i32 0, i32 1>
%a_hi = shufflevector <4 x i64> %a, <4 x i64> poison, <2 x i32> <i32 2, i32 3>
%b_lo = shufflevector <4 x i64> %b, <4 x i64> poison, <2 x i32> <i32 0, i32 1>
%b_hi = shufflevector <4 x i64> %b, <4 x i64> poison, <2 x i32> <i32 2, i32 3>
%bc_a_lo = bitcast <2 x i64> %a_lo to <4 x i32>
%bc_a_hi = bitcast <2 x i64> %a_hi to <4 x i32>
%bc_b_lo = bitcast <2 x i64> %b_lo to <4 x i32>
%bc_b_hi = bitcast <2 x i64> %b_hi to <4 x i32>
%cmp_lo = icmp sgt <4 x i32> %bc_a_lo, %bc_b_lo
%cmp_hi = icmp sgt <4 x i32> %bc_a_hi, %bc_b_hi
%sel_lo = select <4 x i1> %cmp_lo, <4 x i32> %bc_a_lo, <4 x i32> %bc_b_lo
%sel_hi = select <4 x i1> %cmp_hi, <4 x i32> %bc_a_hi, <4 x i32> %bc_b_hi
%bc_lo = bitcast <4 x i32> %sel_lo to <2 x i64>
%bc_hi = bitcast <4 x i32> %sel_hi to <2 x i64>
%result = shufflevector <2 x i64> %bc_lo, <2 x i64> %bc_hi, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i64> %result
}
; Negative test: misaligned lanes in widening bitcast should not fold.
define <8 x i16> @bitcast_widen_misaligned(<8 x i16> %a) {
; CHECK-LABEL: @bitcast_widen_misaligned(
; CHECK-NEXT: [[LO:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 4>
; CHECK-NEXT: [[BC_LO:%.*]] = bitcast <4 x i16> [[LO]] to <2 x i32>
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[A]] to <4 x i32>
; CHECK-NEXT: [[BC_HI:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <2 x i32> <i32 2, i32 3>
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i32> [[BC_LO]], <2 x i32> [[BC_HI]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
; CHECK-NEXT: [[TMP3:%.*]] = add <4 x i32> [[TMP2]], [[TMP2]]
; CHECK-NEXT: [[RESULT:%.*]] = bitcast <4 x i32> [[TMP3]] to <8 x i16>
; CHECK-NEXT: ret <8 x i16> [[RESULT]]
;
%lo = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 4>
%hi = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
%bc_lo = bitcast <4 x i16> %lo to <2 x i32>
%bc_hi = bitcast <4 x i16> %hi to <2 x i32>
%add_lo = add <2 x i32> %bc_lo, %bc_lo
%add_hi = add <2 x i32> %bc_hi, %bc_hi
%res_lo = bitcast <2 x i32> %add_lo to <4 x i16>
%res_hi = bitcast <2 x i32> %add_hi to <4 x i16>
%result = shufflevector <4 x i16> %res_lo, <4 x i16> %res_hi, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
ret <8 x i16> %result
}
; Regression test: bitcast with non-divisible shuffle output size must not crash.
define <3 x i32> @bitcast_widening_non_divisible(<2 x i64> %x) {
; CHECK-LABEL: @bitcast_widening_non_divisible(
; CHECK-NEXT: [[BC:%.*]] = bitcast <2 x i64> [[X:%.*]] to <4 x i32>
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[BC]], <4 x i32> poison, <3 x i32> <i32 0, i32 1, i32 2>
; CHECK-NEXT: ret <3 x i32> [[R]]
;
%bc = bitcast <2 x i64> %x to <4 x i32>
%r = shufflevector <4 x i32> %bc, <4 x i32> poison, <3 x i32> <i32 0, i32 1, i32 2>
ret <3 x i32> %r
}
; One-way widening bitcast: operate in wider type, don't bitcast back.
; Output type differs from input type.
define <4 x i32> @bitcast_oneway_widen_or(<2 x i64> %a, <2 x i64> %b) {
; CHECK-LABEL: @bitcast_oneway_widen_or(
; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i64> [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[RESULT:%.*]] = bitcast <2 x i64> [[TMP1]] to <4 x i32>
; CHECK-NEXT: ret <4 x i32> [[RESULT]]
;
%a_lo = shufflevector <2 x i64> %a, <2 x i64> poison, <1 x i32> <i32 0>
%a_hi = shufflevector <2 x i64> %a, <2 x i64> poison, <1 x i32> <i32 1>
%b_lo = shufflevector <2 x i64> %b, <2 x i64> poison, <1 x i32> <i32 0>
%b_hi = shufflevector <2 x i64> %b, <2 x i64> poison, <1 x i32> <i32 1>
%bc_a_lo = bitcast <1 x i64> %a_lo to <2 x i32>
%bc_a_hi = bitcast <1 x i64> %a_hi to <2 x i32>
%bc_b_lo = bitcast <1 x i64> %b_lo to <2 x i32>
%bc_b_hi = bitcast <1 x i64> %b_hi to <2 x i32>
%or_lo = or <2 x i32> %bc_a_lo, %bc_b_lo
%or_hi = or <2 x i32> %bc_a_hi, %bc_b_hi
%result = shufflevector <2 x i32> %or_lo, <2 x i32> %or_hi, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i32> %result
}
; One-way narrowing bitcast: operate in narrower type, don't bitcast back.
define <2 x i64> @bitcast_oneway_narrow_sub(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: @bitcast_oneway_narrow_sub(
; CHECK-NEXT: [[RESULT:%.*]] = bitcast <4 x i32> [[TMP1:%.*]] to <2 x i64>
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i32> [[B:%.*]] to <2 x i64>
; CHECK-NEXT: [[RESULT1:%.*]] = sub <2 x i64> [[RESULT]], [[TMP2]]
; CHECK-NEXT: ret <2 x i64> [[RESULT1]]
;
%a_lo = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
%a_hi = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 2, i32 3>
%b_lo = shufflevector <4 x i32> %b, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
%b_hi = shufflevector <4 x i32> %b, <4 x i32> poison, <2 x i32> <i32 2, i32 3>
%bc_a_lo = bitcast <2 x i32> %a_lo to <1 x i64>
%bc_a_hi = bitcast <2 x i32> %a_hi to <1 x i64>
%bc_b_lo = bitcast <2 x i32> %b_lo to <1 x i64>
%bc_b_hi = bitcast <2 x i32> %b_hi to <1 x i64>
%sub_lo = sub <1 x i64> %bc_a_lo, %bc_b_lo
%sub_hi = sub <1 x i64> %bc_a_hi, %bc_b_hi
%result = shufflevector <1 x i64> %sub_lo, <1 x i64> %sub_hi, <2 x i32> <i32 0, i32 1>
ret <2 x i64> %result
}
; Poison lanes in shuffle through bitcast: ensure poison is preserved.
define <4 x i32> @bitcast_poison_lanes(<4 x i32> %a) {
; CHECK-LABEL: @bitcast_poison_lanes(
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x i64>
; CHECK-NEXT: [[BC_LO:%.*]] = shufflevector <2 x i64> [[TMP1]], <2 x i64> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[ADD_LO:%.*]] = add <1 x i64> [[BC_LO]], [[BC_LO]]
; CHECK-NEXT: [[RES_LO:%.*]] = bitcast <1 x i64> [[ADD_LO]] to <2 x i32>
; CHECK-NEXT: [[RESULT:%.*]] = shufflevector <2 x i32> [[RES_LO]], <2 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
; CHECK-NEXT: ret <4 x i32> [[RESULT]]
;
%a_lo = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
%bc_lo = bitcast <2 x i32> %a_lo to <1 x i64>
%add_lo = add <1 x i64> %bc_lo, %bc_lo
%res_lo = bitcast <1 x i64> %add_lo to <2 x i32>
%result = shufflevector <2 x i32> %res_lo, <2 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
ret <4 x i32> %result
}
; Negative test: different operations on halves should not fold.
define <4 x i32> @bitcast_different_ops_neg(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: @bitcast_different_ops_neg(
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x i64>
; CHECK-NEXT: [[BC_A_LO:%.*]] = shufflevector <2 x i64> [[TMP1]], <2 x i64> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i32> [[A]] to <2 x i64>
; CHECK-NEXT: [[BC_A_HI:%.*]] = shufflevector <2 x i64> [[TMP2]], <2 x i64> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i32> [[B:%.*]] to <2 x i64>
; CHECK-NEXT: [[BC_B_LO:%.*]] = shufflevector <2 x i64> [[TMP3]], <2 x i64> poison, <1 x i32> zeroinitializer
; CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[B]] to <2 x i64>
; CHECK-NEXT: [[BC_B_HI:%.*]] = shufflevector <2 x i64> [[TMP4]], <2 x i64> poison, <1 x i32> <i32 1>
; CHECK-NEXT: [[ADD_LO:%.*]] = add <1 x i64> [[BC_A_LO]], [[BC_B_LO]]
; CHECK-NEXT: [[XOR_HI:%.*]] = xor <1 x i64> [[BC_A_HI]], [[BC_B_HI]]
; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <1 x i64> [[ADD_LO]], <1 x i64> [[XOR_HI]], <2 x i32> <i32 0, i32 1>
; CHECK-NEXT: [[RESULT:%.*]] = bitcast <2 x i64> [[TMP5]] to <4 x i32>
; CHECK-NEXT: ret <4 x i32> [[RESULT]]
;
%a_lo = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
%a_hi = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 2, i32 3>
%b_lo = shufflevector <4 x i32> %b, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
%b_hi = shufflevector <4 x i32> %b, <4 x i32> poison, <2 x i32> <i32 2, i32 3>
%bc_a_lo = bitcast <2 x i32> %a_lo to <1 x i64>
%bc_a_hi = bitcast <2 x i32> %a_hi to <1 x i64>
%bc_b_lo = bitcast <2 x i32> %b_lo to <1 x i64>
%bc_b_hi = bitcast <2 x i32> %b_hi to <1 x i64>
%add_lo = add <1 x i64> %bc_a_lo, %bc_b_lo
%xor_hi = xor <1 x i64> %bc_a_hi, %bc_b_hi
%res_lo = bitcast <1 x i64> %add_lo to <2 x i32>
%res_hi = bitcast <1 x i64> %xor_hi to <2 x i32>
%result = shufflevector <2 x i32> %res_lo, <2 x i32> %res_hi, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i32> %result
}
; Bitcast with intrinsic (abs) through narrowing bitcast.
define <4 x i32> @bitcast_narrow_abs(<4 x i32> %a) {
; CHECK-LABEL: @bitcast_narrow_abs(
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x i64>
; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.abs.v2i64(<2 x i64> [[TMP1]], i1 false)
; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x i64> [[TMP2]] to <4 x i32>
; CHECK-NEXT: ret <4 x i32> [[TMP3]]
;
%lo = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
%hi = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 2, i32 3>
%bc_lo = bitcast <2 x i32> %lo to <1 x i64>
%bc_hi = bitcast <2 x i32> %hi to <1 x i64>
%abs_lo = call <1 x i64> @llvm.abs.v1i64(<1 x i64> %bc_lo, i1 false)
%abs_hi = call <1 x i64> @llvm.abs.v1i64(<1 x i64> %bc_hi, i1 false)
%res_lo = bitcast <1 x i64> %abs_lo to <2 x i32>
%res_hi = bitcast <1 x i64> %abs_hi to <2 x i32>
%result = shufflevector <2 x i32> %res_lo, <2 x i32> %res_hi, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i32> %result
}
; Single-element source vector: full ratio compression (R equals total elements).
define <2 x i64> @bitcast_single_src_elt(<2 x i64> %a) {
; CHECK-LABEL: @bitcast_single_src_elt(
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[A:%.*]] to <8 x i16>
; CHECK-NEXT: [[TMP2:%.*]] = add <8 x i16> [[TMP1]], splat (i16 1)
; CHECK-NEXT: [[RESULT:%.*]] = bitcast <8 x i16> [[TMP2]] to <2 x i64>
; CHECK-NEXT: ret <2 x i64> [[RESULT]]
;
%a0 = shufflevector <2 x i64> %a, <2 x i64> poison, <1 x i32> <i32 0>
%a1 = shufflevector <2 x i64> %a, <2 x i64> poison, <1 x i32> <i32 1>
%bc0 = bitcast <1 x i64> %a0 to <4 x i16>
%bc1 = bitcast <1 x i64> %a1 to <4 x i16>
%add0 = add <4 x i16> %bc0, splat (i16 1)
%add1 = add <4 x i16> %bc1, splat (i16 1)
%res0 = bitcast <4 x i16> %add0 to <1 x i64>
%res1 = bitcast <4 x i16> %add1 to <1 x i64>
%result = shufflevector <1 x i64> %res0, <1 x i64> %res1, <2 x i32> <i32 0, i32 1>
ret <2 x i64> %result
}