return NULL_TREE;
}
-/* Return type in which CODE operation with optab OP can be
- computed. */
+/* Return the type that should be used to implement OP on type TYPE.
+ This is TYPE itself if the target can do the operation directly,
+ otherwise it is a scalar type or a smaller vector type. */
static tree
-get_compute_type (enum tree_code code, optab op, tree type)
+get_compute_type (optab op, tree type)
{
- /* For very wide vectors, try using a smaller vector mode. */
- tree compute_type = type;
- if (op
- && (!VECTOR_MODE_P (TYPE_MODE (type))
- || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing))
+ if (op)
{
- tree vector_compute_type
- = type_for_widest_vector_mode (type, op);
+ if (VECTOR_MODE_P (TYPE_MODE (type))
+ && can_implement_p (op, TYPE_MODE (type)))
+ return type;
+
+ /* For very wide vectors, try using a smaller vector mode. */
+ tree vector_compute_type = type_for_widest_vector_mode (type, op);
if (vector_compute_type != NULL_TREE
&& maybe_ne (TYPE_VECTOR_SUBPARTS (vector_compute_type), 1U)
- && (optab_handler (op, TYPE_MODE (vector_compute_type))
- != CODE_FOR_nothing))
- compute_type = vector_compute_type;
- }
-
- /* If we are breaking a BLKmode vector into smaller pieces,
- type_for_widest_vector_mode has already looked into the optab,
- so skip these checks. */
- if (compute_type == type)
- {
- machine_mode compute_mode = TYPE_MODE (compute_type);
- if (VECTOR_MODE_P (compute_mode))
- {
- if (op
- && (optab_handler (op, compute_mode) != CODE_FOR_nothing
- || optab_libfunc (op, compute_mode)))
- return compute_type;
- if (code == MULT_HIGHPART_EXPR
- && can_mult_highpart_p (compute_mode,
- TYPE_UNSIGNED (compute_type)))
- return compute_type;
- }
- /* There is no operation in hardware, so fall back to scalars. */
- compute_type = TREE_TYPE (type);
+ && can_implement_p (op, TYPE_MODE (vector_compute_type)))
+ return vector_compute_type;
}
- return compute_type;
+ /* There is no operation in hardware, so fall back to scalars. */
+ return TREE_TYPE (type);
}
static tree
gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
tree lhs = gimple_assign_lhs (stmt);
tree type = TREE_TYPE (lhs);
- tree compute_type = get_compute_type (COND_EXPR, mov_optab, type);
+ tree compute_type = get_compute_type (mov_optab, type);
machine_mode compute_mode = TYPE_MODE (compute_type);
gcc_assert (compute_mode != BLKmode);
tree rhs2 = gimple_assign_rhs2 (stmt);
}
if (optab1)
- compute_type = get_compute_type (code1, optab1, arg_type);
+ compute_type = get_compute_type (optab1, arg_type);
enum insn_code icode1;
if (VECTOR_TYPE_P (compute_type)
&& ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
}
if (optab1 && optab2)
- compute_type = get_compute_type (code1, optab1, arg_type);
+ compute_type = get_compute_type (optab1, arg_type);
enum insn_code icode1, icode2;
if (VECTOR_TYPE_P (compute_type)
{
op = optab_for_tree_code (code, type, optab_scalar);
- compute_type = get_compute_type (code, op, type);
+ compute_type = get_compute_type (op, type);
if (compute_type == type)
return;
/* The rtl expander will expand vector/scalar as vector/vector
if necessary. Pick one with wider vector type. */
- tree compute_vtype = get_compute_type (code, opv, type);
+ tree compute_vtype = get_compute_type (opv, type);
if (subparts_gt (compute_vtype, compute_type))
{
compute_type = compute_vtype;
if (code == LROTATE_EXPR || code == RROTATE_EXPR)
{
if (compute_type == NULL_TREE)
- compute_type = get_compute_type (code, op, type);
+ compute_type = get_compute_type (op, type);
if (compute_type == type)
return;
/* Before splitting vector rotates into scalar rotates,
{
optab oplv = vashl_optab, opl = ashl_optab;
optab oprv = vlshr_optab, opr = lshr_optab, opo = ior_optab;
- tree compute_lvtype = get_compute_type (LSHIFT_EXPR, oplv, type);
- tree compute_rvtype = get_compute_type (RSHIFT_EXPR, oprv, type);
- tree compute_otype = get_compute_type (BIT_IOR_EXPR, opo, type);
- tree compute_ltype = get_compute_type (LSHIFT_EXPR, opl, type);
- tree compute_rtype = get_compute_type (RSHIFT_EXPR, opr, type);
+ tree compute_lvtype = get_compute_type (oplv, type);
+ tree compute_rvtype = get_compute_type (oprv, type);
+ tree compute_otype = get_compute_type (opo, type);
+ tree compute_ltype = get_compute_type (opl, type);
+ tree compute_rtype = get_compute_type (opr, type);
/* The rtl expander will expand vector/scalar as vector/vector
if necessary. Pick one with wider vector type. */
if (subparts_gt (compute_lvtype, compute_ltype))
op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
if (compute_type == NULL_TREE)
- compute_type = get_compute_type (code, op, type);
+ compute_type = get_compute_type (op, type);
if (compute_type == type)
return;