pr118182-2.c fails on gcc-14 because it lacks the late_combine passes,
particularly the one that runs after register allocation.

Even in the trunk, the predicate broadcast for the add reduction is
expanded and register-allocated as _zvfh, taking up an unneeded scalar
register to hold the constant to be vec_duplicated.

It is the late combine pass after register allocation that substitutes
this unneeded scalar register into the vec_duplicate, resolving to the
_zero or _imm insns.

It's easy enough and more efficient to expand pred_broadcast to the
insns that take the already-duplicated vector constant, when the
operands satisfy the predicates of the _zero or _imm insns.

Regression-tested with gcc-14 x86_64-linux-gnu-hosted crosses to
riscv64-elf and riscv32-elf.  Also smoke-tested on trunk, still passing
the pr118182-2.c test with a cross to riscv64-elf.  Ok to install?


for  gcc/ChangeLog

        PR target/118182
        * config/riscv/vector.md (@pred_broadcast<mode>): Expand to
        _zero and _imm variants without vec_duplicate.
---
 gcc/config/riscv/vector.md |   22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 51eb64fb12264..3ab4d76e6c6a7 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -2136,18 +2136,34 @@ (define_expand "@pred_broadcast<mode>"
             (match_operand 7 "const_int_operand")
             (reg:SI VL_REGNUM)
             (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
-         (vec_duplicate:V_VLS
-           (match_operand:<VEL> 3 "direct_broadcast_operand"))
+         ;; (vec_duplicate:V_VLS ;; wrapper activated by wrap_vec_dup below.
+         (match_operand:<VEL> 3 "direct_broadcast_operand") ;; )
          (match_operand:V_VLS 2 "vector_merge_operand")))]
   "TARGET_VECTOR"
 {
   /* Transform vmv.v.x/vfmv.v.f (avl = 1) into vmv.s.x since vmv.s.x/vfmv.s.f
      has better chances to do vsetvl fusion in vsetvl pass.  */
+  bool wrap_vec_dup = true;
+  rtx vec_cst = NULL_RTX;
   if (riscv_vector::splat_to_scalar_move_p (operands))
     {
       operands[1] = riscv_vector::gen_scalar_move_mask (<VM>mode);
       operands[3] = force_reg (<VEL>mode, operands[3]);
     }
+  else if (immediate_operand (operands[3], <VEL>mode)
+          && (vec_cst = gen_const_vec_duplicate (<MODE>mode, operands[3]))
+          && (/* -> pred_broadcast<mode>_zero */
+              (vector_least_significant_set_mask_operand (operands[1],
+                                                          <VM>mode)
+               && vector_const_0_operand (vec_cst, <MODE>mode))
+              || (/* pred_broadcast<mode>_imm */
+                  vector_all_trues_mask_operand (operands[1], <VM>mode)
+                  && vector_const_int_or_double_0_operand (vec_cst,
+                                                           <MODE>mode))))
+    {
+      operands[3] = vec_cst;
+      wrap_vec_dup = false;
+    }
   /* Handle vmv.s.x instruction (Wb1 mask) which has memory scalar.  */
   else if (satisfies_constraint_Wdm (operands[3]))
     {
@@ -2191,6 +2207,8 @@ (define_expand "@pred_broadcast<mode>"
     ;
   else
     operands[3] = force_reg (<VEL>mode, operands[3]);
+  if (wrap_vec_dup)
+    operands[3] = gen_rtx_VEC_DUPLICATE (<MODE>mode, operands[3]);
 })
 
 (define_insn_and_split "*pred_broadcast<mode>"


-- 
Alexandre Oliva, happy hacker            https://blog.lx.oliva.nom.br/
Free Software Activist     FSFLA co-founder     GNU Toolchain Engineer
More tolerance and less prejudice are key for inclusion and diversity.
Excluding neuro-others for not behaving ""normal"" is *not* inclusive!

Reply via email to