/* Do not recognize x / x as valid division, as we are getting
confused later by replacing all immediate uses x in such
a stmt. */
- && gimple_assign_rhs1 (use_stmt) != def;
+ && gimple_assign_rhs1 (use_stmt) != def
+ && !stmt_can_throw_internal (cfun, use_stmt);
}
/* Return TRUE if USE_STMT is a multiplication of DEF by A. */
{
if (gimple_code (use_stmt) == GIMPLE_ASSIGN
&& gimple_assign_rhs_code (use_stmt) == RDIV_EXPR
- && gimple_assign_rhs1 (use_stmt) != gimple_assign_rhs2 (use_stmt))
+ && gimple_assign_rhs1 (use_stmt) != gimple_assign_rhs2 (use_stmt)
+ && !stmt_can_throw_internal (cfun, use_stmt))
{
tree denominator = gimple_assign_rhs2 (use_stmt);
if (TREE_CODE (denominator) == SSA_NAME)
- {
- return is_square_of (SSA_NAME_DEF_STMT (denominator), def);
- }
+ return is_square_of (SSA_NAME_DEF_STMT (denominator), def);
}
return 0;
}
/* If it is more profitable to optimize 1 / x, don't optimize 1 / (x * x). */
if (sqrt_recip_count > square_recip_count)
- return;
+ goto out;
/* Do the expensive part only if we can hope to optimize something. */
if (count + square_recip_count >= threshold && count >= 1)
}
}
+out:
for (occ = occ_head; occ; )
occ = free_bb (occ);
gsi_replace (&gsi, fma_stmt, true);
/* Follow all SSA edges so that we generate FMS, FNMA and FNMS
regardless of where the negation occurs. */
+ gimple *orig_stmt = gsi_stmt (gsi);
if (fold_stmt (&gsi, follow_all_ssa_edges))
- update_stmt (gsi_stmt (gsi));
+ {
+ if (maybe_clean_or_replace_eh_stmt (orig_stmt, gsi_stmt (gsi)))
+ gcc_unreachable ();
+ update_stmt (gsi_stmt (gsi));
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
{
&& (tree_to_shwi (TYPE_SIZE (type))
<= PARAM_VALUE (PARAM_AVOID_FMA_MAX_BITS)));
bool defer = check_defer;
+ bool seen_negate_p = 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
ssa_op_iter iter;
use_operand_p usep;
+ /* If (due to earlier missed optimizations) we have two
+ negates of the same value, treat them as equivalent
+ to a single negate with multiple uses. */
+ if (seen_negate_p)
+ return false;
+
result = gimple_assign_lhs (use_stmt);
/* Make sure the negate statement becomes dead with this
if (gimple_bb (use_stmt) != gimple_bb (mul_stmt))
return false;
- negate_p = true;
+ negate_p = seen_negate_p = true;
}
tree cond, else_value, ops[3];