From: Robin Dapp Date: Wed, 29 Apr 2026 07:37:19 +0000 (+0200) Subject: RISC-V: Example dependent filter for RVV widen overlap. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0ca2ba3b88532aefff95036205fa0e6db0abe718;p=thirdparty%2Fgcc.git 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 --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md index 1f285a342ba..81d14df17ab 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". ;; 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 f429ca86a8f..5fd2328062d 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 29d9aaf1ffd..cc1b8cd16a9 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 00e64a85455..2b6888fc679 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__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: - [(match_operand: 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: 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: 3 "register_operand" " vr, vr")) - (match_operand:VWEXTI 2 "vector_merge_operand" " vu, 0")))] + (match_operand: 3 "register_operand" "Wtt,Wtt,Wtt,Wtt")) + (match_operand:VWEXTI 2 "vector_merge_operand" " vu, 0, vu, 0")))] "TARGET_VECTOR && !TARGET_XTHEADVECTOR" "vext.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} } } */