https://gcc.gnu.org/g:5aec85a5f490895f90c1ef75f965ea100e80f50e

commit r16-2460-g5aec85a5f490895f90c1ef75f965ea100e80f50e
Author: Pan Li <pan2...@intel.com>
Date:   Wed Jul 23 12:08:02 2025 +0800

    RISC-V: Avoid vaaddu.vx combine pattern pollute VXRM csr
    
    The vaaddu.vx combine almost comes from avg_floor, it will
    requires the vxrm to be RDN.  But not all vaaddu.vx should
    depends on the RDN.  The vaaddu.vx combine should leverage
    the VXRM value as is instead of pollute them all to RDN.
    
    This patch would like to fix this and set it as is.
    
    gcc/ChangeLog:
    
            * config/riscv/autovec-opt.md (*uavg_floor_vx_<mode>): Rename
            from...
            (*<sat_op_v_vdup>_vx_<mode>): Rename to...
            (*<sat_op_vdup_v>_vx_<mode>): Rename to...
            * config/riscv/riscv-protos.h (enum insn_flags): Add vxrm
            RNE, ROD type.
            (enum insn_type): Add RNE_P, ROD_P type.
            (expand_vx_binary_vxrm_vec_vec_dup): Add new func decl.
            (expand_vx_binary_vxrm_vec_dup_vec): Ditto.
            * config/riscv/riscv-v.cc (get_insn_type_by_vxrm_val): Add
            helper to get insn type by vxrm value.
            (expand_vx_binary_vxrm_vec_vec_dup): Add new func impl
            to expand vec + vec_dup pattern.
            (expand_vx_binary_vxrm_vec_dup_vec): Ditto but for
            vec_dup + vec pattern.
            * config/riscv/vector-iterators.md: Add helper iterator
            for sat vx combine.
    
    Signed-off-by: Pan Li <pan2...@intel.com>

Diff:
---
 gcc/config/riscv/autovec-opt.md      | 28 ++++++++-----
 gcc/config/riscv/riscv-protos.h      | 12 +++++-
 gcc/config/riscv/riscv-v.cc          | 79 +++++++++++++++++++++++++++++++++++-
 gcc/config/riscv/vector-iterators.md | 16 ++++++++
 4 files changed, 122 insertions(+), 13 deletions(-)

diff --git a/gcc/config/riscv/autovec-opt.md b/gcc/config/riscv/autovec-opt.md
index 6dd4b77be006..65319960bc01 100644
--- a/gcc/config/riscv/autovec-opt.md
+++ b/gcc/config/riscv/autovec-opt.md
@@ -1714,7 +1714,7 @@
   }
   [(set_attr "type" "vialu")])
 
-(define_insn_and_split "*uavg_floor_vx_<mode>"
+(define_insn_and_split "*<sat_op_v_vdup>_vx_<mode>"
  [(set (match_operand:V_VLSI   0 "register_operand")
    (if_then_else:V_VLSI
     (unspec:<VM>
@@ -1730,7 +1730,7 @@
     (unspec:V_VLSI
      [(match_operand:V_VLSI    3 "register_operand")
       (vec_duplicate:V_VLSI
-       (match_operand:<VEL>    4 "register_operand"))] UNSPEC_VAADDU)
+       (match_operand:<VEL>    4 "reg_or_int_operand"))] VSAT_VX_OP_V_VDUP)
     (unspec:V_VLSI
      [(match_operand:DI        2 "register_operand")] UNSPEC_VUNDEF)))]
   "TARGET_VECTOR && can_create_pseudo_p ()"
@@ -1738,14 +1738,17 @@
   "&& 1"
   [(const_int 0)]
   {
-    insn_code code = code_for_pred_scalar (UNSPEC_VAADDU, <MODE>mode);
-    rtx ops[] = {operands[0], operands[3], operands[4]};
-    riscv_vector::emit_vlmax_insn (code, riscv_vector::BINARY_OP_VXRM_RDN, 
ops);
+    int vxrm_val = INTVAL (operands[9]);
+    riscv_vector::expand_vx_binary_vxrm_vec_vec_dup (operands[0], operands[3],
+                                                    operands[4],
+                                                    <VSAT_VX_OP_V_VDUP>,
+                                                    vxrm_val, <MODE>mode);
+
     DONE;
   }
   [(set_attr "type" "vaalu")])
 
-(define_insn_and_split "*uavg_floor_vx_<mode>"
+(define_insn_and_split "*<sat_op_vdup_v>_vx_<mode>"
  [(set (match_operand:V_VLSI   0 "register_operand")
    (if_then_else:V_VLSI
     (unspec:<VM>
@@ -1760,8 +1763,8 @@
       (reg:SI VXRM_REGNUM)] UNSPEC_VPREDICATE)
     (unspec:V_VLSI
      [(vec_duplicate:V_VLSI
-       (match_operand:<VEL>    4 "register_operand"))
-      (match_operand:V_VLSI    3 "register_operand")] UNSPEC_VAADDU)
+       (match_operand:<VEL>    4 "reg_or_int_operand"))
+      (match_operand:V_VLSI    3 "register_operand")] VSAT_VX_OP_VDUP_V)
     (unspec:V_VLSI
      [(match_operand:DI        2 "register_operand")] UNSPEC_VUNDEF)))]
   "TARGET_VECTOR && can_create_pseudo_p ()"
@@ -1769,9 +1772,12 @@
   "&& 1"
   [(const_int 0)]
   {
-    insn_code code = code_for_pred_scalar (UNSPEC_VAADDU, <MODE>mode);
-    rtx ops[] = {operands[0], operands[3], operands[4]};
-    riscv_vector::emit_vlmax_insn (code, riscv_vector::BINARY_OP_VXRM_RDN, 
ops);
+    int vxrm_val = INTVAL (operands[9]);
+    riscv_vector::expand_vx_binary_vxrm_vec_dup_vec (operands[0], operands[3],
+                                                    operands[4],
+                                                    <VSAT_VX_OP_VDUP_V>,
+                                                    vxrm_val, <MODE>mode);
+
     DONE;
   }
   [(set_attr "type" "vaalu")])
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 0379f2ce2567..539321ff95b8 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -414,8 +414,14 @@ enum insn_flags : unsigned int
   /* Means INSN has VXRM operand and the value is VXRM_RNU.  */
   VXRM_RNU_P = 1 << 20,
 
+  /* Means INSN has VXRM operand and the value is VXRM_RNE.  */
+  VXRM_RNE_P = 1 << 21,
+
   /* Means INSN has VXRM operand and the value is VXRM_RDN.  */
-  VXRM_RDN_P = 1 << 21,
+  VXRM_RDN_P = 1 << 22,
+
+  /* Means INSN has VXRM operand and the value is VXRM_ROD.  */
+  VXRM_ROD_P = 1 << 23,
 };
 
 enum insn_type : unsigned int
@@ -477,7 +483,9 @@ enum insn_type : unsigned int
   BINARY_OP_TUMA = __MASK_OP_TUMA | BINARY_OP_P,
   BINARY_OP_FRM_DYN = BINARY_OP | FRM_DYN_P,
   BINARY_OP_VXRM_RNU = BINARY_OP | VXRM_RNU_P,
+  BINARY_OP_VXRM_RNE = BINARY_OP | VXRM_RNE_P,
   BINARY_OP_VXRM_RDN = BINARY_OP | VXRM_RDN_P,
+  BINARY_OP_VXRM_ROD = BINARY_OP | VXRM_ROD_P,
 
   /* Ternary operator. Always have real merge operand.  */
   TERNARY_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
@@ -672,6 +680,8 @@ void expand_vec_oct_sstrunc (rtx, rtx, machine_mode, 
machine_mode,
                             machine_mode);
 void expand_vx_binary_vec_dup_vec (rtx, rtx, rtx, rtx_code, machine_mode);
 void expand_vx_binary_vec_vec_dup (rtx, rtx, rtx, rtx_code, machine_mode);
+void expand_vx_binary_vxrm_vec_vec_dup (rtx, rtx, rtx, int, int, machine_mode);
+void expand_vx_binary_vxrm_vec_dup_vec (rtx, rtx, rtx, int, int, machine_mode);
 #endif
 bool sew64_scalar_helper (rtx *, rtx *, rtx, machine_mode,
                          bool, void (*)(rtx *, rtx), enum avl_type);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 9f6ae79326e4..54eb8c66320d 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -351,9 +351,12 @@ public:
       add_rounding_mode_operand (FRM_RNE);
     else if (m_insn_flags & VXRM_RNU_P)
       add_rounding_mode_operand (VXRM_RNU);
+    else if (m_insn_flags & VXRM_RNE_P)
+      add_rounding_mode_operand (VXRM_RNE);
     else if (m_insn_flags & VXRM_RDN_P)
       add_rounding_mode_operand (VXRM_RDN);
-
+    else if (m_insn_flags & VXRM_ROD_P)
+      add_rounding_mode_operand (VXRM_ROD);
 
     if (insn_data[(int) icode].n_operands != m_opno)
       internal_error ("invalid number of operands for insn %s, "
@@ -5650,6 +5653,80 @@ expand_vx_binary_vec_dup_vec (rtx op_0, rtx op_1, rtx 
op_2,
   emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops);
 }
 
+static enum insn_type
+get_insn_type_by_vxrm_val (int vxrm_val)
+{
+  enum insn_type itype;
+
+  switch (vxrm_val)
+    {
+    case VXRM_RNU:
+      itype = BINARY_OP_VXRM_RNU;
+      break;
+    case VXRM_RNE:
+      itype = BINARY_OP_VXRM_RNE;
+      break;
+    case VXRM_RDN:
+      itype = BINARY_OP_VXRM_RDN;
+      break;
+    case VXRM_ROD:
+      itype = BINARY_OP_VXRM_ROD;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  return itype;
+}
+
+/* Expand the binary vx combine with the format like v2 = vop(v1, vec_dup(x))
+   and its' vxrm value.  Aka the second op comes from the vec_duplicate,
+   and the first op is the vector reg.  */
+
+void
+expand_vx_binary_vxrm_vec_vec_dup (rtx op_0, rtx op_1, rtx op_2, int unspec,
+                                  int vxrm_val, machine_mode mode)
+{
+  enum insn_code icode;
+  enum insn_type itype = get_insn_type_by_vxrm_val (vxrm_val);
+  rtx ops[] = {op_0, op_1, op_2};
+
+  switch (unspec)
+    {
+    case UNSPEC_VAADDU:
+      icode = code_for_pred_scalar (unspec, mode);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  emit_vlmax_insn (icode, itype, ops);
+}
+
+/* Expand the binary vx combine with the format like v2 = vop(vec_dup(x), v1)
+   and its' vxrm value.  Aka the second op comes from the vec_duplicate,
+   and the first op is the vector reg.  */
+
+void
+expand_vx_binary_vxrm_vec_dup_vec (rtx op_0, rtx op_1, rtx op_2, int unspec,
+                                  int vxrm_val, machine_mode mode)
+{
+  enum insn_code icode;
+  enum insn_type itype = get_insn_type_by_vxrm_val (vxrm_val);
+  rtx ops[] = {op_0, op_1, op_2};
+
+  switch (unspec)
+    {
+    case UNSPEC_VAADDU:
+      icode = code_for_pred_scalar (unspec, mode);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  emit_vlmax_insn (icode, itype, ops);
+}
+
 /* Expand the binary vx combine with the format like v2 = vop(v1, vec_dup(x)).
    Aka the second op comes from the vec_duplicate, and the first op is
    the vector reg.  */
diff --git a/gcc/config/riscv/vector-iterators.md 
b/gcc/config/riscv/vector-iterators.md
index 5f6cc42b46b9..dbb48a4393ac 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -4013,6 +4013,14 @@
                              UNSPEC_VASUBU UNSPEC_VASUB UNSPEC_VSMUL
                              UNSPEC_VSSRL UNSPEC_VSSRA])
 
+(define_int_iterator VSAT_VX_OP_V_VDUP [
+  UNSPEC_VAADDU
+])
+
+(define_int_iterator VSAT_VX_OP_VDUP_V [
+  UNSPEC_VAADDU
+])
+
 (define_int_iterator VSAT_ARITH_OP [UNSPEC_VAADDU UNSPEC_VAADD
                                    UNSPEC_VASUBU UNSPEC_VASUB UNSPEC_VSMUL])
 (define_int_iterator VSAT_SHIFT_OP [UNSPEC_VSSRL UNSPEC_VSSRA])
@@ -4047,6 +4055,14 @@
                                (UNSPEC_VSSRA "vsshift") (UNSPEC_VNCLIP 
"vnclip")
                                (UNSPEC_VNCLIPU "vnclip")])
 
+(define_int_attr sat_op_v_vdup [
+  (UNSPEC_VAADDU "aaddu")
+])
+
+(define_int_attr sat_op_vdup_v [
+  (UNSPEC_VAADDU "aaddu")
+])
+
 (define_int_attr misc_op [(UNSPEC_VMSBF "sbf") (UNSPEC_VMSIF "sif") 
(UNSPEC_VMSOF "sof")
                          (UNSPEC_VFRSQRT7 "rsqrt7")])

Reply via email to