From: Pan Li <pan2...@intel.com>

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>
---
 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 d8849422791..dc669c57001 100644
--- a/gcc/config/riscv/autovec-opt.md
+++ b/gcc/config/riscv/autovec-opt.md
@@ -1714,7 +1714,7 @@ (define_insn_and_split "*<optab>_vx_<mode>"
   }
   [(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 @@ (define_insn_and_split "*uavg_floor_vx_<mode>"
     (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 @@ (define_insn_and_split "*uavg_floor_vx_<mode>"
   "&& 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 @@ (define_insn_and_split "*uavg_floor_vx_<mode>"
       (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 @@ (define_insn_and_split "*uavg_floor_vx_<mode>"
   "&& 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 a41c4c299fa..9cb6d30ef6f 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 242ac087764..15c473f9b3d 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, "
@@ -5597,6 +5600,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 5f6cc42b46b..dbb48a4393a 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -4013,6 +4013,14 @@ (define_int_iterator VSAT_OP [UNSPEC_VAADDU UNSPEC_VAADD
                              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 @@ (define_int_attr sat_insn_type [(UNSPEC_VAADDU "vaalu") 
(UNSPEC_VAADD "vaalu")
                                (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")])
 
-- 
2.43.0

Reply via email to