aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Leoshkevich <iii@linux.ibm.com>2019-10-07 15:01:15 +0000
committerIlya Leoshkevich <iii@linux.ibm.com>2019-10-07 15:01:15 +0000
commitf5623b5a3ab4a9fe4847348644baf1f268d90b12 (patch)
tree57e8c3ef3613a9b118825f76b0390c14d6429549
parente8d83f8e2302f3455a478a5174a418926ff286b8 (diff)
Introduce can_vcond_compare_p function
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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@276660 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/optabs-tree.c39
-rw-r--r--gcc/optabs.c19
-rw-r--r--gcc/optabs.h6
4 files changed, 68 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 922ca5d0bd9..c9ca3bae0e4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,6 +1,16 @@
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
* gimple-expr.c (gimple_cond_get_ops_from_tree): Assert that the
caller passes a non-trapping condition.
(is_gimple_condexpr): Allow trapping conditions.
diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
index 8157798cc71..a5ecbf075b5 100644
--- a/gcc/optabs-tree.c
+++ b/gcc/optabs-tree.c
@@ -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
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 35921e691f9..d6701df158c 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -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.
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 897bb5d4443..b1348ce85c9 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -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