diff options
author | Robin Dapp <rdapp@ventanamicro.com> | 2024-11-21 14:49:53 +0100 |
---|---|---|
committer | Robin Dapp <rdapp@ventanamicro.com> | 2024-11-25 16:01:48 +0100 |
commit | b82a5810e7bcc82b933e16f9067879b9d22b85c7 (patch) | |
tree | b993dd2397f6f4834f70f25fd79f925851f581dc /gcc | |
parent | 2e6b3308af6ddf87925321ddd2d387bfd352e410 (diff) | |
download | gcc-b82a5810e7bcc82b933e16f9067879b9d22b85c7.zip gcc-b82a5810e7bcc82b933e16f9067879b9d22b85c7.tar.gz gcc-b82a5810e7bcc82b933e16f9067879b9d22b85c7.tar.bz2 |
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<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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/riscv/vector.md | 91 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/rvv/base/abi-call-args-4.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/rvv/base/pr117544.c | 14 |
3 files changed, 99 insertions, 7 deletions
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md index 02cbd2f..57e3c34 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<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 @@ 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 @@ (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 98fdfc1..3c48e67 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 0000000..af3532a --- /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 } } */ |