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