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 b797d018c84e2f55a683b786f855b018c2549d24..a8968f3dd1a243e5ab66d396323e6a3efca01360 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 3d5b07d95ce27906e37331de0ad4a657bd8ae514..8d89f08d2bdc804e6e4d0076372fd09eb43eb04a 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 bfa10c8f71b54eea667d5a743ef8486822e72e92..84aaa7a9a0247e1921778d7cccdf72ebf780b8d5 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,