From: Robin Dapp Date: Thu, 21 Nov 2024 13:49:53 +0000 (+0100) Subject: RISC-V: Ensure vtype for full-register moves [PR117544]. X-Git-Tag: basepoints/gcc-16~3900 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b82a5810e7bcc82b933e16f9067879b9d22b85c7;p=thirdparty%2Fgcc.git RISC-V: Ensure vtype for full-register moves [PR117544]. As discussed in PR117544 the VTYPE register is not preserved across function calls. Even though vmv1r-like instructions operate independently of the actual vtype they still require a valid vtype. As we cannot guarantee that the vtype is valid we must make sure to emit a vsetvl between a function call and a vmv1r.v. This patch makes the necessary changes by splitting the full-reg-move insns into patterns that use the vtype register and adding vmov to the types of instructions requiring a vset. PR target/117544 gcc/ChangeLog: * config/riscv/vector.md (*mov_whole): Split. (*mov_fract): Ditto. (*mov): Ditto. (*mov_vls): Ditto. (*mov_reg_whole_vtype): New pattern with vtype use. (*mov_fract_vtype): Ditto. (*mov_vtype): Ditto. (*mov_vls_vtype): Ditto. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/base/abi-call-args-4.c: Expect vsetvl. * gcc.target/riscv/rvv/base/pr117544.c: New test. --- diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md index 02cbd2f56f19..57e3c34c1c5a 100644 --- a/gcc/config/riscv/vector.md +++ b/gcc/config/riscv/vector.md @@ -42,7 +42,8 @@ (cond [(eq_attr "type" "vlde,vste,vldm,vstm,vlds,vsts,\ vldux,vldox,vstux,vstox,vldff,\ vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,viminmax,\ - vimul,vidiv,viwmul,vimuladd,viwmuladd,vimerge,vimov,\ + vimul,vidiv,viwmul,vimuladd,viwmuladd,vimerge, + vmov,vimov,\ vsalu,vaalu,vsmul,vsshift,vnclip,\ vfalu,vfwalu,vfmul,vfdiv,vfwmul,vfmuladd,vfwmuladd,vfsqrt,vfrecp,\ vfcmp,vfminmax,vfsgnj,vfclass,vfmerge,vfmov,\ @@ -1214,21 +1215,58 @@ ;; which is not the pattern we want. ;; According the facts above, we make "*mov_whole" includes load/store/move for whole ;; vector modes according to '-march' and "*mov_fract" only include fractional vector modes. -(define_insn "*mov_whole" +(define_insn_and_split "*mov_whole" [(set (match_operand:V_WHOLE 0 "reg_or_mem_operand" "=vr, m,vr") (match_operand:V_WHOLE 1 "reg_or_mem_operand" " m,vr,vr"))] "TARGET_VECTOR && !TARGET_XTHEADVECTOR" "@ vl%m1re.v\t%0,%1 vs%m1r.v\t%1,%0 - vmv%m1r.v\t%0,%1" + #" + "&& !memory_operand (operands[0], mode) + && !memory_operand (operands[1], mode)" + [(parallel [(set (match_dup 0) (match_dup 1)) + (use (reg:SI VTYPE_REGNUM))])] + "" [(set_attr "type" "vldr,vstr,vmov") (set_attr "mode" "")]) -(define_insn "*mov_fract" +;; Full-register moves like vmv1r.v require a valid vtype. +;; The ABI does not guarantee that the vtype is valid after a function +;; call so we need to make it dependent on the vtype and have +;; the vsetvl pass insert a vsetvl if necessary. +;; To facilitate optimization we keep the reg-reg move patterns "regular" +;; until split time and only then switch to a pattern like below that +;; uses the vtype register. +;; As the use of these patterns is limited (in the general context) +;; there is no need for helper functions and we can just create the RTX +;; directly. +(define_insn "*mov_reg_whole_vtype" + [(set (match_operand:V_WHOLE 0 "reg_or_mem_operand" "=vr") + (match_operand:V_WHOLE 1 "reg_or_mem_operand" " vr")) + (use (reg:SI VTYPE_REGNUM))] + "TARGET_VECTOR && !TARGET_XTHEADVECTOR" + "vmv%m1r.v\t%0,%1" + [(set_attr "type" "vmov") + (set_attr "mode" "")]) + +(define_insn_and_split "*mov_fract" [(set (match_operand:V_FRACT 0 "register_operand" "=vr") (match_operand:V_FRACT 1 "register_operand" " vr"))] "TARGET_VECTOR" + "#" + "&& 1" + [(parallel [(set (match_dup 0) (match_dup 1)) + (use (reg:SI VTYPE_REGNUM))])] + "" + [(set_attr "type" "vmov") + (set_attr "mode" "")]) + +(define_insn "*mov_fract_vtype" + [(set (match_operand:V_FRACT 0 "register_operand" "=vr") + (match_operand:V_FRACT 1 "register_operand" " vr")) + (use (reg:SI VTYPE_REGNUM))] + "TARGET_VECTOR" "vmv1r.v\t%0,%1" [(set_attr "type" "vmov") (set_attr "mode" "")]) @@ -1249,10 +1287,23 @@ DONE; }) -(define_insn "*mov" +(define_insn_and_split "*mov" [(set (match_operand:VB 0 "register_operand" "=vr") (match_operand:VB 1 "register_operand" " vr"))] "TARGET_VECTOR && !TARGET_XTHEADVECTOR" + "#" + "&& 1" + [(parallel [(set (match_dup 0) (match_dup 1)) + (use (reg:SI VTYPE_REGNUM))])] + "" + [(set_attr "type" "vmov") + (set_attr "mode" "")]) + +(define_insn "*mov_vtype" + [(set (match_operand:VB 0 "register_operand" "=vr") + (match_operand:VB 1 "register_operand" " vr")) + (use (reg:SI VTYPE_REGNUM))] + "TARGET_VECTOR && !TARGET_XTHEADVECTOR" "vmv1r.v\t%0,%1" [(set_attr "type" "vmov") (set_attr "mode" "")]) @@ -1451,18 +1502,44 @@ (set (attr "mode_idx") (const_int INVALID_ATTRIBUTE))] ) -(define_insn "*mov_vls" +(define_insn_and_split "*mov_vls" [(set (match_operand:VLS 0 "register_operand" "=vr") (match_operand:VLS 1 "register_operand" " vr"))] "TARGET_VECTOR" + "#" + "&& 1" + [(parallel [(set (match_dup 0) (match_dup 1)) + (use (reg:SI VTYPE_REGNUM))])] + "" + [(set_attr "type" "vmov") + (set_attr "mode" "")]) + +(define_insn "*mov_vls_vtype" + [(set (match_operand:VLS 0 "register_operand" "=vr") + (match_operand:VLS 1 "register_operand" " vr")) + (use (reg:SI VTYPE_REGNUM))] + "TARGET_VECTOR" "vmv%m1r.v\t%0,%1" [(set_attr "type" "vmov") (set_attr "mode" "")]) -(define_insn "*mov_vls" +(define_insn_and_split "*mov_vls" [(set (match_operand:VLSB 0 "register_operand" "=vr") (match_operand:VLSB 1 "register_operand" " vr"))] "TARGET_VECTOR" + "#" + "&& 1" + [(parallel [(set (match_dup 0) (match_dup 1)) + (use (reg:SI VTYPE_REGNUM))])] + "" + [(set_attr "type" "vmov") + (set_attr "mode" "")]) + +(define_insn "*mov_vls_vtype" + [(set (match_operand:VLSB 0 "register_operand" "=vr") + (match_operand:VLSB 1 "register_operand" " vr")) + (use (reg:SI VTYPE_REGNUM))] + "TARGET_VECTOR" "vmv1r.v\t%0,%1" [(set_attr "type" "vmov") (set_attr "mode" "")]) diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-call-args-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-call-args-4.c index 98fdfc1d76c8..3c48e67561c7 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-call-args-4.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-call-args-4.c @@ -94,6 +94,7 @@ foo4 (vint8m1_t a1, vint16m2_t b1, vint32m4_t c1, vint64m8_t d1, vint8m1_t a2, /* ** foo5: +** vsetivli\tzero,0,e8,m1,ta,ma ** vmv1r\.v\tv8,v16 ** vmv1r\.v\tv9,v17 ** vmv1r\.v\tv10,v18 diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr117544.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr117544.c new file mode 100644 index 000000000000..af3532a3e00d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr117544.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv -mabi=lp64d -O3" } */ + +#include +void bar() __attribute__((riscv_vector_cc)); + +vint32m1_t foo(vint32m1_t a, vint32m1_t b) { + register vint32m1_t x asm("v24") = b; + bar(); + asm ("#xx %0"::"vr"(x) ); + return x; +} + +/* { dg-final { scan-assembler-times "vset" 2 } } */