https://gcc.gnu.org/g:0ca2ba3b88532aefff95036205fa0e6db0abe718
commit r17-1782-g0ca2ba3b88532aefff95036205fa0e6db0abe718 Author: Robin Dapp <[email protected]> Date: Wed Apr 29 09:37:19 2026 +0200 RISC-V: Example dependent filter for RVV widen overlap. 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. Diff: --- 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 1f285a342ba9..81d14df17ab6 100644 --- a/gcc/config/riscv/constraints.md +++ b/gcc/config/riscv/constraints.md @@ -184,6 +184,14 @@ (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 f429ca86a8fd..5fd2328062d9 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -175,6 +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 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 29d9aaf1ffde..cc1b8cd16a93 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -11217,6 +11217,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 00e64a854552..2b6888fc679c 100644 --- a/gcc/config/riscv/vector.md +++ b/gcc/config/riscv/vector.md @@ -4090,19 +4090,19 @@ ;; 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 cecf796e10cf..4cc6aa68b13f 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 b34a835b9659..f7d668c624b0 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 95af07166a31..3eed1198a705 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} } } */
