diff mbox series

Introduce can_vec_cmp_compare_p

Message ID 20201126192609.284642-1-iii@linux.ibm.com
State New
Headers show
Series Introduce can_vec_cmp_compare_p | expand

Commit Message

Ilya Leoshkevich Nov. 26, 2020, 7:26 p.m. UTC
Bootstrapped and regtested on x86_64-redhat-linux and
s390x-redhat-linux.  Ok for master?



This is the same as dcd2ca63ec5c ("Introduce can_vcond_compare_p
function"), but for vec_cmp.  The reason it's needed is that since
5d9ade39b872 ("IBM Z: Fix PR97326: Enable fp compares in vec_cmp")
and 4acba4859013 ("IBM Z: Restrict vec_cmp<m><n> on z13") s390's vec_cmp
expander advertises that it supports floating point comparisons except
signaling ones on z13, but the common code ignores the latter
restriction.

gcc/ChangeLog:

2020-11-25  Ilya Leoshkevich  <iii@linux.ibm.com>

	* optabs-tree.c (vec_cmp_icode_p): New function.
	(vec_cmp_eq_icode_p): New function.
	(expand_vec_cmp_expr_p): Use vec_cmp_icode_p and
	vec_cmp_eq_icode_p.
	(vcond_icode_p): Use get_rtx_code_1, just to be uniform with
	vec_cmp_icode_p.
	* optabs.c (unsigned_optab_p): New function.
	(insn_predicate_matches_p): New function.
	(can_vec_cmp_compare_p): New function.
	(can_vcond_compare_p): Use unsigned_optab_p and
	insn_predicate_matches_p.
	(get_rtx_code): Use get_rtx_code_1.
	(get_rtx_code_1): Version of get_rtx_code that returns UNKNOWN
	instead of asserting.
	* optabs.h (can_vec_cmp_compare_p): New function.
	(get_rtx_code_1): New function.
---
 gcc/optabs-tree.c | 47 ++++++++++++++++++++++------
 gcc/optabs.c      | 78 ++++++++++++++++++++++++++++++++++++++---------
 gcc/optabs.h      | 12 ++++++--
 3 files changed, 109 insertions(+), 28 deletions(-)

Comments

Richard Biener Dec. 1, 2020, 10:35 a.m. UTC | #1
On Thu, Nov 26, 2020 at 8:27 PM Ilya Leoshkevich via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Bootstrapped and regtested on x86_64-redhat-linux and
> s390x-redhat-linux.  Ok for master?

OK/

Thanks,
Richard.

>
>
> This is the same as dcd2ca63ec5c ("Introduce can_vcond_compare_p
> function"), but for vec_cmp.  The reason it's needed is that since
> 5d9ade39b872 ("IBM Z: Fix PR97326: Enable fp compares in vec_cmp")
> and 4acba4859013 ("IBM Z: Restrict vec_cmp<m><n> on z13") s390's vec_cmp
> expander advertises that it supports floating point comparisons except
> signaling ones on z13, but the common code ignores the latter
> restriction.
>
> gcc/ChangeLog:
>
> 2020-11-25  Ilya Leoshkevich  <iii@linux.ibm.com>
>
>         * optabs-tree.c (vec_cmp_icode_p): New function.
>         (vec_cmp_eq_icode_p): New function.
>         (expand_vec_cmp_expr_p): Use vec_cmp_icode_p and
>         vec_cmp_eq_icode_p.
>         (vcond_icode_p): Use get_rtx_code_1, just to be uniform with
>         vec_cmp_icode_p.
>         * optabs.c (unsigned_optab_p): New function.
>         (insn_predicate_matches_p): New function.
>         (can_vec_cmp_compare_p): New function.
>         (can_vcond_compare_p): Use unsigned_optab_p and
>         insn_predicate_matches_p.
>         (get_rtx_code): Use get_rtx_code_1.
>         (get_rtx_code_1): Version of get_rtx_code that returns UNKNOWN
>         instead of asserting.
>         * optabs.h (can_vec_cmp_compare_p): New function.
>         (get_rtx_code_1): New function.
> ---
>  gcc/optabs-tree.c | 47 ++++++++++++++++++++++------
>  gcc/optabs.c      | 78 ++++++++++++++++++++++++++++++++++++++---------
>  gcc/optabs.h      | 12 ++++++--
>  3 files changed, 109 insertions(+), 28 deletions(-)
>
> diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
> index b797d018c84..a8968f3dd1a 100644
> --- a/gcc/optabs-tree.c
> +++ b/gcc/optabs-tree.c
> @@ -337,6 +337,35 @@ supportable_convert_operation (enum tree_code code,
>    return false;
>  }
>
> +/* Return true iff vec_cmp_optab/vec_cmpu_optab can handle a vector comparison
> +   for code CODE, comparing operands of type VALUE_TYPE and producing a result
> +   of type MASK_TYPE.  */
> +
> +static bool
> +vec_cmp_icode_p (tree value_type, tree mask_type, enum tree_code code)
> +{
> +  enum rtx_code rcode = get_rtx_code_1 (code, TYPE_UNSIGNED (value_type));
> +  if (rcode == UNKNOWN)
> +    return false;
> +
> +  return can_vec_cmp_compare_p (rcode, TYPE_MODE (value_type),
> +                               TYPE_MODE (mask_type));
> +}
> +
> +/* Return true iff vec_cmpeq_optab can handle a vector comparison for code
> +   CODE, comparing operands of type VALUE_TYPE and producing a result of type
> +   MASK_TYPE.  */
> +
> +static bool
> +vec_cmp_eq_icode_p (tree value_type, tree mask_type, enum tree_code code)
> +{
> +  if (code != EQ_EXPR && code != NE_EXPR)
> +    return false;
> +
> +  return get_vec_cmp_eq_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type))
> +        != CODE_FOR_nothing;
> +}
> +
>  /* Return TRUE if appropriate vector insn is available
>     for vector comparison expr with vector type VALUE_TYPE
>     and resulting mask with MASK_TYPE.  */
> @@ -344,14 +373,8 @@ supportable_convert_operation (enum tree_code code,
>  bool
>  expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
>  {
> -  if (get_vec_cmp_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type),
> -                        TYPE_UNSIGNED (value_type)) != CODE_FOR_nothing)
> -    return true;
> -  if ((code == EQ_EXPR || code == NE_EXPR)
> -      && (get_vec_cmp_eq_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type))
> -         != CODE_FOR_nothing))
> -    return true;
> -  return false;
> +  return vec_cmp_icode_p (value_type, mask_type, code)
> +        || vec_cmp_eq_icode_p (value_type, mask_type, code);
>  }
>
>  /* Return true iff vcond_optab/vcondu_optab can handle a vector
> @@ -361,8 +384,12 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
>  static bool
>  vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
>  {
> -  return can_vcond_compare_p (get_rtx_code (code, TYPE_UNSIGNED (cmp_op_type)),
> -                             TYPE_MODE (value_type), TYPE_MODE (cmp_op_type));
> +  enum rtx_code rcode = get_rtx_code_1 (code, TYPE_UNSIGNED (cmp_op_type));
> +  if (rcode == UNKNOWN)
> +    return false;
> +
> +  return can_vcond_compare_p (rcode, TYPE_MODE (value_type),
> +                             TYPE_MODE (cmp_op_type));
>  }
>
>  /* Return true iff vcondeq_optab can handle a vector comparison for code CODE,
> diff --git a/gcc/optabs.c b/gcc/optabs.c
> index 1820b91877a..76045596980 100644
> --- a/gcc/optabs.c
> +++ b/gcc/optabs.c
> @@ -3834,23 +3834,59 @@ can_compare_p (enum rtx_code code, machine_mode mode,
>    return 0;
>  }
>
> -/* Return whether the backend can emit a vector comparison for code CODE,
> -   comparing operands of mode CMP_OP_MODE and producing a result with
> -   VALUE_MODE.  */
> +/* Return whether RTL code CODE corresponds to an unsigned optab.  */
> +
> +static bool
> +unsigned_optab_p (enum rtx_code code)
> +{
> +  return code == LTU || code == LEU || code == GTU || code == GEU;
> +}
> +
> +/* Return whether the backend-emitted comparison for code CODE, comparing
> +   operands of mode VALUE_MODE and producing a result with MASK_MODE, matches
> +   operand OPNO of pattern ICODE.  */
> +
> +static bool
> +insn_predicate_matches_p (enum insn_code icode, unsigned int opno,
> +                         enum rtx_code code, machine_mode mask_mode,
> +                         machine_mode value_mode)
> +{
> +  rtx reg1 = alloca_raw_REG (value_mode, LAST_VIRTUAL_REGISTER + 1);
> +  rtx reg2 = alloca_raw_REG (value_mode, LAST_VIRTUAL_REGISTER + 2);
> +  rtx test = alloca_rtx_fmt_ee (code, mask_mode, reg1, reg2);
> +  return insn_operand_matches (icode, opno, test);
> +}
> +
> +/* Return whether the backend can emit a vector comparison (vec_cmp/vec_cmpu)
> +   for code CODE, comparing operands of mode VALUE_MODE and producing a result
> +   with MASK_MODE.  */
> +
> +bool
> +can_vec_cmp_compare_p (enum rtx_code code, machine_mode value_mode,
> +                      machine_mode mask_mode)
> +{
> +  enum insn_code icode
> +      = get_vec_cmp_icode (value_mode, mask_mode, unsigned_optab_p (code));
> +  if (icode == CODE_FOR_nothing)
> +    return false;
> +
> +  return insn_predicate_matches_p (icode, 1, code, mask_mode, value_mode);
> +}
> +
> +/* Return whether the backend can emit a vector comparison (vcond/vcondu) for
> +   code CODE, comparing operands of mode CMP_OP_MODE and producing a result
> +   with VALUE_MODE.  */
>
>  bool
>  can_vcond_compare_p (enum rtx_code code, machine_mode value_mode,
>                      machine_mode cmp_op_mode)
>  {
> -  enum insn_code icode;
> -  bool unsigned_p = (code == LTU || code == LEU || code == GTU || code == GEU);
> -  rtx reg1 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 1);
> -  rtx reg2 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 2);
> -  rtx test = alloca_rtx_fmt_ee (code, value_mode, reg1, reg2);
> -
> -  return (icode = get_vcond_icode (value_mode, cmp_op_mode, unsigned_p))
> -        != CODE_FOR_nothing
> -        && insn_operand_matches (icode, 3, test);
> +  enum insn_code icode
> +      = get_vcond_icode (value_mode, cmp_op_mode, unsigned_optab_p (code));
> +  if (icode == CODE_FOR_nothing)
> +    return false;
> +
> +  return insn_predicate_matches_p (icode, 3, code, value_mode, cmp_op_mode);
>  }
>
>  /* Return whether the backend can emit vector set instructions for inserting
> @@ -5403,11 +5439,11 @@ gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
>    return insn;
>  }
>
> -/* Return rtx code for TCODE. Use UNSIGNEDP to select signed
> +/* Return rtx code for TCODE or UNKNOWN.  Use UNSIGNEDP to select signed
>     or unsigned operation code.  */
>
>  enum rtx_code
> -get_rtx_code (enum tree_code tcode, bool unsignedp)
> +get_rtx_code_1 (enum tree_code tcode, bool unsignedp)
>  {
>    enum rtx_code code;
>    switch (tcode)
> @@ -5465,11 +5501,23 @@ get_rtx_code (enum tree_code tcode, bool unsignedp)
>        break;
>
>      default:
> -      gcc_unreachable ();
> +      code = UNKNOWN;
> +      break;
>      }
>    return code;
>  }
>
> +/* Return rtx code for TCODE.  Use UNSIGNEDP to select signed
> +   or unsigned operation code.  */
> +
> +enum rtx_code
> +get_rtx_code (enum tree_code tcode, bool unsignedp)
> +{
> +  enum rtx_code code = get_rtx_code_1 (tcode, unsignedp);
> +  gcc_assert (code != UNKNOWN);
> +  return code;
> +}
> +
>  /* Return a comparison rtx of mode CMP_MODE for COND.  Use UNSIGNEDP to
>     select signed or unsigned operators.  OPNO holds the index of the
>     first comparison operand for insn ICODE.  Do not generate the
> diff --git a/gcc/optabs.h b/gcc/optabs.h
> index bfa10c8f71b..84aaa7a9a02 100644
> --- a/gcc/optabs.h
> +++ b/gcc/optabs.h
> @@ -244,9 +244,14 @@ enum can_compare_purpose
>  extern int can_compare_p (enum rtx_code, machine_mode,
>                           enum can_compare_purpose);
>
> -/* Return whether the backend can emit a vector comparison for code CODE,
> -   comparing operands of mode CMP_OP_MODE and producing a result with
> -   VALUE_MODE.  */
> +/* Return whether the backend can emit a vector comparison (vec_cmp/vec_cmpu)
> +   for code CODE, comparing operands of mode VALUE_MODE and producing a result
> +   with MASK_MODE.  */
> +extern bool can_vec_cmp_compare_p (enum rtx_code, machine_mode, machine_mode);
> +
> +/* Return whether the backend can emit a vector comparison (vcond/vcondu) for
> +   code CODE, comparing operands of mode CMP_OP_MODE and producing a result
> +   with VALUE_MODE.  */
>  extern bool can_vcond_compare_p (enum rtx_code, machine_mode, machine_mode);
>
>  /* Return whether the backend can emit vector set instructions for inserting
> @@ -366,6 +371,7 @@ extern void expand_insn (enum insn_code icode, unsigned int nops,
>  extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
>                               class expand_operand *ops);
>
> +extern enum rtx_code get_rtx_code_1 (enum tree_code tcode, bool unsignedp);
>  extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp);
>  extern rtx vector_compare_rtx (machine_mode cmp_mode, enum tree_code tcode,
>                                tree t_op0, tree t_op1, bool unsignedp,
> --
> 2.25.4
>
diff mbox series

Patch

diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
index b797d018c84..a8968f3dd1a 100644
--- a/gcc/optabs-tree.c
+++ b/gcc/optabs-tree.c
@@ -337,6 +337,35 @@  supportable_convert_operation (enum tree_code code,
   return false;
 }
 
+/* Return true iff vec_cmp_optab/vec_cmpu_optab can handle a vector comparison
+   for code CODE, comparing operands of type VALUE_TYPE and producing a result
+   of type MASK_TYPE.  */
+
+static bool
+vec_cmp_icode_p (tree value_type, tree mask_type, enum tree_code code)
+{
+  enum rtx_code rcode = get_rtx_code_1 (code, TYPE_UNSIGNED (value_type));
+  if (rcode == UNKNOWN)
+    return false;
+
+  return can_vec_cmp_compare_p (rcode, TYPE_MODE (value_type),
+				TYPE_MODE (mask_type));
+}
+
+/* Return true iff vec_cmpeq_optab can handle a vector comparison for code
+   CODE, comparing operands of type VALUE_TYPE and producing a result of type
+   MASK_TYPE.  */
+
+static bool
+vec_cmp_eq_icode_p (tree value_type, tree mask_type, enum tree_code code)
+{
+  if (code != EQ_EXPR && code != NE_EXPR)
+    return false;
+
+  return get_vec_cmp_eq_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type))
+	 != CODE_FOR_nothing;
+}
+
 /* Return TRUE if appropriate vector insn is available
    for vector comparison expr with vector type VALUE_TYPE
    and resulting mask with MASK_TYPE.  */
@@ -344,14 +373,8 @@  supportable_convert_operation (enum tree_code code,
 bool
 expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
 {
-  if (get_vec_cmp_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type),
-			 TYPE_UNSIGNED (value_type)) != CODE_FOR_nothing)
-    return true;
-  if ((code == EQ_EXPR || code == NE_EXPR)
-      && (get_vec_cmp_eq_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type))
-	  != CODE_FOR_nothing))
-    return true;
-  return false;
+  return vec_cmp_icode_p (value_type, mask_type, code)
+	 || vec_cmp_eq_icode_p (value_type, mask_type, code);
 }
 
 /* Return true iff vcond_optab/vcondu_optab can handle a vector
@@ -361,8 +384,12 @@  expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
 static bool
 vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
 {
-  return can_vcond_compare_p (get_rtx_code (code, TYPE_UNSIGNED (cmp_op_type)),
-			      TYPE_MODE (value_type), TYPE_MODE (cmp_op_type));
+  enum rtx_code rcode = get_rtx_code_1 (code, TYPE_UNSIGNED (cmp_op_type));
+  if (rcode == UNKNOWN)
+    return false;
+
+  return can_vcond_compare_p (rcode, TYPE_MODE (value_type),
+			      TYPE_MODE (cmp_op_type));
 }
 
 /* Return true iff vcondeq_optab can handle a vector comparison for code CODE,
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 1820b91877a..76045596980 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -3834,23 +3834,59 @@  can_compare_p (enum rtx_code code, machine_mode mode,
   return 0;
 }
 
-/* Return whether the backend can emit a vector comparison for code CODE,
-   comparing operands of mode CMP_OP_MODE and producing a result with
-   VALUE_MODE.  */
+/* Return whether RTL code CODE corresponds to an unsigned optab.  */
+
+static bool
+unsigned_optab_p (enum rtx_code code)
+{
+  return code == LTU || code == LEU || code == GTU || code == GEU;
+}
+
+/* Return whether the backend-emitted comparison for code CODE, comparing
+   operands of mode VALUE_MODE and producing a result with MASK_MODE, matches
+   operand OPNO of pattern ICODE.  */
+
+static bool
+insn_predicate_matches_p (enum insn_code icode, unsigned int opno,
+			  enum rtx_code code, machine_mode mask_mode,
+			  machine_mode value_mode)
+{
+  rtx reg1 = alloca_raw_REG (value_mode, LAST_VIRTUAL_REGISTER + 1);
+  rtx reg2 = alloca_raw_REG (value_mode, LAST_VIRTUAL_REGISTER + 2);
+  rtx test = alloca_rtx_fmt_ee (code, mask_mode, reg1, reg2);
+  return insn_operand_matches (icode, opno, test);
+}
+
+/* Return whether the backend can emit a vector comparison (vec_cmp/vec_cmpu)
+   for code CODE, comparing operands of mode VALUE_MODE and producing a result
+   with MASK_MODE.  */
+
+bool
+can_vec_cmp_compare_p (enum rtx_code code, machine_mode value_mode,
+		       machine_mode mask_mode)
+{
+  enum insn_code icode
+      = get_vec_cmp_icode (value_mode, mask_mode, unsigned_optab_p (code));
+  if (icode == CODE_FOR_nothing)
+    return false;
+
+  return insn_predicate_matches_p (icode, 1, code, mask_mode, value_mode);
+}
+
+/* Return whether the backend can emit a vector comparison (vcond/vcondu) for
+   code CODE, comparing operands of mode CMP_OP_MODE and producing a result
+   with VALUE_MODE.  */
 
 bool
 can_vcond_compare_p (enum rtx_code code, machine_mode value_mode,
 		     machine_mode cmp_op_mode)
 {
-  enum insn_code icode;
-  bool unsigned_p = (code == LTU || code == LEU || code == GTU || code == GEU);
-  rtx reg1 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 1);
-  rtx reg2 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 2);
-  rtx test = alloca_rtx_fmt_ee (code, value_mode, reg1, reg2);
-
-  return (icode = get_vcond_icode (value_mode, cmp_op_mode, unsigned_p))
-	 != CODE_FOR_nothing
-	 && insn_operand_matches (icode, 3, test);
+  enum insn_code icode
+      = get_vcond_icode (value_mode, cmp_op_mode, unsigned_optab_p (code));
+  if (icode == CODE_FOR_nothing)
+    return false;
+
+  return insn_predicate_matches_p (icode, 3, code, value_mode, cmp_op_mode);
 }
 
 /* Return whether the backend can emit vector set instructions for inserting
@@ -5403,11 +5439,11 @@  gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
   return insn;
 }
 
-/* Return rtx code for TCODE. Use UNSIGNEDP to select signed
+/* Return rtx code for TCODE or UNKNOWN.  Use UNSIGNEDP to select signed
    or unsigned operation code.  */
 
 enum rtx_code
-get_rtx_code (enum tree_code tcode, bool unsignedp)
+get_rtx_code_1 (enum tree_code tcode, bool unsignedp)
 {
   enum rtx_code code;
   switch (tcode)
@@ -5465,11 +5501,23 @@  get_rtx_code (enum tree_code tcode, bool unsignedp)
       break;
 
     default:
-      gcc_unreachable ();
+      code = UNKNOWN;
+      break;
     }
   return code;
 }
 
+/* Return rtx code for TCODE.  Use UNSIGNEDP to select signed
+   or unsigned operation code.  */
+
+enum rtx_code
+get_rtx_code (enum tree_code tcode, bool unsignedp)
+{
+  enum rtx_code code = get_rtx_code_1 (tcode, unsignedp);
+  gcc_assert (code != UNKNOWN);
+  return code;
+}
+
 /* Return a comparison rtx of mode CMP_MODE for COND.  Use UNSIGNEDP to
    select signed or unsigned operators.  OPNO holds the index of the
    first comparison operand for insn ICODE.  Do not generate the
diff --git a/gcc/optabs.h b/gcc/optabs.h
index bfa10c8f71b..84aaa7a9a02 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -244,9 +244,14 @@  enum can_compare_purpose
 extern int can_compare_p (enum rtx_code, machine_mode,
 			  enum can_compare_purpose);
 
-/* Return whether the backend can emit a vector comparison for code CODE,
-   comparing operands of mode CMP_OP_MODE and producing a result with
-   VALUE_MODE.  */
+/* Return whether the backend can emit a vector comparison (vec_cmp/vec_cmpu)
+   for code CODE, comparing operands of mode VALUE_MODE and producing a result
+   with MASK_MODE.  */
+extern bool can_vec_cmp_compare_p (enum rtx_code, machine_mode, machine_mode);
+
+/* Return whether the backend can emit a vector comparison (vcond/vcondu) for
+   code CODE, comparing operands of mode CMP_OP_MODE and producing a result
+   with VALUE_MODE.  */
 extern bool can_vcond_compare_p (enum rtx_code, machine_mode, machine_mode);
 
 /* Return whether the backend can emit vector set instructions for inserting
@@ -366,6 +371,7 @@  extern void expand_insn (enum insn_code icode, unsigned int nops,
 extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
 			      class expand_operand *ops);
 
+extern enum rtx_code get_rtx_code_1 (enum tree_code tcode, bool unsignedp);
 extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp);
 extern rtx vector_compare_rtx (machine_mode cmp_mode, enum tree_code tcode,
 			       tree t_op0, tree t_op1, bool unsignedp,