From c55a080c080ed76a9aabe6dcd1966fedc0ecda5a Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Tue, 26 Nov 2024 09:12:57 -0800 Subject: [PATCH] [RISCV] Add shuffle coverage for compress, decompress, and repeat idioms compress is intented to match vcompress from the ISA manual. Note that deinterleave is a subset of this, and is already tested elsewhere. decompress is the synthetic pattern defined in same - though we can often do better than the mentioned iota/vrgather. Note that some of these can also be expressed as interleave with at least one undef source, and is already tested elsewhere. repeat repeats each input element N times in the output. It can be described as as a interleave operations, but we can sometimes do better lowering wise. --- .../RISCV/rvv/fixed-vectors-int-shuffles.ll | 197 ++++++++++++++++++ 1 file changed, 197 insertions(+) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll index e46587f58b4e..dbfe7bb51dbf 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll @@ -744,3 +744,200 @@ define <8 x i8> @shuffle_v64i8_v8i8(<64 x i8> %wide.vec) { %s = shufflevector <64 x i8> %wide.vec, <64 x i8> poison, <8 x i32> ret <8 x i8> %s } + +define <8 x i8> @shuffle_compress_singlesrc_e8(<8 x i8> %v) { +; CHECK-LABEL: shuffle_compress_singlesrc_e8: +; CHECK: # %bb.0: +; CHECK-NEXT: lui a0, %hi(.LCPI49_0) +; CHECK-NEXT: addi a0, a0, %lo(.LCPI49_0) +; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; CHECK-NEXT: vle8.v v10, (a0) +; CHECK-NEXT: vrgather.vv v9, v8, v10 +; CHECK-NEXT: vmv1r.v v8, v9 +; CHECK-NEXT: ret + %out = shufflevector <8 x i8> %v, <8 x i8> poison, <8 x i32> + ret <8 x i8> %out +} + +define <8 x i16> @shuffle_compress_singlesrc_e16(<8 x i16> %v) { +; CHECK-LABEL: shuffle_compress_singlesrc_e16: +; CHECK: # %bb.0: +; CHECK-NEXT: lui a0, %hi(.LCPI50_0) +; CHECK-NEXT: addi a0, a0, %lo(.LCPI50_0) +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vle16.v v10, (a0) +; CHECK-NEXT: vrgather.vv v9, v8, v10 +; CHECK-NEXT: vmv.v.v v8, v9 +; CHECK-NEXT: ret + %out = shufflevector <8 x i16> %v, <8 x i16> poison, <8 x i32> + ret <8 x i16> %out +} + +define <8 x i32> @shuffle_compress_singlesrc_e32(<8 x i32> %v) { +; CHECK-LABEL: shuffle_compress_singlesrc_e32: +; CHECK: # %bb.0: +; CHECK-NEXT: lui a0, %hi(.LCPI51_0) +; CHECK-NEXT: addi a0, a0, %lo(.LCPI51_0) +; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-NEXT: vle16.v v12, (a0) +; CHECK-NEXT: vrgatherei16.vv v10, v8, v12 +; CHECK-NEXT: vmv.v.v v8, v10 +; CHECK-NEXT: ret + %out = shufflevector <8 x i32> %v, <8 x i32> poison, <8 x i32> + ret <8 x i32> %out +} + +define <8 x i64> @shuffle_compress_singlesrc_e64(<8 x i64> %v) { +; CHECK-LABEL: shuffle_compress_singlesrc_e64: +; CHECK: # %bb.0: +; CHECK-NEXT: lui a0, %hi(.LCPI52_0) +; CHECK-NEXT: addi a0, a0, %lo(.LCPI52_0) +; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma +; CHECK-NEXT: vle16.v v16, (a0) +; CHECK-NEXT: vrgatherei16.vv v12, v8, v16 +; CHECK-NEXT: vmv.v.v v8, v12 +; CHECK-NEXT: ret + %out = shufflevector <8 x i64> %v, <8 x i64> poison, <8 x i32> + ret <8 x i64> %out +} + +define <8 x i32> @shuffle_compress_singlesrc_gaps_e32(<8 x i32> %v) { +; CHECK-LABEL: shuffle_compress_singlesrc_gaps_e32: +; CHECK: # %bb.0: +; CHECK-NEXT: lui a0, %hi(.LCPI53_0) +; CHECK-NEXT: addi a0, a0, %lo(.LCPI53_0) +; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-NEXT: vle16.v v12, (a0) +; CHECK-NEXT: vrgatherei16.vv v10, v8, v12 +; CHECK-NEXT: vmv.v.v v8, v10 +; CHECK-NEXT: ret + %out = shufflevector <8 x i32> %v, <8 x i32> poison, <8 x i32> + ret <8 x i32> %out +} + +define <8 x i32> @shuffle_decompress2_singlesrc_e32(<8 x i32> %v) { +; CHECK-LABEL: shuffle_decompress2_singlesrc_e32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vwaddu.vv v10, v8, v8 +; CHECK-NEXT: li a0, -1 +; CHECK-NEXT: vwmaccu.vx v10, a0, v8 +; CHECK-NEXT: vmv2r.v v8, v10 +; CHECK-NEXT: ret + %out = shufflevector <8 x i32> %v, <8 x i32> poison, <8 x i32> + ret <8 x i32> %out +} + +define <8 x i32> @shuffle_decompress3_singlesrc_e32(<8 x i32> %v) { +; RV32-LABEL: shuffle_decompress3_singlesrc_e32: +; RV32: # %bb.0: +; RV32-NEXT: lui a0, %hi(.LCPI55_0) +; RV32-NEXT: addi a0, a0, %lo(.LCPI55_0) +; RV32-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; RV32-NEXT: vle16.v v12, (a0) +; RV32-NEXT: vrgatherei16.vv v10, v8, v12 +; RV32-NEXT: vmv.v.v v8, v10 +; RV32-NEXT: ret +; +; RV64-LABEL: shuffle_decompress3_singlesrc_e32: +; RV64: # %bb.0: +; RV64-NEXT: lui a0, 32769 +; RV64-NEXT: slli a0, a0, 21 +; RV64-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; RV64-NEXT: vmv.v.x v12, a0 +; RV64-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; RV64-NEXT: vrgatherei16.vv v10, v8, v12 +; RV64-NEXT: vmv.v.v v8, v10 +; RV64-NEXT: ret + %out = shufflevector <8 x i32> %v, <8 x i32> poison, <8 x i32> + ret <8 x i32> %out +} + +; TODO: This should be a single vslideup.vi +define <8 x i32> @shuffle_decompress4_singlesrc_e32(<8 x i32> %v) { +; CHECK-LABEL: shuffle_decompress4_singlesrc_e32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vid.v v10 +; CHECK-NEXT: vsrl.vi v12, v10, 2 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vrgatherei16.vv v10, v8, v12 +; CHECK-NEXT: vmv.v.v v8, v10 +; CHECK-NEXT: ret + %out = shufflevector <8 x i32> %v, <8 x i32> poison, <8 x i32> + ret <8 x i32> %out +} + +; TODO: This should be either a single vslideup.vi or two widening interleaves. +define <8 x i8> @shuffle_decompress4_singlesrc_e8(<8 x i8> %v) { +; CHECK-LABEL: shuffle_decompress4_singlesrc_e8: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; CHECK-NEXT: vid.v v9 +; CHECK-NEXT: vsrl.vi v10, v9, 2 +; CHECK-NEXT: vrgather.vv v9, v8, v10 +; CHECK-NEXT: vmv1r.v v8, v9 +; CHECK-NEXT: ret + %out = shufflevector <8 x i8> %v, <8 x i8> poison, <8 x i32> + ret <8 x i8> %out +} + +define <8 x i32> @shuffle_decompress_singlesrc_e32(<8 x i32> %v) { +; CHECK-LABEL: shuffle_decompress_singlesrc_e32: +; CHECK: # %bb.0: +; CHECK-NEXT: lui a0, %hi(.LCPI58_0) +; CHECK-NEXT: addi a0, a0, %lo(.LCPI58_0) +; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-NEXT: vle16.v v12, (a0) +; CHECK-NEXT: vrgatherei16.vv v10, v8, v12 +; CHECK-NEXT: vmv.v.v v8, v10 +; CHECK-NEXT: ret + %out = shufflevector <8 x i32> %v, <8 x i32> poison, <8 x i32> + ret <8 x i32> %out +} + +define <8 x i32> @shuffle_repeat2_singlesrc_e32(<8 x i32> %v) { +; CHECK-LABEL: shuffle_repeat2_singlesrc_e32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vwaddu.vv v10, v8, v8 +; CHECK-NEXT: li a0, -1 +; CHECK-NEXT: vwmaccu.vx v10, a0, v8 +; CHECK-NEXT: vmv2r.v v8, v10 +; CHECK-NEXT: ret + %out = shufflevector <8 x i32> %v, <8 x i32> poison, <8 x i32> + ret <8 x i32> %out +} + +define <8 x i32> @shuffle_repeat3_singlesrc_e32(<8 x i32> %v) { +; CHECK-LABEL: shuffle_repeat3_singlesrc_e32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vmv.v.i v0, 7 +; CHECK-NEXT: vmv.v.i v11, 1 +; CHECK-NEXT: li a0, 192 +; CHECK-NEXT: vmv.s.x v10, a0 +; CHECK-NEXT: vmerge.vim v11, v11, 0, v0 +; CHECK-NEXT: vmv.v.v v0, v10 +; CHECK-NEXT: vmerge.vim v12, v11, 2, v0 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vrgatherei16.vv v10, v8, v12 +; CHECK-NEXT: vmv.v.v v8, v10 +; CHECK-NEXT: ret + %out = shufflevector <8 x i32> %v, <8 x i32> poison, <8 x i32> + ret <8 x i32> %out +} + +define <8 x i32> @shuffle_repeat4_singlesrc_e32(<8 x i32> %v) { +; CHECK-LABEL: shuffle_repeat4_singlesrc_e32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vid.v v10 +; CHECK-NEXT: vsrl.vi v12, v10, 2 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vrgatherei16.vv v10, v8, v12 +; CHECK-NEXT: vmv.v.v v8, v10 +; CHECK-NEXT: ret + %out = shufflevector <8 x i32> %v, <8 x i32> poison, <8 x i32> + ret <8 x i32> %out +}