| ; 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 |
| } |