From: Pan Li Date: Mon, 15 May 2023 08:18:03 +0000 (+0800) Subject: RISC-V: Optimize vsetvl AVL for VLS VLMAX auto-vectorization X-Git-Tag: basepoints/gcc-15~9321 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e9ea407c474b52722cb135f3f6b265ef01aede04;p=thirdparty%2Fgcc.git RISC-V: Optimize vsetvl AVL for VLS VLMAX auto-vectorization This patch is optimizing the AVL for VLS auto-vectorzation. Given below sample code: typedef int8_t vnx2qi __attribute__ ((vector_size (2))); __attribute__ ((noipa)) void f_vnx2qi (int8_t a, int8_t b, int8_t *out) { vnx2qi v = {a, b}; *(vnx2qi *) out = v; } Before this patch: f_vnx2qi: vsetvli a5,zero,e8,mf8,ta,ma vmv.v.x v1,a0 vslide1down.vx v1,v1,a1 vse8.v v1,0(a2) ret After this patch: f_vnx2qi: vsetivli zero,2,e8,mf8,ta,ma vmv.v.x v1,a0 vslide1down.vx v1,v1,a1 vse8.v v1,0(a2) ret Signed-off-by: Pan Li Co-authored-by: Juzhe-Zhong Co-authored-by: kito-cheng gcc/ChangeLog: * config/riscv/riscv-v.cc (const_vlmax_p): New function for deciding the mode is constant or not. (set_len_and_policy): Optimize VLS-VLMAX code gen to vsetivli. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/base/vf_avl-1.c: New test. --- diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index b8dc333f54e1..d65e7300303c 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -50,6 +50,19 @@ using namespace riscv_vector; namespace riscv_vector { +/* Return true if vlmax is constant value and can be used in vsetivl. */ +static bool +const_vlmax_p (machine_mode mode) +{ + poly_uint64 nuints = GET_MODE_NUNITS (mode); + + return nuints.is_constant () + /* The vsetivli can only hold register 0~31. */ + ? (IN_RANGE (nuints.to_constant (), 0, 31)) + /* Only allowed in VLS-VLMAX mode. */ + : false; +} + template class insn_expander { public: @@ -101,12 +114,19 @@ public: void set_len_and_policy (rtx len, bool force_vlmax = false) { - bool vlmax_p = force_vlmax; + bool vlmax_p = force_vlmax || !len; gcc_assert (has_dest); - if (!len) + if (vlmax_p && const_vlmax_p (dest_mode)) + { + /* Optimize VLS-VLMAX code gen, we can use vsetivli instead of the + vsetvli to obtain the value of vlmax. */ + poly_uint64 nunits = GET_MODE_NUNITS (dest_mode); + len = gen_int_mode (nunits, Pmode); + vlmax_p = false; /* It has became NONVLMAX now. */ + } + else if (!len) { - vlmax_p = true; len = gen_reg_rtx (Pmode); emit_vlmax_vsetvl (dest_mode, len); } diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/vf_avl-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/vf_avl-1.c new file mode 100644 index 000000000000..11adf6bc611b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/vf_avl-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv32gcv -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax" } */ + +#include + +typedef int8_t vnx2qi __attribute__ ((vector_size (2))); + +__attribute__ ((noipa)) void +f_vnx2qi (int8_t a, int8_t b, int8_t *out) +{ + vnx2qi v = {a, b}; + *(vnx2qi *) out = v; +} + +/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*2,\s*e8,\s*mf8,\s*t[au],\s*m[au]} 1 } } */