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

Reply via email to