Introduce can_vcond_compare_p function
authorIlya Leoshkevich <iii@linux.ibm.com>
Mon, 7 Oct 2019 15:01:15 +0000 (15:01 +0000)
committerIlya Leoshkevich <iii@gcc.gnu.org>
Mon, 7 Oct 2019 15:01:15 +0000 (15:01 +0000)
z13 supports only non-signaling vector comparisons.  This means we
cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13.
However, we cannot express this restriction today: the code only checks
whether vcond$a$b optab exists, but this does not say anything about the
operation.

Introduce a function that checks whether back-end supports vector
comparisons with individual rtx codes by matching vcond expander's third
argument with a fake comparison with the corresponding rtx code.

gcc/ChangeLog:

2019-10-07  Ilya Leoshkevich  <iii@linux.ibm.com>

PR target/77918
* optabs-tree.c (vcond_icode_p): New function.
(vcond_eq_icode_p): Likewise.
(expand_vec_cond_expr_p): Use vcond_icode_p and
vcond_eq_icode_p.
* optabs.c (can_vcond_compare_p): New function.
* optabs.h (can_vcond_compare_p): Likewise.

From-SVN: r276660

gcc/ChangeLog
gcc/optabs-tree.c
gcc/optabs.c
gcc/optabs.h

index 922ca5d0bd94a29ceced7efc0ffe970d2ba15d5c..c9ca3bae0e488a288e9f5d39086e5e1381d5b467 100644 (file)
@@ -1,3 +1,13 @@
+2019-10-07  Ilya Leoshkevich  <iii@linux.ibm.com>
+
+       PR target/77918
+       * optabs-tree.c (vcond_icode_p): New function.
+       (vcond_eq_icode_p): Likewise.
+       (expand_vec_cond_expr_p): Use vcond_icode_p and
+       vcond_eq_icode_p.
+       * optabs.c (can_vcond_compare_p): New function.
+       * optabs.h (can_vcond_compare_p): Likewise.
+
 2019-10-07  Ilya Leoshkevich  <iii@linux.ibm.com>
 
        PR target/77918
index 8157798cc719966d089f768994842f8bb77e5cf8..a5ecbf075b5d0cce6f1dfbcc51399fae87f5e1be 100644 (file)
@@ -23,7 +23,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "target.h"
 #include "insn-codes.h"
+#include "rtl.h"
 #include "tree.h"
+#include "memmodel.h"
+#include "optabs.h"
 #include "optabs-tree.h"
 #include "stor-layout.h"
 
@@ -329,6 +332,31 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
   return false;
 }
 
+/* Return true iff vcond_optab/vcondu_optab can handle a vector
+   comparison for code CODE, comparing operands of type CMP_OP_TYPE and
+   producing a result of type VALUE_TYPE.  */
+
+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));
+}
+
+/* Return true iff vcondeq_optab can handle a vector comparison for code CODE,
+   comparing operands of type CMP_OP_TYPE and producing a result of type
+   VALUE_TYPE.  */
+
+static bool
+vcond_eq_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
+{
+  if (code != EQ_EXPR && code != NE_EXPR)
+    return false;
+
+  return get_vcond_eq_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type))
+        != CODE_FOR_nothing;
+}
+
 /* Return TRUE iff, appropriate vector insns are available
    for vector cond expr with vector type VALUE_TYPE and a comparison
    with operand vector types in CMP_OP_TYPE.  */
@@ -347,14 +375,13 @@ expand_vec_cond_expr_p (tree value_type, tree cmp_op_type, enum tree_code code)
       || maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode)))
     return false;
 
-  if (get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
-                      TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing
-      && ((code != EQ_EXPR && code != NE_EXPR)
-         || get_vcond_eq_icode (TYPE_MODE (value_type),
-                                TYPE_MODE (cmp_op_type)) == CODE_FOR_nothing))
+  if (TREE_CODE_CLASS (code) != tcc_comparison)
+    /* This may happen, for example, if code == SSA_NAME, in which case we
+       cannot be certain whether a vector insn is available.  */
     return false;
 
-  return true;
+  return vcond_icode_p (value_type, cmp_op_type, code)
+        || vcond_eq_icode_p (value_type, cmp_op_type, code);
 }
 
 /* Use the current target and options to initialize
index 35921e691f94e301f0461a8943435aad0be94bd8..d6701df158c593e3be86d15b076c646a8f8ff58d 100644 (file)
@@ -3819,6 +3819,25 @@ 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.  */
+
+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);
+}
+
 /* This function is called when we are going to emit a compare instruction that
    compares the values found in X and Y, using the rtl operator COMPARISON.
 
index 897bb5d4443ad96fc9ca9a59316b953a396e55e2..b1348ce85c916e6b9fcdbaf5c51a1644a4e28dc3 100644 (file)
@@ -242,6 +242,12 @@ enum can_compare_purpose
    (without splitting it into pieces).  */
 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.  */
+extern bool can_vcond_compare_p (enum rtx_code, machine_mode, machine_mode);
+
 extern rtx prepare_operand (enum insn_code, rtx, int, machine_mode,
                            machine_mode, int);
 /* Emit a pair of rtl insns to compare two rtx's and to jump