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.
`
However, the lra for now doesn't try to overlap as much as
possible. The overlap rvv register pair(s) in the constraint
is avaiable but the lra is the final decicsion maker to pick
the avaiable register pairs.
Therefore, from the test cases we can see, not all registers
in rvv will overlap for insn vsext.vf, even if it could
overlap up to a point.
gcc/ChangeLog:
* config/riscv/constraints.md (Wtt): Rename to Wov to
indicate widen overlap vector regs.
* config/riscv/riscv-protos.h (riscv_widen_overlap_ok):
Rename from...
(riscv_widen_reg_p): Rename to...
* config/riscv/riscv.cc (riscv_widen_overlap_ok): Rename
from...
(riscv_widen_reg_p): Rename to... And take care of
overlap and non-overlap in constraint.
* config/riscv/vector.md: Rename to Wov.
Signed-off-by: Pan Li <[email protected]>
---
gcc/config/riscv/constraints.md | 35 ++++++++++++++++++++++++++++-----
gcc/config/riscv/riscv-protos.h | 4 ++--
gcc/config/riscv/riscv.cc | 27 +++++++++++++++----------
gcc/config/riscv/vector.md | 2 +-
4 files changed, 50 insertions(+), 18 deletions(-)
diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index 81d14df17ab..ec0e04cf4de 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -184,12 +184,37 @@ (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"
+;; Dependent (dynamic) constraint for widening overlap:
+;; 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 "Wov" "TARGET_VECTOR ? V_REGS : NO_REGS"
"Vector widening overlap"
- "riscv_widen_overlap_ok (regno, mode, ref_regno, ref_mode)"
+ "riscv_widen_reg_p (regno, mode, ref_regno, ref_mode)"
"0")
;; This constraint is used to match instruction "csrr %0, vlenb" which is
generated in "mov<mode>".
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 5fd2328062d..ddc8eb6a774 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -175,8 +175,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 bool riscv_widen_reg_p (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 d5eab542131..a61a534da4f 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -11248,35 +11248,42 @@ riscv_hard_regno_nregs (unsigned int regno,
machine_mode mode)
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)
+riscv_widen_reg_p (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))
+ if (!V_REG_P (regno) || !V_REG_P (wide_regno) || regno == wide_regno)
return false;
gcc_checking_assert (riscv_vector_mode_p (mode)
&& riscv_vector_mode_p (wide_mode));
+ if (riscv_tuple_mode_p (mode) || riscv_tuple_mode_p (wide_mode))
+ return false;
+
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)
+ if (wide_nregs < nregs)
return false;
+ else if (wide_nregs == nregs) { /* Source LMUL < 1. */
+ gcc_checking_assert (nregs == 1);
- if (regno >= wide_regno + (wide_nregs - nregs))
return true;
+ }
- /* No overlap is OK. */
- if (regno < wide_regno)
+ gcc_checking_assert ((wide_nregs % nregs) == 0);
+
+ /* No overlap. */
+ if (regno + nregs <= wide_regno || wide_regno + wide_nregs <= regno)
return true;
- return false;
+ unsigned int highest_num = wide_nregs - nregs;
+
+ return (regno % wide_nregs) == highest_num;
}
/* Implement TARGET_HARD_REGNO_MODE_OK. */
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 2b6888fc679..500546bdf98 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -4101,7 +4101,7 @@ (define_insn "@pred_<optab><mode>_vf2"
(reg:SI VL_REGNUM)
(reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
(any_extend:VWEXTI
- (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand"
"Wtt,Wtt,Wtt,Wtt"))
+ (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand"
"Wov,Wov,Wov,Wov"))
(match_operand:VWEXTI 2 "vector_merge_operand" " vu, 0, vu,
0")))]
"TARGET_VECTOR && !TARGET_XTHEADVECTOR"
"v<sz>ext.vf2\t%0,%3%p1"
--
2.43.0