]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Ensure vtype for full-register moves [PR117544].
authorRobin Dapp <rdapp@ventanamicro.com>
Thu, 21 Nov 2024 13:49:53 +0000 (14:49 +0100)
committerRobin Dapp <rdapp@ventanamicro.com>
Mon, 25 Nov 2024 15:01:48 +0000 (16:01 +0100)
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.

gcc/config/riscv/vector.md
gcc/testsuite/gcc.target/riscv/rvv/base/abi-call-args-4.c
gcc/testsuite/gcc.target/riscv/rvv/base/pr117544.c [new file with mode: 0644]

index 02cbd2f56f19debf7233d9e7399881c14a586ab4..57e3c34c1c5ad446386e6be04df962246c91cb37 100644 (file)
@@ -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,\
 ;; 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>")])
     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>")])
    (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>")])
index 98fdfc1d76c8b8348b12d87615f57ea89d2ee267..3c48e67561c7962d76a49d0a529c617444a730ce 100644 (file)
@@ -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 (file)
index 0000000..af3532a
--- /dev/null
@@ -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 } } */