aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 922ca5d..c9ca3ba 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 8157798..a5ecbf0 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 35921e6..d6701df 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 897bb5d..b1348ce 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