From 245adda985f70e64f14b31db0f138754535266a1 Mon Sep 17 00:00:00 2001 From: sunyuechi Date: Sun, 29 Sep 2024 11:17:18 +0800 Subject: [PATCH] fmt-ops: add RVV optimizations for s32_to_f32d --- spa/plugins/audioconvert/benchmark-fmt-ops.c | 5 ++ spa/plugins/audioconvert/fmt-ops-rvv.c | 49 ++++++++++++++++++++ spa/plugins/audioconvert/fmt-ops.c | 3 ++ spa/plugins/audioconvert/fmt-ops.h | 1 + spa/plugins/audioconvert/test-fmt-ops.c | 6 +++ 5 files changed, 64 insertions(+) diff --git a/spa/plugins/audioconvert/benchmark-fmt-ops.c b/spa/plugins/audioconvert/benchmark-fmt-ops.c index d1c89eb40..9ea43ec65 100644 --- a/spa/plugins/audioconvert/benchmark-fmt-ops.c +++ b/spa/plugins/audioconvert/benchmark-fmt-ops.c @@ -205,6 +205,11 @@ static void test_s32_f32(void) if (cpu_flags & SPA_CPU_FLAG_AVX2) { run_test("test_s32_f32d", "avx2", true, false, conv_s32_to_f32d_avx2); } +#endif +#if defined (HAVE_RVV) + if (cpu_flags & SPA_CPU_FLAG_RISCV_V) { + run_test("test_s32_f32d", "rvv", true, false, conv_s32_to_f32d_rvv); + } #endif run_test("test_s32_f32d", "c", true, false, conv_s32_to_f32d_c); run_test("test_s32d_f32d", "c", false, false, conv_s32d_to_f32d_c); diff --git a/spa/plugins/audioconvert/fmt-ops-rvv.c b/spa/plugins/audioconvert/fmt-ops-rvv.c index 940ea0641..02b017207 100644 --- a/spa/plugins/audioconvert/fmt-ops-rvv.c +++ b/spa/plugins/audioconvert/fmt-ops-rvv.c @@ -158,6 +158,55 @@ conv_s16_to_f32d_rvv(struct convert *conv, void * SPA_RESTRICT dst[], const void s16_to_f32d(conv, &dst[i], &s[i], n_channels, n_samples); } +static void +s32_to_f32d(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, + uint32_t n_channels, uint32_t n_samples) +{ + float *d = dst[0]; + uint32_t stride = n_channels << 2; + + asm __volatile__ ( + ".option arch, +v \n\t" + "li t0, 805306368 \n\t" + "fmv.w.x fa5, t0 \n\t" + "1: \n\t" + "vsetvli t0, %[n_samples], e32, m8, ta, ma \n\t" + "vlse32.v v8, (%[src]), %[stride] \n\t" + "sub %[n_samples], %[n_samples], t0 \n\t" + "vfcvt.f.x.v v8, v8 \n\t" + "mul t4, t0, %[stride] \n\t" + "vfmul.vf v8, v8, fa5 \n\t" + "slli t3, t0, 2 \n\t" + "vse32.v v8, (%[d]) \n\t" + "add %[src], %[src], t4 \n\t" + "add %[d], %[d], t3 \n\t" + "bnez %[n_samples], 1b \n\t" + : [n_samples] "+r" (n_samples), + [src] "+r" (src), + [d] "+r" (d) + : [stride] "r" (stride) + : "cc", "memory" + ); + +} + +void +conv_s32_to_f32d_rvv(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + if (n_samples <= 4) { + conv_s32_to_f32d_c(conv, dst, src, n_samples); + return; + } + + const int32_t *s = src[0]; + uint32_t i = 0, n_channels = conv->n_channels; + + for(i = 0; i < n_channels; i++) + s32_to_f32d(conv, &dst[i], &s[i], n_channels, n_samples); + return; +} + static void f32d_to_s32(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) diff --git a/spa/plugins/audioconvert/fmt-ops.c b/spa/plugins/audioconvert/fmt-ops.c index 10620b463..70afcbaff 100644 --- a/spa/plugins/audioconvert/fmt-ops.c +++ b/spa/plugins/audioconvert/fmt-ops.c @@ -105,6 +105,9 @@ static struct conv_info conv_table[] = #endif #if defined (HAVE_SSE2) MAKE(S32, F32P, 0, conv_s32_to_f32d_sse2, SPA_CPU_FLAG_SSE2), +#endif +#if defined (HAVE_RVV) + MAKE(S32, F32P, 0, conv_s32_to_f32d_rvv, SPA_CPU_FLAG_RISCV_V), #endif MAKE(S32, F32, 0, conv_s32_to_f32_c), MAKE(S32P, F32P, 0, conv_s32d_to_f32d_c), diff --git a/spa/plugins/audioconvert/fmt-ops.h b/spa/plugins/audioconvert/fmt-ops.h index 00483431e..506703031 100644 --- a/spa/plugins/audioconvert/fmt-ops.h +++ b/spa/plugins/audioconvert/fmt-ops.h @@ -446,6 +446,7 @@ DEFINE_FUNCTION(f32_to_s16, rvv); DEFINE_FUNCTION(f32d_to_s16d, rvv); DEFINE_FUNCTION(f32d_to_s16, rvv); DEFINE_FUNCTION(s16_to_f32d, rvv); +DEFINE_FUNCTION(s32_to_f32d, rvv); #endif #if defined(HAVE_SSE2) DEFINE_FUNCTION(s16_to_f32d_2, sse2); diff --git a/spa/plugins/audioconvert/test-fmt-ops.c b/spa/plugins/audioconvert/test-fmt-ops.c index acd3ae6a2..17a26a351 100644 --- a/spa/plugins/audioconvert/test-fmt-ops.c +++ b/spa/plugins/audioconvert/test-fmt-ops.c @@ -385,6 +385,12 @@ static void test_s32_f32(void) true, false, conv_s32_to_f32d_avx2); } #endif +#if defined(HAVE_RVV) + if (cpu_flags & SPA_CPU_FLAG_RISCV_V) { + run_test("test_s32_f32d_rvv", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, false, conv_s32_to_f32d_rvv); + } +#endif } static void test_f32_u24(void)