Introduce can_vec_cmp_compare_p
authorIlya Leoshkevich <iii@linux.ibm.com>
Tue, 24 Nov 2020 22:45:59 +0000 (23:45 +0100)
committerIlya Leoshkevich <iii@linux.ibm.com>
Tue, 1 Dec 2020 11:03:30 +0000 (12:03 +0100)
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
gcc/optabs.c
gcc/optabs.h

index b797d01..a8968f3 100644 (file)
@@ -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,
index 3d5b07d..8d89f08 100644 (file)
@@ -4057,23 +4057,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
@@ -5626,11 +5662,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)
@@ -5688,11 +5724,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
index bfa10c8..84aaa7a 100644 (file)
@@ -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,