+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
#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"
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. */
|| 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
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.
(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