aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRobin Dapp <rdapp@ventanamicro.com>2024-11-21 14:49:53 +0100
committerRobin Dapp <rdapp@ventanamicro.com>2024-11-25 16:01:48 +0100
commitb82a5810e7bcc82b933e16f9067879b9d22b85c7 (patch)
treeb993dd2397f6f4834f70f25fd79f925851f581dc /gcc
parent2e6b3308af6ddf87925321ddd2d387bfd352e410 (diff)
downloadgcc-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.md91
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/abi-call-args-4.c1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/pr117544.c14
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 } } */