From: Pan Li <[email protected]>

According to the RVV 1.0 spec, the widening ops like vzext.vf2
could have the source registers overlap on constraint, aka:

`
The destination EEW is greater than the source EEW, the source
EMUL is at least 1, and the overlap is in the highest-
numbered part of the destination register group.
`

This PATCH could like to re-enable it start from vzext.vf2 for
lmul m2.

gcc/ChangeLog:

        * config/riscv/constraints.md (TARGET_VECTOR ? V_REGS : NO_REGS):
        Add reg constraint wo21 and wo22.
        * config/riscv/riscv-protos.h (widening_valid_reg_group_p): Add
        new func decl to predicate valid overlap or not.
        * config/riscv/riscv-v.cc (widening_valid_reg_group_p): Add new
        func impl to predicate valid overlap or not.
        * config/riscv/riscv.md (none,wo21): Add new attr for reg
        overlap insns.
        * config/riscv/vector.md: Add 2 new alternative for m2 reg
        overlap for v[sz]ext.vf2.

Signed-off-by: Pan Li <[email protected]>
---
 gcc/config/riscv/constraints.md | 34 +++++++++++++++++++++++++++++++++
 gcc/config/riscv/riscv-protos.h |  1 +
 gcc/config/riscv/riscv-v.cc     | 18 +++++++++++++++++
 gcc/config/riscv/riscv.md       |  3 +++
 gcc/config/riscv/vector.md      | 24 ++++++++++++++---------
 5 files changed, 71 insertions(+), 9 deletions(-)

diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index 673b05954e1..82680d85121 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -344,3 +344,37 @@ (define_constraint "ads_Bext"
   "Sequence bit extract."
   (and (match_code "const_int")
        (match_test "(ival & (ival + 1)) == 0")))
+
+;; The RVV widening constraints for register overlap, aka dest EEW > src EEW.
+;; Quote from RVV spec 1.0:
+;;
+;; The destination EEW is greater than the source EEW, the source EMUL is at
+;; least 1, and the overlap is in the highest-numbered part of the destination
+;; register group (e.g., when LMUL=8, vzext.vf4 v0, v6 is legal, but a source
+;; of v0, v2, or v4 is not).
+;;
+;; Take vzext.vfN for example, only below cases are valid.
+;; Source EMUL = LMUL * (Source EEW / SEW) = LMUL * SEW / (N * SEW) = LMUL / N
+;;
+;; +-----------+------------+------------+----------+
+;; |           | LMUL = 8   | LMUL = 4   | LMUL = 2 |
+;; +-----------+------------+------------+----------+
+;; | vzext.vf2 | EMUL = 4   | EMUL = 2   | EMUL = 1 |
+;; +-----------+------------+------------+----------+
+;; |           | v0-7, v4-7 | v0-3, v2-3 | v0-1, v1 |
+;; +-----------+------------+------------+----------+
+;; | vzext.vf4 | EMUL = 2   | EMUL = 1   |          |
+;; +-----------+------------+------------+----------+
+;; |           | v0-7, v6-7 | v0-3, v3   |          |
+;; +-----------+------------+------------+----------+
+;; | vzext.vf8 | EMUL = 1   |            |          |
+;; +-----------+------------+------------+----------+
+;; |           | v0-7, v7   |            |          |
+;; +-----------+------------+------------+----------+
+;;
+(define_register_constraint "wo21" "TARGET_VECTOR ? V_REGS : NO_REGS"
+  "A constraint matches the reg group overlap with highest 1 num in 2 regs."
+  "(regno % 2) == 1")
+(define_register_constraint "wo22" "TARGET_VECTOR ? V_REGS : NO_REGS"
+  "A constraint matches the reg group overlap in 2 regs."
+  "(regno % 2) == 0")
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 0734c31ec56..ef8d12f1559 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -791,6 +791,7 @@ bool gather_scatter_valid_offset_p (machine_mode);
 HOST_WIDE_INT estimated_poly_value (poly_int64, unsigned int);
 bool whole_reg_to_reg_move_p (rtx *, machine_mode, int);
 bool splat_to_scalar_move_p (rtx *);
+bool widening_valid_reg_group_p (rtx_insn *, rtx);
 rtx get_fp_rounding_coefficient (machine_mode);
 }
 
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 29dc3ebccd6..60431d08135 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -6455,4 +6455,22 @@ splat_to_scalar_move_p (rtx *ops)
         && known_ge (GET_MODE_SIZE (Pmode), GET_MODE_SIZE (GET_MODE (ops[3])));
 }
 
+bool
+widening_valid_reg_group_p (rtx_insn *insn, rtx op_0)
+{
+  attr_reg_group_overlap overlap = get_attr_reg_group_overlap (insn);
+
+  switch (overlap)
+    {
+    case REG_GROUP_OVERLAP_NONE:
+      return true;
+    case REG_GROUP_OVERLAP_WO21:
+      return riscv_get_v_regno_alignment (GET_MODE (op_0)) == 2;
+    default:
+      break;
+    }
+
+  return false;
+}
+
 } // namespace riscv_vector
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 3fe0ad0ccdf..53790d1c9c4 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -593,6 +593,9 @@ (define_attr "spec_restriction_disabled" "no,yes"
        ]
        (const_string "no")))
 
+(define_attr "reg_group_overlap" "none,wo21"
+  (const_string "none"))
+
 ;; Attribute to control enable or disable instructions.
 (define_attr "enabled" "no,yes"
   (cond [
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 219ecdac68b..8f53745a2dc 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -4035,23 +4035,29 @@ (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"              "=wo22,  wo22, 
 ?&vr,  ?&vr")
        (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"         "vmWc1, vmWc1, 
vmWc1, vmWc1")
+            (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" " wo21,  wo21, 
   vr,    vr"))
+         (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")
-   (set_attr "mode" "<MODE>")])
+   (set_attr "mode" "<MODE>")
+   (set_attr "reg_group_overlap" "wo21,wo21,none,none")
+   (set (attr "enabled")
+    (if_then_else
+     (match_test "riscv_vector::widening_valid_reg_group_p (insn, 
operands[0])")
+     (const_string "yes")
+     (const_string "no")))])
 
 ;; Vector Quad-Widening Sign-extend and Zero-extend.
 (define_insn "@pred_<optab><mode>_vf4"
-- 
2.43.0

Reply via email to