]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Avoid vaaddu.vx combine pattern pollute VXRM csr
authorPan Li <pan2.li@intel.com>
Wed, 23 Jul 2025 04:08:02 +0000 (12:08 +0800)
committerPan Li <pan2.li@intel.com>
Thu, 24 Jul 2025 01:57:49 +0000 (09:57 +0800)
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.li@intel.com>
gcc/config/riscv/autovec-opt.md
gcc/config/riscv/riscv-protos.h
gcc/config/riscv/riscv-v.cc
gcc/config/riscv/vector-iterators.md

index 6dd4b77be00685ee92c8ebc56abe08061994865f..65319960bc015b2e5d93821da7fcaa73c592c88f 100644 (file)
   }
   [(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>
     (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 ()"
   "&& 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>
       (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 ()"
   "&& 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")])
index 0379f2ce25678ea9d297c866b07683168c84de0a..539321ff95b8379f24cf92868dcaa27aabd37bac 100644 (file)
@@ -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);
index 9f6ae79326e4cab22d2fbc94fb27d60782651e92..54eb8c66320dc1d369c79f09fc1b010bbe70e4aa 100644 (file)
@@ -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.  */
index 5f6cc42b46b9929511bcd9d332c4b74b82c02c83..dbb48a4393acd4091d742321d68b28e18c5754f6 100644 (file)
                              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])
                                (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")])