[v1,1/5] RISC-V: Allow RVV register overlap for v[sz]ext.vf4

Message ID 20260708142206.215039-2-pan2.li@intel.com
State Committed
Delegated to: Robin Dapp
Headers
Series Support RVV register overlap for v[sz]ext.vf4 |

Checks

Context Check Description
rivoscibot/toolchain-ci-rivos-apply-patch success Patch applied
rivoscibot/toolchain-ci-rivos-lint warning Lint failed
rivoscibot/toolchain-ci-rivos-build--newlib-rv64gcv-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gc_zba_zbb_zbc_zbs-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gcv-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-test fail Testing failed

Commit Message

Li, Pan2 July 8, 2026, 2:20 p.m. UTC
  From: Pan Li <pan2.li@intel.com>

Like v[sz]ext.vf2, allow the rvv register overlap
for v[sz]ext.vf4.

gcc/ChangeLog:

	* config/riscv/riscv-protos.h (is_frac_vlmul_p): Add new func
	decl to predicate frac vlmul for a mode.
	* config/riscv/riscv-v.cc (is_frac_vlmul_p): Add new func impl
	for above.
	(riscv_v_widen_constraint_ok): Add Source and Dest lmul less
	and equal 1 handling.
	* config/riscv/vector.md: Leverage widen constraint Wvr.

Signed-off-by: Pan Li <pan2.li@intel.com>
---
 gcc/config/riscv/riscv-protos.h |  1 +
 gcc/config/riscv/riscv-v.cc     | 26 +++++++++++++++++++++++++-
 gcc/config/riscv/vector.md      | 16 ++++++++--------
 3 files changed, 34 insertions(+), 9 deletions(-)
  

Comments

Robin Dapp July 9, 2026, 8:31 a.m. UTC | #1
> +bool
> +is_frac_vlmul_p (machine_mode mode)
> +{
> +  switch (get_vlmul (mode))
> +    {
> +    case LMUL_1:
> +    case LMUL_2:
> +    case LMUL_4:
> +    case LMUL_8:
> +      return false;
> +    case LMUL_F8:
> +    case LMUL_F4:
> +    case LMUL_F2:
> +      return true;
> +    default:
> +      break;
> +    }
> +
> +  gcc_unreachable ();
> +}

The only concern I have here is that we might want to (prematurely) optimize 
this to something like return get_vlmul > 4; rather than a full-blown switch 
case (thinking that the dynamic filter is being called very often).
On the other hand your version is more readable.

I guess easy enough to change later, so OK.
  
Li, Pan2 July 10, 2026, 1:43 a.m. UTC | #2
Thanks Robin.

> I guess easy enough to change later, so OK.

I see, will take care of this if there is a perf problem later.

Pan

-----Original Message-----
From: Robin Dapp <rdapp.gcc@gmail.com> 
Sent: Thursday, July 9, 2026 4:32 PM
To: Li, Pan2 <pan2.li@intel.com>; gcc-patches@gcc.gnu.org
Cc: juzhe.zhong@rivai.ai; kito.cheng@gmail.com; jeffreyalaw@gmail.com; rdapp.gcc@gmail.com; Chen, Ken <ken.chen@intel.com>; Liu, Hongtao <hongtao.liu@intel.com>
Subject: Re: [PATCH v1 1/5] RISC-V: Allow RVV register overlap for v[sz]ext.vf4

> +bool
> +is_frac_vlmul_p (machine_mode mode)
> +{
> +  switch (get_vlmul (mode))
> +    {
> +    case LMUL_1:
> +    case LMUL_2:
> +    case LMUL_4:
> +    case LMUL_8:
> +      return false;
> +    case LMUL_F8:
> +    case LMUL_F4:
> +    case LMUL_F2:
> +      return true;
> +    default:
> +      break;
> +    }
> +
> +  gcc_unreachable ();
> +}

The only concern I have here is that we might want to (prematurely) optimize 
this to something like return get_vlmul > 4; rather than a full-blown switch 
case (thinking that the dynamic filter is being called very often).
On the other hand your version is more readable.

I guess easy enough to change later, so OK.

-- 
Regards
 Robin
  

Patch

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index e7bce0db7a3..b72d660f37e 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -642,6 +642,7 @@  void emit_nonvlmax_insn (unsigned, unsigned, rtx *, rtx);
 void emit_avltype_insn (unsigned, unsigned, rtx *, avl_type, rtx = nullptr);
 void emit_vlmax_insn_lra (unsigned, unsigned, rtx *, rtx);
 enum vlmul_type get_vlmul (machine_mode);
+bool is_frac_vlmul_p (machine_mode);
 rtx get_vlmax_rtx (machine_mode);
 unsigned int get_ratio (machine_mode);
 unsigned int get_nf (machine_mode);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 48cc56ea3d9..c4e62cfc372 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -2054,6 +2054,27 @@  get_vlmul (machine_mode mode)
   return mode_vtype_infos.vlmul[mode];
 }
 
+bool
+is_frac_vlmul_p (machine_mode mode)
+{
+  switch (get_vlmul (mode))
+    {
+    case LMUL_1:
+    case LMUL_2:
+    case LMUL_4:
+    case LMUL_8:
+      return false;
+    case LMUL_F8:
+    case LMUL_F4:
+    case LMUL_F2:
+      return true;
+    default:
+      break;
+    }
+
+  gcc_unreachable ();
+}
+
 /* Return the VLMAX rtx of vector mode MODE.  */
 rtx
 get_vlmax_rtx (machine_mode mode)
@@ -6505,7 +6526,7 @@  riscv_v_widen_constraint_ok (unsigned int regno, machine_mode mode,
   unsigned int wide_nregs = riscv_hard_regno_nregs (wide_regno, wide_mode);
   unsigned int nregs = riscv_hard_regno_nregs (regno, mode);
 
-  if (wide_nregs == nregs) /* Source LMUL < 1.  */
+  if (wide_nregs == nregs) /* Dest LMUL <= 1.  */
     {
       gcc_checking_assert (nregs == 1);
 
@@ -6519,6 +6540,9 @@  riscv_v_widen_constraint_ok (unsigned int regno, machine_mode mode,
   if (regno + nregs <= wide_regno || wide_regno + wide_nregs <= regno)
     return true;
 
+  if (is_frac_vlmul_p (mode)) /* Source LMUL < 1.  */
+    return false;
+
   unsigned int highest_num = wide_nregs - nregs;
 
   return (regno % wide_nregs) == highest_num;
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 5d22edb0f3f..a5ebc85b764 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -4110,19 +4110,19 @@  (define_insn "@pred_<optab><mode>_vf2"
 
 ;; Vector Quad-Widening Sign-extend and Zero-extend.
 (define_insn "@pred_<optab><mode>_vf4"
-  [(set (match_operand:VQEXTI 0 "register_operand"          "=&vr,&vr")
+  [(set (match_operand:VQEXTI 0 "register_operand"             "=vr,  vr,  vd,  vd")
 	(if_then_else:VQEXTI
 	  (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:VQEXTI
-	    (match_operand:<V_QUAD_TRUNC> 3 "register_operand" "   vr,   vr"))
-	  (match_operand:VQEXTI 2 "vector_merge_operand"       "   vu,    0")))]
+	    (match_operand:<V_QUAD_TRUNC> 3 "register_operand" "Wvr, Wvr, Wvr, Wvr"))
+	  (match_operand:VQEXTI 2 "vector_merge_operand"       " vu,   0,  vu,   0")))]
   "TARGET_VECTOR && !TARGET_XTHEADVECTOR"
   "v<sz>ext.vf4\t%0,%3%p1"
   [(set_attr "type" "vext")