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