This fixes PR50082 by completely defering to fold what kind of overflow warning to emit from tree-ssa-forwprop.c. It also moves overflow handling to the single place that decides whether and what we optimize.
Bootstrapped and tested on x86_64-unknown-linux-gnu. Ian, does this look ok? Thanks, Richard. 2011-08-16 Richard GUenther <rguent...@suse.de> PR tree-optimization/50082 * tree-ssa-forwprop.c (combine_cond_expr_cond): Handle overflow warnings here, instead of ... (ssa_forward_propagate_and_combine): ... here. (forward_propagate_into_comparison_1): Adjust. (forward_propagate_into_comparison): Likewise. (forward_propagate_into_gimple_cond): Likewise. (forward_propagate_into_cond): Likewise. Index: gcc/tree-ssa-forwprop.c =================================================================== *** gcc/tree-ssa-forwprop.c (revision 177781) --- gcc/tree-ssa-forwprop.c (working copy) *************** rhs_to_tree (tree type, gimple stmt) *** 369,384 **** considered simplified. */ static tree ! combine_cond_expr_cond (location_t loc, enum tree_code code, tree type, tree op0, tree op1, bool invariant_only) { tree t; gcc_assert (TREE_CODE_CLASS (code) == tcc_comparison); ! t = fold_binary_loc (loc, code, type, op0, op1); if (!t) ! return NULL_TREE; /* Require that we got a boolean type out if we put one in. */ gcc_assert (TREE_CODE (TREE_TYPE (t)) == TREE_CODE (type)); --- 369,388 ---- considered simplified. */ static tree ! combine_cond_expr_cond (gimple stmt, enum tree_code code, tree type, tree op0, tree op1, bool invariant_only) { tree t; gcc_assert (TREE_CODE_CLASS (code) == tcc_comparison); ! fold_defer_overflow_warnings (); ! t = fold_binary_loc (gimple_location (stmt), code, type, op0, op1); if (!t) ! { ! fold_undefer_overflow_warnings (false, NULL, 0); ! return NULL_TREE; ! } /* Require that we got a boolean type out if we put one in. */ gcc_assert (TREE_CODE (TREE_TYPE (t)) == TREE_CODE (type)); *************** combine_cond_expr_cond (location_t loc, *** 388,394 **** /* Bail out if we required an invariant but didn't get one. */ if (!t || (invariant_only && !is_gimple_min_invariant (t))) ! return NULL_TREE; return t; } --- 392,403 ---- /* Bail out if we required an invariant but didn't get one. */ if (!t || (invariant_only && !is_gimple_min_invariant (t))) ! { ! fold_undefer_overflow_warnings (false, NULL, 0); ! return NULL_TREE; ! } ! ! fold_undefer_overflow_warnings (!gimple_no_warning_p (stmt), stmt, 0); return t; } *************** combine_cond_expr_cond (location_t loc, *** 398,404 **** were no simplifying combines. */ static tree ! forward_propagate_into_comparison_1 (location_t loc, enum tree_code code, tree type, tree op0, tree op1) { --- 407,413 ---- were no simplifying combines. */ static tree ! forward_propagate_into_comparison_1 (gimple stmt, enum tree_code code, tree type, tree op0, tree op1) { *************** forward_propagate_into_comparison_1 (loc *** 414,420 **** if (def_stmt && can_propagate_from (def_stmt)) { rhs0 = rhs_to_tree (TREE_TYPE (op1), def_stmt); ! tmp = combine_cond_expr_cond (loc, code, type, rhs0, op1, !single_use0_p); if (tmp) return tmp; --- 423,429 ---- if (def_stmt && can_propagate_from (def_stmt)) { rhs0 = rhs_to_tree (TREE_TYPE (op1), def_stmt); ! tmp = combine_cond_expr_cond (stmt, code, type, rhs0, op1, !single_use0_p); if (tmp) return tmp; *************** forward_propagate_into_comparison_1 (loc *** 428,434 **** if (def_stmt && can_propagate_from (def_stmt)) { rhs1 = rhs_to_tree (TREE_TYPE (op0), def_stmt); ! tmp = combine_cond_expr_cond (loc, code, type, op0, rhs1, !single_use1_p); if (tmp) return tmp; --- 437,443 ---- if (def_stmt && can_propagate_from (def_stmt)) { rhs1 = rhs_to_tree (TREE_TYPE (op0), def_stmt); ! tmp = combine_cond_expr_cond (stmt, code, type, op0, rhs1, !single_use1_p); if (tmp) return tmp; *************** forward_propagate_into_comparison_1 (loc *** 438,444 **** /* If that wasn't successful either, try both operands. */ if (rhs0 != NULL_TREE && rhs1 != NULL_TREE) ! tmp = combine_cond_expr_cond (loc, code, type, rhs0, rhs1, !(single_use0_p && single_use1_p)); --- 447,453 ---- /* If that wasn't successful either, try both operands. */ if (rhs0 != NULL_TREE && rhs1 != NULL_TREE) ! tmp = combine_cond_expr_cond (stmt, code, type, rhs0, rhs1, !(single_use0_p && single_use1_p)); *************** forward_propagate_into_comparison (gimpl *** 460,466 **** tree rhs2 = gimple_assign_rhs2 (stmt); /* Combine the comparison with defining statements. */ ! tmp = forward_propagate_into_comparison_1 (gimple_location (stmt), gimple_assign_rhs_code (stmt), TREE_TYPE (gimple_assign_lhs (stmt)), --- 469,475 ---- tree rhs2 = gimple_assign_rhs2 (stmt); /* Combine the comparison with defining statements. */ ! tmp = forward_propagate_into_comparison_1 (stmt, gimple_assign_rhs_code (stmt), TREE_TYPE (gimple_assign_lhs (stmt)), *************** forward_propagate_into_comparison (gimpl *** 491,497 **** static int forward_propagate_into_gimple_cond (gimple stmt) { - location_t loc = gimple_location (stmt); tree tmp; enum tree_code code = gimple_cond_code (stmt); bool cfg_changed = false; --- 500,505 ---- *************** forward_propagate_into_gimple_cond (gimp *** 502,508 **** if (TREE_CODE_CLASS (gimple_cond_code (stmt)) != tcc_comparison) return 0; ! tmp = forward_propagate_into_comparison_1 (loc, code, boolean_type_node, rhs1, rhs2); if (tmp) --- 510,516 ---- if (TREE_CODE_CLASS (gimple_cond_code (stmt)) != tcc_comparison) return 0; ! tmp = forward_propagate_into_comparison_1 (stmt, code, boolean_type_node, rhs1, rhs2); if (tmp) *************** static int *** 541,553 **** forward_propagate_into_cond (gimple_stmt_iterator *gsi_p) { gimple stmt = gsi_stmt (*gsi_p); - location_t loc = gimple_location (stmt); tree tmp = NULL_TREE; tree cond = gimple_assign_rhs1 (stmt); /* We can do tree combining on SSA_NAME and comparison expressions. */ if (COMPARISON_CLASS_P (cond)) ! tmp = forward_propagate_into_comparison_1 (loc, TREE_CODE (cond), boolean_type_node, TREE_OPERAND (cond, 0), TREE_OPERAND (cond, 1)); --- 549,560 ---- forward_propagate_into_cond (gimple_stmt_iterator *gsi_p) { gimple stmt = gsi_stmt (*gsi_p); tree tmp = NULL_TREE; tree cond = gimple_assign_rhs1 (stmt); /* We can do tree combining on SSA_NAME and comparison expressions. */ if (COMPARISON_CLASS_P (cond)) ! tmp = forward_propagate_into_comparison_1 (stmt, TREE_CODE (cond), boolean_type_node, TREE_OPERAND (cond, 0), TREE_OPERAND (cond, 1)); *************** forward_propagate_into_cond (gimple_stmt *** 559,565 **** return 0; rhs0 = gimple_assign_rhs1 (def_stmt); ! tmp = combine_cond_expr_cond (loc, NE_EXPR, boolean_type_node, rhs0, build_int_cst (TREE_TYPE (rhs0), 0), false); } --- 566,572 ---- return 0; rhs0 = gimple_assign_rhs1 (def_stmt); ! tmp = combine_cond_expr_cond (stmt, NE_EXPR, boolean_type_node, rhs0, build_int_cst (TREE_TYPE (rhs0), 0), false); } *************** ssa_forward_propagate_and_combine (void) *** 2440,2466 **** { /* In this case the entire COND_EXPR is in rhs1. */ int did_something; - fold_defer_overflow_warnings (); did_something = forward_propagate_into_cond (&gsi); stmt = gsi_stmt (gsi); if (did_something == 2) cfg_changed = true; - fold_undefer_overflow_warnings - (!TREE_NO_WARNING (rhs1) && did_something, stmt, - WARN_STRICT_OVERFLOW_CONDITIONAL); changed = did_something != 0; } else if (TREE_CODE_CLASS (code) == tcc_comparison) { - bool no_warning = gimple_no_warning_p (stmt); int did_something; - fold_defer_overflow_warnings (); did_something = forward_propagate_into_comparison (&gsi); if (did_something == 2) cfg_changed = true; - fold_undefer_overflow_warnings - (!no_warning && changed, - stmt, WARN_STRICT_OVERFLOW_CONDITIONAL); changed = did_something != 0; } else if (code == BIT_AND_EXPR --- 2447,2464 ---- *************** ssa_forward_propagate_and_combine (void) *** 2489,2500 **** case GIMPLE_COND: { int did_something; - fold_defer_overflow_warnings (); did_something = forward_propagate_into_gimple_cond (stmt); if (did_something == 2) cfg_changed = true; - fold_undefer_overflow_warnings - (did_something, stmt, WARN_STRICT_OVERFLOW_CONDITIONAL); changed = did_something != 0; break; } --- 2487,2495 ----