Hi, 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 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. Regtested on rv64gcv but the CI knows best :) Regards Robin PR target/117544 gcc/ChangeLog: * config/riscv/vector.md (*mov<mode>_whole): Split. (*mov<mode>_fract): Ditto. (*mov<mode>): Ditto. (*mov<mode>_vls): Ditto. (*mov<mode>_reg_whole_vtype): New pattern with vtype use. (*mov<mode>_fract_vtype): Ditto. (*mov<mode>_vtype): Ditto. (*mov<mode>_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. --- gcc/config/riscv/vector.md | 91 +++++++++++++++++-- .../riscv/rvv/base/abi-call-args-4.c | 1 + .../gcc.target/riscv/rvv/base/pr117544.c | 14 +++ 3 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/pr117544.c diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md index 02cbd2f56f1..57e3c34c1c5 100644 --- a/gcc/config/riscv/vector.md +++ b/gcc/config/riscv/vector.md @@ -42,7 +42,8 @@ (define_attr "has_vtype_op" "false,true" (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 @@ (define_expand "mov<mode>" ;; which is not the pattern we want. ;; According the facts above, we make "*mov<mode>_whole" includes load/store/move for whole ;; vector modes according to '-march' and "*mov<mode>_fract" only include fractional vector modes. -(define_insn "*mov<mode>_whole" +(define_insn_and_split "*mov<mode>_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<sew>.v\t%0,%1 vs%m1r.v\t%1,%0 - vmv%m1r.v\t%0,%1" + #" + "&& !memory_operand (operands[0], <MODE>mode) + && !memory_operand (operands[1], <MODE>mode)" + [(parallel [(set (match_dup 0) (match_dup 1)) + (use (reg:SI VTYPE_REGNUM))])] + "" [(set_attr "type" "vldr,vstr,vmov") (set_attr "mode" "<MODE>")]) -(define_insn "*mov<mode>_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<mode>_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" "<MODE>")]) + +(define_insn_and_split "*mov<mode>_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" "<MODE>")]) + +(define_insn "*mov<mode>_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" "<MODE>")]) @@ -1249,10 +1287,23 @@ (define_expand "mov<mode>" DONE; }) -(define_insn "*mov<mode>" +(define_insn_and_split "*mov<mode>" [(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" "<MODE>")]) + +(define_insn "*mov<mode>_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" "<MODE>")]) @@ -1451,18 +1502,44 @@ (define_insn_and_split "*mov<VLS_AVL_REG:mode><P:mode>_lra" (set (attr "mode_idx") (const_int INVALID_ATTRIBUTE))] ) -(define_insn "*mov<mode>_vls" +(define_insn_and_split "*mov<mode>_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" "<MODE>")]) + +(define_insn "*mov<mode>_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" "<MODE>")]) -(define_insn "*mov<mode>_vls" +(define_insn_and_split "*mov<mode>_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" "<MODE>")]) + +(define_insn "*mov<mode>_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" "<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 98fdfc1d76c..3c48e67561c 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 00000000000..af3532a3e00 --- /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 <riscv_vector.h> +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 } } */ -- 2.47.0