if (optimize_bb_for_speed_p (bb)
&& occ->recip_def && use_stmt != occ->recip_def_stmt)
{
+ gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
gimple_assign_set_rhs_code (use_stmt, MULT_EXPR);
SET_USE (use_p, occ->recip_def);
- fold_stmt_inplace (use_stmt);
+ fold_stmt_inplace (&gsi);
update_stmt (use_stmt);
}
}
FOR_EACH_IMM_USE_STMT (stmt, ui, arg1)
{
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
gimple_assign_set_rhs_code (stmt, MULT_EXPR);
- fold_stmt_inplace (stmt);
+ fold_stmt_inplace (&gsi);
update_stmt (stmt);
}
}
if (sizeof (HOST_WIDEST_INT) < 8)
return 0;
- bswap32_p = (built_in_decls[BUILT_IN_BSWAP32]
+ bswap32_p = (builtin_decl_explicit_p (BUILT_IN_BSWAP32)
&& optab_handler (bswap_optab, SImode) != CODE_FOR_nothing);
- bswap64_p = (built_in_decls[BUILT_IN_BSWAP64]
+ bswap64_p = (builtin_decl_explicit_p (BUILT_IN_BSWAP64)
&& (optab_handler (bswap_optab, DImode) != CODE_FOR_nothing
|| (bswap32_p && word_mode == SImode)));
assumes that the return and argument type are the same. */
if (bswap32_p)
{
- tree fndecl = built_in_decls[BUILT_IN_BSWAP32];
+ tree fndecl = builtin_decl_explicit (BUILT_IN_BSWAP32);
bswap32_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
}
if (bswap64_p)
{
- tree fndecl = built_in_decls[BUILT_IN_BSWAP64];
+ tree fndecl = builtin_decl_explicit (BUILT_IN_BSWAP64);
bswap64_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
}
case 32:
if (bswap32_p)
{
- fndecl = built_in_decls[BUILT_IN_BSWAP32];
+ fndecl = builtin_decl_explicit (BUILT_IN_BSWAP32);
bswap_type = bswap32_type;
}
break;
case 64:
if (bswap64_p)
{
- fndecl = built_in_decls[BUILT_IN_BSWAP64];
+ fndecl = builtin_decl_explicit (BUILT_IN_BSWAP64);
bswap_type = bswap64_type;
}
break;
: rhs_code != FIXED_CONVERT_EXPR)
rhs1 = rhs;
else
- rhs1 = gimple_assign_rhs1 (stmt);
+ {
+ rhs1 = gimple_assign_rhs1 (stmt);
+
+ if (TREE_CODE (rhs1) == INTEGER_CST)
+ {
+ *new_rhs_out = rhs1;
+ *type_out = NULL;
+ return true;
+ }
+ }
}
else
rhs1 = rhs;
and *TYPE2_OUT would give the operands of the multiplication. */
static bool
-is_widening_mult_p (tree type, gimple stmt,
+is_widening_mult_p (gimple stmt,
tree *type1_out, tree *rhs1_out,
tree *type2_out, tree *rhs2_out)
{
+ tree type = TREE_TYPE (gimple_assign_lhs (stmt));
+
if (TREE_CODE (type) != INTEGER_TYPE
&& TREE_CODE (type) != FIXED_POINT_TYPE)
return false;
if (TREE_CODE (type) != INTEGER_TYPE)
return false;
- if (!is_widening_mult_p (type, stmt, &type1, &rhs1, &type2, &rhs2))
+ if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2))
return false;
to_mode = TYPE_MODE (type);
{
if (op != smul_widen_optab)
{
- from_mode = GET_MODE_WIDER_MODE (from_mode);
- if (GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode))
- return false;
+ /* We can use a signed multiply with unsigned types as long as
+ there is a wider mode to use, or it is the smaller of the two
+ types that is unsigned. Note that type1 >= type2, always. */
+ if ((TYPE_UNSIGNED (type1)
+ && TYPE_PRECISION (type1) == GET_MODE_PRECISION (from_mode))
+ || (TYPE_UNSIGNED (type2)
+ && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode)))
+ {
+ from_mode = GET_MODE_WIDER_MODE (from_mode);
+ if (GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode))
+ return false;
+ }
op = smul_widen_optab;
handler = find_widening_optab_handler_and_mode (op, to_mode,
rhs2 = build_and_insert_cast (gsi, loc, tmp, rhs2);
}
+ /* Handle constants. */
+ if (TREE_CODE (rhs1) == INTEGER_CST)
+ rhs1 = fold_convert (type1, rhs1);
+ if (TREE_CODE (rhs2) == INTEGER_CST)
+ rhs2 = fold_convert (type2, rhs2);
+
gimple_assign_set_rhs1 (stmt, rhs1);
gimple_assign_set_rhs2 (stmt, rhs2);
gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR);
if (is_gimple_assign (rhs1_stmt))
rhs1_code = gimple_assign_rhs_code (rhs1_stmt);
}
- else
- return false;
if (TREE_CODE (rhs2) == SSA_NAME)
{
if (is_gimple_assign (rhs2_stmt))
rhs2_code = gimple_assign_rhs_code (rhs2_stmt);
}
- else
- return false;
/* Allow for one conversion statement between the multiply
and addition/subtraction statement. If there are more than
if (code == PLUS_EXPR
&& (rhs1_code == MULT_EXPR || rhs1_code == WIDEN_MULT_EXPR))
{
- if (!is_widening_mult_p (type, rhs1_stmt, &type1, &mult_rhs1,
+ if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1,
&type2, &mult_rhs2))
return false;
add_rhs = rhs2;
}
else if (rhs2_code == MULT_EXPR || rhs2_code == WIDEN_MULT_EXPR)
{
- if (!is_widening_mult_p (type, rhs2_stmt, &type1, &mult_rhs1,
+ if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1,
&type2, &mult_rhs2))
return false;
add_rhs = rhs1;
from_mode = TYPE_MODE (type1);
from_unsigned1 = TYPE_UNSIGNED (type1);
from_unsigned2 = TYPE_UNSIGNED (type2);
+ optype = type1;
/* There's no such thing as a mixed sign madd yet, so use a wider mode. */
if (from_unsigned1 != from_unsigned2)
{
- enum machine_mode mode = GET_MODE_WIDER_MODE (from_mode);
- if (GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (to_mode))
+ if (!INTEGRAL_TYPE_P (type))
+ return false;
+ /* We can use a signed multiply with unsigned types as long as
+ there is a wider mode to use, or it is the smaller of the two
+ types that is unsigned. Note that type1 >= type2, always. */
+ if ((from_unsigned1
+ && TYPE_PRECISION (type1) == GET_MODE_PRECISION (from_mode))
+ || (from_unsigned2
+ && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode)))
{
- from_mode = mode;
- from_unsigned1 = from_unsigned2 = false;
+ from_mode = GET_MODE_WIDER_MODE (from_mode);
+ if (GET_MODE_SIZE (from_mode) >= GET_MODE_SIZE (to_mode))
+ return false;
}
- else
- return false;
+
+ from_unsigned1 = from_unsigned2 = false;
+ optype = build_nonstandard_integer_type (GET_MODE_PRECISION (from_mode),
+ false);
}
/* If there was a conversion between the multiply and addition
/* Verify that the machine can perform a widening multiply
accumulate in this mode/signedness combination, otherwise
this transformation is likely to pessimize code. */
- optype = build_nonstandard_integer_type (from_mode, from_unsigned1);
this_optab = optab_for_tree_code (wmult_code, optype, optab_default);
handler = find_widening_optab_handler_and_mode (this_optab, to_mode,
from_mode, 0, &actual_mode);
mult_rhs2 = build_and_insert_cast (gsi, loc, tmp, mult_rhs2);
}
+ if (!useless_type_conversion_p (type, TREE_TYPE (add_rhs)))
+ add_rhs = build_and_insert_cast (gsi, loc, create_tmp_var (type, NULL),
+ add_rhs);
+
+ /* Handle constants. */
+ if (TREE_CODE (mult_rhs1) == INTEGER_CST)
+ mult_rhs1 = fold_convert (type1, mult_rhs1);
+ if (TREE_CODE (mult_rhs2) == INTEGER_CST)
+ mult_rhs2 = fold_convert (type2, mult_rhs2);
+
gimple_assign_set_rhs_with_ops_1 (gsi, wmult_code, mult_rhs1, mult_rhs2,
add_rhs);
update_stmt (gsi_stmt (*gsi));
if (optab_handler (fma_optab, TYPE_MODE (type)) == CODE_FOR_nothing)
return false;
+ /* If the multiplication has zero uses, it is kept around probably because
+ of -fnon-call-exceptions. Don't optimize it away in that case,
+ it is DCE job. */
+ if (has_zero_uses (mul_result))
+ return false;
+
/* Make sure that the multiplication statement becomes dead after
the transformation, thus that all uses are transformed to FMAs.
This means we assume that an FMA operation has the same cost