RISC-V: Allow simplification non-vlmax with len = NUNITS reg to reg move
commit9873f13d833b536b46cd6ff46d72e62407b048a8
authorJuzhe-Zhong <juzhe.zhong@rivai.ai>
Sat, 6 Jan 2024 02:08:55 +0000 (6 10:08 +0800)
committerPan Li <pan2.li@intel.com>
Sat, 6 Jan 2024 02:12:43 +0000 (6 10:12 +0800)
tree2954af305be21d4d5f75081bc4cba70261981af9
parent5a0b3355d956f5d36f9b562e027b890cc5f61d88
RISC-V: Allow simplification non-vlmax with len = NUNITS reg to reg move

V2: Address comments from Robin.

While working on fixing a bug, I notice this following code has redundant move:

#include "riscv_vector.h"
void
f (float x, float y, void *out)
{
  float f[4] = { x, x, x, y };
  vfloat32m1_t v = __riscv_vle32_v_f32m1 (f, 4);
  __riscv_vse32_v_f32m1 (out, v, 4);
}

Before this patch:

f:
        vsetivli        zero,4,e32,m1,ta,ma
        addi    sp,sp,-16
        vfmv.v.f        v1,fa0
        vfslide1down.vf v1,v1,fa1
        vmv.v.v v1,v1                       ----> redundant move.
        vse32.v v1,0(a0)
        addi    sp,sp,16
        jr      ra

The rootcause is that the complicate vmv.v.v pattern doesn't simplify it
into simple (set (reg) (reg)) reg-to-reg move pattern.

Currently, we support such simplification for VLMAX.

However, the case I found is non-VLMAX but with LEN = NUNITS which should be
considered as equivalent to VLMAX.

Add a simple fix for such situation.

Tested on both RV32/RV64 no regressions.

gcc/ChangeLog:

* config/riscv/riscv-protos.h (whole_reg_to_reg_move_p): New function.
* config/riscv/riscv-v.cc (whole_reg_to_reg_move_p): Ditto.
* config/riscv/vector.md: Allow non-vlmax with len = NUNITS simplification.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/base/vf_avl-4.c: New test.
gcc/config/riscv/riscv-protos.h
gcc/config/riscv/riscv-v.cc
gcc/config/riscv/vector.md
gcc/testsuite/gcc.target/riscv/rvv/base/vf_avl-4.c [new file with mode: 0644]