@@ -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,34 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
return false;
}
+/* Return TRUE iff vcond_optab/vcondu_optab support the given tree
+ comparison. */
+
+static bool
+vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
+{
+ enum rtx_code rcode = get_rtx_code_safe (code, TYPE_UNSIGNED (cmp_op_type));
+ if (rcode == LAST_AND_UNUSED_RTX_CODE)
+ /* 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 can_vector_compare_p (rcode, TYPE_MODE (value_type),
+ TYPE_MODE (cmp_op_type), cvcp_vcond);
+}
+
+/* Return TRUE iff vcondeq_optab supports the given tree comparison. */
+
+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 +378,8 @@ 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))
- 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
@@ -3819,6 +3819,30 @@ can_compare_p (enum rtx_code code, machine_mode mode,
return 0;
}
+/* Return whether back-end can emit a vector comparison insn(s) using a given
+ CODE, with operands with CMP_OP_MODE, producing a result with VALUE_MODE,
+ in order to achieve a PURPOSE. */
+
+bool
+can_vector_compare_p (enum rtx_code code, machine_mode value_mode,
+ machine_mode cmp_op_mode,
+ enum can_vector_compare_purpose purpose)
+{
+ 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);
+
+ if (purpose == cvcp_vcond
+ && (icode = get_vcond_icode (value_mode, cmp_op_mode, unsigned_p))
+ != CODE_FOR_nothing
+ && insn_operand_matches (icode, 3, test))
+ return true;
+
+ return false;
+}
+
/* 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.
@@ -5348,11 +5372,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
- or unsigned operation code. */
+/* Return rtx code for TCODE or LAST_AND_UNUSED_RTX_CODE if it has no RTL
+ counterpart. Use UNSIGNEDP to select signed or unsigned operation code. */
enum rtx_code
-get_rtx_code (enum tree_code tcode, bool unsignedp)
+get_rtx_code_safe (enum tree_code tcode, bool unsignedp)
{
enum rtx_code code;
switch (tcode)
@@ -5410,11 +5434,22 @@ get_rtx_code (enum tree_code tcode, bool unsignedp)
break;
default:
- gcc_unreachable ();
+ code = LAST_AND_UNUSED_RTX_CODE;
+ break;
}
return code;
}
+/* Like get_rtx_code_safe, but asserts when given unsupported tree codes. */
+
+enum rtx_code
+get_rtx_code (enum tree_code tcode, bool unsignedp)
+{
+ enum rtx_code code = get_rtx_code_safe (tcode, unsignedp);
+ gcc_assert (code != LAST_AND_UNUSED_RTX_CODE);
+ 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
@@ -242,6 +242,21 @@ enum can_compare_purpose
(without splitting it into pieces). */
extern int can_compare_p (enum rtx_code, machine_mode,
enum can_compare_purpose);
+
+/* The various uses that a vector comparison can have; used by
+ can_vector_compare_p. So far only vcond is defined, vec_cmp is a possible
+ future extension. */
+enum can_vector_compare_purpose
+{
+ cvcp_vcond
+};
+
+/* Return whether back-end can emit a vector comparison insn(s) using a given
+ CODE, with operands with CMP_OP_MODE, producing a result with VALUE_MODE,
+ in order to achieve a PURPOSE. */
+extern bool can_vector_compare_p (enum rtx_code, machine_mode, machine_mode,
+ enum can_vector_compare_purpose);
+
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
@@ -356,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_safe (enum tree_code tcode, bool unsignedp);
extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp);
#endif /* GCC_OPTABS_H */