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: Add more comments for
the v[sz]ext.vf2 reg overlap.
* config/riscv/riscv.cc (riscv_widen_overlap_ok): Take
care of the reg overlap.
* config/riscv/vector.md: Add low priority constraint.
Signed-off-by: Pan Li <[email protected]>
---
gcc/config/riscv/constraints.md | 31 ++++++++++++++++++++++++++++---
gcc/config/riscv/riscv.cc | 30 +++++++++++++++++++++---------
gcc/config/riscv/vector.md | 16 ++++++++--------
3 files changed, 57 insertions(+), 20 deletions(-)
diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index 81d14df17ab..cca4ea4279b 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -184,9 +184,34 @@ (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.
+;; 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 "Wtt" "TARGET_VECTOR ? V_REGS : NO_REGS"
"Vector widening overlap"
"riscv_widen_overlap_ok (regno, mode, ref_regno, ref_mode)"
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index cc1b8cd16a9..46cab20e664 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -11236,22 +11236,34 @@ riscv_widen_overlap_ok (unsigned int regno,
machine_mode mode,
gcc_checking_assert (riscv_vector_mode_p (mode)
&& riscv_vector_mode_p (wide_mode));
+ if (regno == wide_regno)
+ 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)
+ /* Reg num alignment. */
+ if (wide_nregs < nregs)
return false;
- if (regno >= wide_regno + (wide_nregs - nregs))
- return true;
+ if (wide_nregs == nregs) { /* Source LMUL < 1, and vd is not equal to vs. */
+ gcc_checking_assert (nregs == 1);
+ gcc_checking_assert (regno != wide_regno);
- /* No overlap is OK. */
- if (regno < wide_regno)
- return true;
+ return true;
+ }
- return false;
+ gcc_checking_assert (wide_nregs > nregs);
+ gcc_checking_assert ((wide_nregs % nregs) == 0);
+
+ /* No overlap, leave it to low priority alternative(s). This could allow
+ the lra overlap registers as much as possible. */
+ if (regno + nregs <= wide_regno || wide_regno + wide_nregs <= regno)
+ 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..2be3357b0bd 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -4090,19 +4090,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, vd,
vd")
+ [(set (match_operand:VWEXTI 0 "register_operand" "=vr, vr, vd,
vd, ?&vr, ?&vr, ?&vd, ?&vd")
(if_then_else:VWEXTI
(unspec:<VM>
- [(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")
+ [(match_operand:<VM> 1 "vector_mask_operand" "Wc1,Wc1, vm,
vm, Wc1, Wc1, vm, vm")
+ (match_operand 4 "vector_length_operand"
"rvl,rvl,rvl,rvl, rvl, rvl, rvl, rvl")
+ (match_operand 5 "const_int_operand" " i, i, i,
i, i, i, i, i")
+ (match_operand 6 "const_int_operand" " i, i, i,
i, i, i, i, i")
+ (match_operand 7 "const_int_operand" " i, i, i,
i, 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"
"Wtt,Wtt,Wtt,Wtt"))
- (match_operand:VWEXTI 2 "vector_merge_operand" " vu, 0, vu,
0")))]
+ (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand"
"Wtt,Wtt,Wtt,Wtt, vr, vr, vd, vd"))
+ (match_operand:VWEXTI 2 "vector_merge_operand" " vu, 0, vu,
0, vu, 0, vu, 0")))]
"TARGET_VECTOR && !TARGET_XTHEADVECTOR"
"v<sz>ext.vf2\t%0,%3%p1"
[(set_attr "type" "vext")
--
2.43.0