From: Robin Dapp <[email protected]>

This is an example of how a dependent filter would look like.
In RVV sources of widening instructions cannot overlap the
destination except in the highest-numbered part (for EMUL>1).

The dependent filter attached to the constraint "Wtt" is
implemented in riscv_widen_operand_ok.

gcc/ChangeLog:

        * config/riscv/constraints.md (TARGET_VECTOR ? V_REGS : NO_REGS):
        Add widen overlap dependent constraint.
        * config/riscv/riscv-protos.h (riscv_widen_overlap_ok): Declare.
        * config/riscv/riscv.cc (riscv_widen_operand_ok): New function.
        * config/riscv/vector.md: Use new constraint.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/rvv/base/pr112431-4.c: Un-xfail.
        * gcc.target/riscv/rvv/base/pr112431-5.c: Ditto.
        * gcc.target/riscv/rvv/base/pr112431-6.c: Ditto.
---
 gcc/config/riscv/constraints.md               |  8 ++++
 gcc/config/riscv/riscv-protos.h               |  2 +
 gcc/config/riscv/riscv.cc                     | 37 +++++++++++++++++++
 gcc/config/riscv/vector.md                    | 16 ++++----
 .../gcc.target/riscv/rvv/base/pr112431-4.c    |  2 +-
 .../gcc.target/riscv/rvv/base/pr112431-5.c    |  2 +-
 .../gcc.target/riscv/rvv/base/pr112431-6.c    |  2 +-
 7 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index 673b05954e1..4ebd9efc0bb 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -184,6 +184,14 @@ (define_register_constraint "vd" "TARGET_VECTOR ? VD_REGS 
: NO_REGS"
 (define_register_constraint "vm" "TARGET_VECTOR ? VM_REGS : NO_REGS"
   "A vector mask register (if available).")
 
+;; Dependent (dynamic) constraint:
+;; "The source group must overlap the highest-numbered part of the
+;; "destination group", i.e. this operand depends on operand 0.
+(define_register_constraint "Wtt" "TARGET_VECTOR ? V_REGS : NO_REGS"
+  "Vector widening overlap"
+  "riscv_widen_overlap_ok (regno, mode, ref_regno, ref_mode)"
+  "0")
+
 ;; This constraint is used to match instruction "csrr %0, vlenb" which is 
generated in "mov<mode>".
 ;; VLENB is a run-time constant which represent the vector register length in 
bytes.
 ;; BYTES_PER_RISCV_VECTOR represent runtime invariant of vector register 
length in bytes.
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 234d625441d..22e2343f605 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -174,6 +174,8 @@ extern poly_uint64 riscv_regmode_natural_size 
(machine_mode);
 extern bool riscv_vla_mode_p (machine_mode);
 extern bool riscv_tuple_mode_p (machine_mode);
 extern bool riscv_vls_mode_p (machine_mode);
+extern bool riscv_widen_overlap_ok (unsigned int, machine_mode,
+                                   unsigned int, machine_mode);
 extern int riscv_get_v_regno_alignment (machine_mode);
 extern bool riscv_shamt_matches_mask_p (int, HOST_WIDE_INT);
 extern void riscv_subword_address (rtx, rtx *, rtx *, rtx *, rtx *);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 8a737bb41b6..63f2a406163 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -11061,6 +11061,43 @@ riscv_hard_regno_nregs (unsigned int regno, 
machine_mode mode)
   return (GET_MODE_SIZE (mode).to_constant () + UNITS_PER_WORD - 1) / 
UNITS_PER_WORD;
 }
 
+/* Return true if REGNO in MODE can be used as source in a widening
+   instruction with destination WIDE_REGNO in WIDE_MODE.
+   This is true if either there is no overlap at all, or the overlap
+   is in the highest-numbered part of the destination group.  */
+
+bool
+riscv_widen_overlap_ok (unsigned int regno, machine_mode mode,
+                       unsigned int wide_regno, machine_mode wide_mode)
+{
+  /* If the referenced regno is no hard reg, allow everything.  */
+  if (wide_regno == INVALID_REGNUM)
+    return true;
+
+  if (!V_REG_P (regno) || !V_REG_P (wide_regno))
+    return false;
+
+  gcc_checking_assert (riscv_vector_mode_p (mode)
+                      && riscv_vector_mode_p (wide_mode));
+
+  unsigned int wide_nregs = riscv_hard_regno_nregs (wide_regno, wide_mode);
+  unsigned int nregs = riscv_hard_regno_nregs (regno, mode);
+
+  /* Overlap is only allowed in the highest-numbered part of the wider
+     destination.  */
+  if (regno == wide_regno)
+    return false;
+
+  if (regno >= wide_regno + (wide_nregs - nregs))
+    return true;
+
+  /* No overlap is OK.  */
+  if (regno < wide_regno)
+    return true;
+
+  return false;
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
 
 static bool
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 136ecdc787e..c31037a2e38 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -4050,19 +4050,19 @@ (define_insn "@pred_<optab><mode>"
 
 ;; Vector Double-Widening Sign-extend and Zero-extend.
 (define_insn "@pred_<optab><mode>_vf2"
-  [(set (match_operand:VWEXTI 0 "register_operand"            "=&vr,&vr")
+  [(set (match_operand:VWEXTI 0 "register_operand"              "=vr, vr, vd, 
vd")
        (if_then_else:VWEXTI
          (unspec:<VM>
-           [(match_operand:<VM> 1 "vector_mask_operand"         "vmWc1,vmWc1")
-            (match_operand 4 "vector_length_operand"            "  rvl,  rvl")
-            (match_operand 5 "const_int_operand"                "    i,    i")
-            (match_operand 6 "const_int_operand"                "    i,    i")
-            (match_operand 7 "const_int_operand"                "    i,    i")
+           [(match_operand:<VM> 1 "vector_mask_operand"         "Wc1,Wc1, vm, 
vm")
+            (match_operand 4 "vector_length_operand"            
"rvl,rvl,rvl,rvl")
+            (match_operand 5 "const_int_operand"                "  i,  i,  i,  
i")
+            (match_operand 6 "const_int_operand"                "  i,  i,  i,  
i")
+            (match_operand 7 "const_int_operand"                "  i,  i,  i,  
i")
             (reg:SI VL_REGNUM)
             (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
          (any_extend:VWEXTI
-           (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand" "   vr,   vr"))
-         (match_operand:VWEXTI 2 "vector_merge_operand"         "   vu,    
0")))]
+           (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand" 
"Wtt,Wtt,Wtt,Wtt"))
+         (match_operand:VWEXTI 2 "vector_merge_operand"         " vu,  0, vu,  
0")))]
   "TARGET_VECTOR && !TARGET_XTHEADVECTOR"
   "v<sz>ext.vf2\t%0,%3%p1"
   [(set_attr "type" "vext")
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr112431-4.c 
b/gcc/testsuite/gcc.target/riscv/rvv/base/pr112431-4.c
index cecf796e10c..4cc6aa68b13 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/pr112431-4.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr112431-4.c
@@ -101,4 +101,4 @@ foo (char const *buf, size_t len)
 /* { dg-final { scan-assembler-not {vmv2r} } } */
 /* { dg-final { scan-assembler-not {vmv4r} } } */
 /* { dg-final { scan-assembler-not {vmv8r} } } */
-/* { dg-final { scan-assembler-not {csrr} { xfail riscv*-*-* } } } */
+/* { dg-final { scan-assembler-not {csrr} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr112431-5.c 
b/gcc/testsuite/gcc.target/riscv/rvv/base/pr112431-5.c
index b34a835b965..f7d668c624b 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/pr112431-5.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr112431-5.c
@@ -65,4 +65,4 @@ foo (char const *buf, size_t len)
 /* { dg-final { scan-assembler-not {vmv2r} } } */
 /* { dg-final { scan-assembler-not {vmv4r} } } */
 /* { dg-final { scan-assembler-not {vmv8r} } } */
-/* { dg-final { scan-assembler-not {csrr} { xfail riscv*-*-* } } } */
+/* { dg-final { scan-assembler-not {csrr} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr112431-6.c 
b/gcc/testsuite/gcc.target/riscv/rvv/base/pr112431-6.c
index 95af07166a3..3eed1198a70 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/pr112431-6.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr112431-6.c
@@ -48,4 +48,4 @@ foo (char const *buf, size_t len)
 /* { dg-final { scan-assembler-not {vmv2r} } } */
 /* { dg-final { scan-assembler-not {vmv4r} } } */
 /* { dg-final { scan-assembler-not {vmv8r} } } */
-/* { dg-final { scan-assembler-not {csrr} { xfail riscv*-*-* } } } */
+/* { dg-final { scan-assembler-not {csrr} } } */
-- 
2.53.0

Reply via email to