This adjusts fold_stmt_inplace to take a gimple_stmt_iterator argument instead of a gimple. This allows it to operate on statements that are only in a gimple_seq but are not (yet) associated with a basic block. fold_stmt_* shouldn't require a CFG (and yep, I'm going to need that in a followup).
This exposes that fold_stmt_inplace used gsi_for_stmt which is an O(n) operation to its callers, quite a few already having a stmt iterator handy. Bootstrap and regtest pending on x86_64-unknown-linux-gnu. Richard. 2011-09-09 Richard Guenther <rguent...@suse.de> * gimple.h (fold_stmt_inplace): Adjust to take a gimple_stmt_iterator instead of a statement. * gimple-fold.c (fold_stmt_inplace): Likewise. * sese.c (graphite_copy_stmts_from_block): Adjust. * tree-ssa-dom.c (propagate_rhs_into_lhs): Likewise. * tree-ssa-forwprop.c (forward_propagate_into_comparison): Use fold_stmt. (forward_propagate_addr_into_variable_array_index): Likewise. (forward_propagate_addr_expr_1): adjust. (associate_plusminus): Likewise. (ssa_forward_propagate_and_combine): Likewise. * tree-ssa-mathopts.c (replace_reciprocal): Adjust. (execute_cse_reciprocals): Likewise. * tree-ssa.c (insert_debug_temp_for_var_def): Adjust. Index: gcc/gimple.h =================================================================== *** gcc/gimple.h (revision 178719) --- gcc/gimple.h (working copy) *************** extern void dump_gimple_statistics (void *** 5068,5074 **** void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree); tree gimple_fold_builtin (gimple); bool fold_stmt (gimple_stmt_iterator *); ! bool fold_stmt_inplace (gimple); tree get_symbol_constant_value (tree); tree canonicalize_constructor_val (tree); extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree, --- 5068,5074 ---- void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree); tree gimple_fold_builtin (gimple); bool fold_stmt (gimple_stmt_iterator *); ! bool fold_stmt_inplace (gimple_stmt_iterator *); tree get_symbol_constant_value (tree); tree canonicalize_constructor_val (tree); extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree, Index: gcc/gimple-fold.c =================================================================== *** gcc/gimple-fold.c (revision 178719) --- gcc/gimple-fold.c (working copy) *************** fold_stmt (gimple_stmt_iterator *gsi) *** 1286,1305 **** return fold_stmt_1 (gsi, false); } ! /* Perform the minimal folding on statement STMT. Only operations like *&x created by constant propagation are handled. The statement cannot be replaced with a new one. Return true if the statement was changed, false otherwise. ! The statement STMT should be in valid gimple form but may be in unfolded state as resulting from for example constant propagation which can produce *&x = 0. */ bool ! fold_stmt_inplace (gimple stmt) { ! gimple_stmt_iterator gsi = gsi_for_stmt (stmt); ! bool changed = fold_stmt_1 (&gsi, true); ! gcc_assert (gsi_stmt (gsi) == stmt); return changed; } --- 1286,1305 ---- return fold_stmt_1 (gsi, false); } ! /* Perform the minimal folding on statement *GSI. Only operations like *&x created by constant propagation are handled. The statement cannot be replaced with a new one. Return true if the statement was changed, false otherwise. ! The statement *GSI should be in valid gimple form but may be in unfolded state as resulting from for example constant propagation which can produce *&x = 0. */ bool ! fold_stmt_inplace (gimple_stmt_iterator *gsi) { ! gimple stmt = gsi_stmt (*gsi); ! bool changed = fold_stmt_1 (gsi, true); ! gcc_assert (gsi_stmt (*gsi) == stmt); return changed; } Index: gcc/sese.c =================================================================== *** gcc/sese.c (revision 178719) --- gcc/sese.c (working copy) *************** graphite_copy_stmts_from_block (basic_bl *** 620,626 **** if (rename_uses (copy, rename_map, &gsi_tgt, region, loop, iv_map, gloog_error)) ! fold_stmt_inplace (copy); update_stmt (copy); } --- 620,629 ---- if (rename_uses (copy, rename_map, &gsi_tgt, region, loop, iv_map, gloog_error)) ! { ! gcc_assert (gsi_stmt (gsi_tgt) == copy); ! fold_stmt_inplace (&gsi_tgt); ! } update_stmt (copy); } Index: gcc/tree-ssa-dom.c =================================================================== *** gcc/tree-ssa-dom.c (revision 178719) --- gcc/tree-ssa-dom.c (working copy) *************** propagate_rhs_into_lhs (gimple stmt, tre *** 2656,2662 **** GIMPLE_ASSIGN, and there is no way to effect such a transformation in-place. We might want to consider using the more general fold_stmt here. */ ! fold_stmt_inplace (use_stmt); /* Sometimes propagation can expose new operands to the renamer. */ --- 2656,2665 ---- GIMPLE_ASSIGN, and there is no way to effect such a transformation in-place. We might want to consider using the more general fold_stmt here. */ ! { ! gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt); ! fold_stmt_inplace (&gsi); ! } /* Sometimes propagation can expose new operands to the renamer. */ Index: gcc/tree-ssa-forwprop.c =================================================================== *** gcc/tree-ssa-forwprop.c (revision 178719) --- gcc/tree-ssa-forwprop.c (working copy) *************** forward_propagate_into_comparison (gimpl *** 477,484 **** if (tmp) { gimple_assign_set_rhs_from_tree (gsi, tmp); ! fold_stmt_inplace (stmt); ! update_stmt (stmt); if (TREE_CODE (rhs1) == SSA_NAME) cfg_changed |= remove_prop_source_from_use (rhs1); --- 477,484 ---- if (tmp) { gimple_assign_set_rhs_from_tree (gsi, tmp); ! fold_stmt (gsi); ! update_stmt (gsi_stmt (*gsi)); if (TREE_CODE (rhs1) == SSA_NAME) cfg_changed |= remove_prop_source_from_use (rhs1); *************** forward_propagate_addr_into_variable_arr *** 764,775 **** } } gimple_assign_set_rhs_from_tree (use_stmt_gsi, new_rhs); ! use_stmt = gsi_stmt (*use_stmt_gsi); ! ! /* That should have created gimple, so there is no need to ! record information to undo the propagation. */ ! fold_stmt_inplace (use_stmt); ! tidy_after_forward_propagate_addr (use_stmt); return true; } --- 764,771 ---- } } gimple_assign_set_rhs_from_tree (use_stmt_gsi, new_rhs); ! fold_stmt (use_stmt_gsi); ! tidy_after_forward_propagate_addr (gsi_stmt (*use_stmt_gsi)); return true; } *************** forward_propagate_addr_expr_1 (tree name *** 982,988 **** TREE_OPERAND (rhs, 0) = new_ptr; TREE_OPERAND (rhs, 1) = double_int_to_tree (TREE_TYPE (TREE_OPERAND (rhs, 1)), off); ! fold_stmt_inplace (use_stmt); tidy_after_forward_propagate_addr (use_stmt); return res; } --- 978,984 ---- TREE_OPERAND (rhs, 0) = new_ptr; TREE_OPERAND (rhs, 1) = double_int_to_tree (TREE_TYPE (TREE_OPERAND (rhs, 1)), off); ! fold_stmt_inplace (use_stmt_gsi); tidy_after_forward_propagate_addr (use_stmt); return res; } *************** forward_propagate_addr_expr_1 (tree name *** 1018,1024 **** gimple_assign_set_rhs1 (use_stmt, unshare_expr (TREE_OPERAND (def_rhs, 0))); *def_rhs_basep = saved; ! fold_stmt_inplace (use_stmt); tidy_after_forward_propagate_addr (use_stmt); return res; } --- 1014,1020 ---- gimple_assign_set_rhs1 (use_stmt, unshare_expr (TREE_OPERAND (def_rhs, 0))); *def_rhs_basep = saved; ! fold_stmt_inplace (use_stmt_gsi); tidy_after_forward_propagate_addr (use_stmt); return res; } *************** simplify_bitwise_binary (gimple_stmt_ite *** 1906,1917 **** always permitted. Returns true if the CFG was changed. */ static bool ! associate_plusminus (gimple stmt) { tree rhs1 = gimple_assign_rhs1 (stmt); tree rhs2 = gimple_assign_rhs2 (stmt); enum tree_code code = gimple_assign_rhs_code (stmt); - gimple_stmt_iterator gsi; bool changed; /* We can't reassociate at all for saturating types. */ --- 1902,1913 ---- always permitted. Returns true if the CFG was changed. */ static bool ! associate_plusminus (gimple_stmt_iterator *gsi) { + gimple stmt = gsi_stmt (*gsi); tree rhs1 = gimple_assign_rhs1 (stmt); tree rhs2 = gimple_assign_rhs2 (stmt); enum tree_code code = gimple_assign_rhs_code (stmt); bool changed; /* We can't reassociate at all for saturating types. */ *************** associate_plusminus (gimple stmt) *** 1986,1992 **** via commutating the addition and contracting operations to zero by reassociation. */ - gsi = gsi_for_stmt (stmt); if (TREE_CODE (rhs1) == SSA_NAME) { gimple def_stmt = SSA_NAME_DEF_STMT (rhs1); --- 1982,1987 ---- *************** associate_plusminus (gimple stmt) *** 2006,2013 **** ? TREE_CODE (def_rhs2) : NEGATE_EXPR); rhs1 = def_rhs2; rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (&gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (gsi) == stmt); gimple_set_modified (stmt, true); } else if (operand_equal_p (def_rhs2, rhs2, 0) --- 2001,2008 ---- ? TREE_CODE (def_rhs2) : NEGATE_EXPR); rhs1 = def_rhs2; rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (*gsi) == stmt); gimple_set_modified (stmt, true); } else if (operand_equal_p (def_rhs2, rhs2, 0) *************** associate_plusminus (gimple stmt) *** 2017,2024 **** code = TREE_CODE (def_rhs1); rhs1 = def_rhs1; rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (&gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (gsi) == stmt); gimple_set_modified (stmt, true); } else if (TREE_CODE (rhs2) == INTEGER_CST --- 2012,2019 ---- code = TREE_CODE (def_rhs1); rhs1 = def_rhs1; rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (*gsi) == stmt); gimple_set_modified (stmt, true); } else if (TREE_CODE (rhs2) == INTEGER_CST *************** associate_plusminus (gimple stmt) *** 2068,2075 **** code = INTEGER_CST; rhs1 = build_int_cst_type (TREE_TYPE (rhs2), -1); rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (&gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (gsi) == stmt); gimple_set_modified (stmt, true); } else if (code == PLUS_EXPR --- 2063,2070 ---- code = INTEGER_CST; rhs1 = build_int_cst_type (TREE_TYPE (rhs2), -1); rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (*gsi) == stmt); gimple_set_modified (stmt, true); } else if (code == PLUS_EXPR *************** associate_plusminus (gimple stmt) *** 2079,2086 **** code = NEGATE_EXPR; rhs1 = def_rhs1; rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (&gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (gsi) == stmt); gimple_set_modified (stmt, true); } } --- 2074,2081 ---- code = NEGATE_EXPR; rhs1 = def_rhs1; rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (*gsi) == stmt); gimple_set_modified (stmt, true); } } *************** associate_plusminus (gimple stmt) *** 2106,2113 **** ? NEGATE_EXPR : TREE_CODE (def_rhs2)); rhs1 = def_rhs2; rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (&gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (gsi) == stmt); gimple_set_modified (stmt, true); } else if (operand_equal_p (def_rhs2, rhs1, 0) --- 2101,2108 ---- ? NEGATE_EXPR : TREE_CODE (def_rhs2)); rhs1 = def_rhs2; rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (*gsi) == stmt); gimple_set_modified (stmt, true); } else if (operand_equal_p (def_rhs2, rhs1, 0) *************** associate_plusminus (gimple stmt) *** 2118,2125 **** ? TREE_CODE (def_rhs1) : NEGATE_EXPR); rhs1 = def_rhs1; rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (&gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (gsi) == stmt); gimple_set_modified (stmt, true); } else if (TREE_CODE (rhs1) == INTEGER_CST --- 2113,2120 ---- ? TREE_CODE (def_rhs1) : NEGATE_EXPR); rhs1 = def_rhs1; rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (*gsi) == stmt); gimple_set_modified (stmt, true); } else if (TREE_CODE (rhs1) == INTEGER_CST *************** associate_plusminus (gimple stmt) *** 2168,2175 **** code = INTEGER_CST; rhs1 = build_int_cst_type (TREE_TYPE (rhs1), -1); rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (&gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (gsi) == stmt); gimple_set_modified (stmt, true); } } --- 2163,2170 ---- code = INTEGER_CST; rhs1 = build_int_cst_type (TREE_TYPE (rhs1), -1); rhs2 = NULL_TREE; ! gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); ! gcc_assert (gsi_stmt (*gsi) == stmt); gimple_set_modified (stmt, true); } } *************** associate_plusminus (gimple stmt) *** 2179,2185 **** out: if (gimple_modified_p (stmt)) { ! fold_stmt_inplace (stmt); update_stmt (stmt); if (maybe_clean_or_replace_eh_stmt (stmt, stmt) && gimple_purge_dead_eh_edges (gimple_bb (stmt))) --- 2174,2180 ---- out: if (gimple_modified_p (stmt)) { ! fold_stmt_inplace (gsi); update_stmt (stmt); if (maybe_clean_or_replace_eh_stmt (stmt, stmt) && gimple_purge_dead_eh_edges (gimple_bb (stmt))) *************** ssa_forward_propagate_and_combine (void) *** 2438,2444 **** else if (is_gimple_min_invariant (rhs)) { /* Make sure to fold &a[0] + off_1 here. */ ! fold_stmt_inplace (stmt); update_stmt (stmt); if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) gsi_next (&gsi); --- 2433,2439 ---- else if (is_gimple_min_invariant (rhs)) { /* Make sure to fold &a[0] + off_1 here. */ ! fold_stmt_inplace (&gsi); update_stmt (stmt); if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) gsi_next (&gsi); *************** ssa_forward_propagate_and_combine (void) *** 2495,2501 **** changed = simplify_bitwise_binary (&gsi); else if (code == PLUS_EXPR || code == MINUS_EXPR) ! changed = associate_plusminus (stmt); else if (CONVERT_EXPR_CODE_P (code) || code == FLOAT_EXPR || code == FIX_TRUNC_EXPR) --- 2490,2496 ---- changed = simplify_bitwise_binary (&gsi); else if (code == PLUS_EXPR || code == MINUS_EXPR) ! changed = associate_plusminus (&gsi); else if (CONVERT_EXPR_CODE_P (code) || code == FLOAT_EXPR || code == FIX_TRUNC_EXPR) Index: gcc/tree-ssa-math-opts.c =================================================================== *** gcc/tree-ssa-math-opts.c (revision 178719) --- gcc/tree-ssa-math-opts.c (working copy) *************** replace_reciprocal (use_operand_p use_p) *** 398,406 **** if (optimize_bb_for_speed_p (bb) && occ->recip_def && use_stmt != occ->recip_def_stmt) { gimple_assign_set_rhs_code (use_stmt, MULT_EXPR); SET_USE (use_p, occ->recip_def); ! fold_stmt_inplace (use_stmt); update_stmt (use_stmt); } } --- 398,407 ---- 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 (&gsi); update_stmt (use_stmt); } } *************** execute_cse_reciprocals (void) *** 610,617 **** FOR_EACH_IMM_USE_STMT (stmt, ui, arg1) { gimple_assign_set_rhs_code (stmt, MULT_EXPR); ! fold_stmt_inplace (stmt); update_stmt (stmt); } } --- 611,619 ---- 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 (&gsi); update_stmt (stmt); } } Index: gcc/tree-ssa.c =================================================================== *** gcc/tree-ssa.c (revision 178719) --- gcc/tree-ssa.c (working copy) *************** insert_debug_temp_for_var_def (gimple_st *** 471,477 **** /* If we didn't replace uses with a debug decl fold the resulting expression. Otherwise we end up with invalid IL. */ if (TREE_CODE (value) != DEBUG_EXPR_DECL) ! fold_stmt_inplace (stmt); } else gimple_debug_bind_reset_value (stmt); --- 471,480 ---- /* If we didn't replace uses with a debug decl fold the resulting expression. Otherwise we end up with invalid IL. */ if (TREE_CODE (value) != DEBUG_EXPR_DECL) ! { ! gimple_stmt_iterator gsi = gsi_for_stmt (stmt); ! fold_stmt_inplace (&gsi); ! } } else gimple_debug_bind_reset_value (stmt);