Several passes needlessly cleanup EH after gsi_remove because they do not know whether the stmt was removed from EH regions. The following patch returns this information from gsi_remove and adjusts all users I could find appropriately.
Bootstrapped and tested on x86_64-unknown-linux-gnu, testing in progress. Richard. 2012-04-04 Richard Guenther <rguent...@suse.de> * gimple-iterator.c (gsi_remove): Return whether EH edges need to be cleanup. * gimple.h (gsi_remove): Adjust. * tree-ssa-operands.c (unlink_stmt_vdef): Optimize. * tree-ssa-dom.c (optimize_stmt): Use gsi_remove result. * tree-ssa-dse.c (dse_optimize_stmt): Likewise. * tree-ssa-forwprop.c (remove_prop_source_from_use): Likewise. * tree-ssa-math-opts.c (execute_optimize_widening_mul): Likewise. * tree-ssa-pre.c (eliminate): Likewise. Index: gcc/gimple.h =================================================================== *** gcc/gimple.h.orig 2012-04-04 14:57:38.000000000 +0200 --- gcc/gimple.h 2012-04-04 14:58:20.633570347 +0200 *************** void gsi_insert_seq_after (gimple_stmt_i *** 5095,5101 **** enum gsi_iterator_update); void gsi_insert_seq_after_without_update (gimple_stmt_iterator *, gimple_seq, enum gsi_iterator_update); ! void gsi_remove (gimple_stmt_iterator *, bool); gimple_stmt_iterator gsi_for_stmt (gimple); void gsi_move_after (gimple_stmt_iterator *, gimple_stmt_iterator *); void gsi_move_before (gimple_stmt_iterator *, gimple_stmt_iterator *); --- 5095,5101 ---- enum gsi_iterator_update); void gsi_insert_seq_after_without_update (gimple_stmt_iterator *, gimple_seq, enum gsi_iterator_update); ! bool gsi_remove (gimple_stmt_iterator *, bool); gimple_stmt_iterator gsi_for_stmt (gimple); void gsi_move_after (gimple_stmt_iterator *, gimple_stmt_iterator *); void gsi_move_before (gimple_stmt_iterator *, gimple_stmt_iterator *); Index: gcc/gimple-iterator.c =================================================================== *** gcc/gimple-iterator.c.orig 2012-04-04 14:57:38.000000000 +0200 --- gcc/gimple-iterator.c 2012-04-04 14:58:56.661952844 +0200 *************** gsi_insert_after (gimple_stmt_iterator * *** 499,511 **** REMOVE_PERMANENTLY is true when the statement is going to be removed from the IL and not reinserted elsewhere. In that case we remove the statement pointed to by iterator I from the EH tables, and free its ! operand caches. Otherwise we do not modify this information. */ ! void gsi_remove (gimple_stmt_iterator *i, bool remove_permanently) { gimple_seq_node cur, next, prev; gimple stmt = gsi_stmt (*i); if (gimple_code (stmt) != GIMPLE_PHI) insert_debug_temps_for_defs (i); --- 499,513 ---- REMOVE_PERMANENTLY is true when the statement is going to be removed from the IL and not reinserted elsewhere. In that case we remove the statement pointed to by iterator I from the EH tables, and free its ! operand caches. Otherwise we do not modify this information. Returns ! true whether EH edge cleanup is required. */ ! bool gsi_remove (gimple_stmt_iterator *i, bool remove_permanently) { gimple_seq_node cur, next, prev; gimple stmt = gsi_stmt (*i); + bool require_eh_edge_purge = false; if (gimple_code (stmt) != GIMPLE_PHI) insert_debug_temps_for_defs (i); *************** gsi_remove (gimple_stmt_iterator *i, boo *** 517,523 **** if (remove_permanently) { ! remove_stmt_from_eh_lp (stmt); gimple_remove_stmt_histograms (cfun, stmt); } --- 519,525 ---- if (remove_permanently) { ! require_eh_edge_purge = remove_stmt_from_eh_lp (stmt); gimple_remove_stmt_histograms (cfun, stmt); } *************** gsi_remove (gimple_stmt_iterator *i, boo *** 537,542 **** --- 539,546 ---- gimple_seq_set_last (i->seq, prev); i->ptr = next; + + return require_eh_edge_purge; } Index: gcc/tree-ssa-operands.c =================================================================== *** gcc/tree-ssa-operands.c.orig 2012-04-04 14:57:38.000000000 +0200 --- gcc/tree-ssa-operands.c 2012-04-04 14:58:20.634570358 +0200 *************** unlink_stmt_vdef (gimple stmt) *** 1475,1492 **** imm_use_iterator iter; gimple use_stmt; tree vdef = gimple_vdef (stmt); if (!vdef || TREE_CODE (vdef) != SSA_NAME) return; ! FOR_EACH_IMM_USE_STMT (use_stmt, iter, gimple_vdef (stmt)) { FOR_EACH_IMM_USE_ON_STMT (use_p, iter) ! SET_USE (use_p, gimple_vuse (stmt)); } ! if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_vdef (stmt))) ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_vuse (stmt)) = 1; } --- 1475,1493 ---- imm_use_iterator iter; gimple use_stmt; tree vdef = gimple_vdef (stmt); + tree vuse = gimple_vuse (stmt); if (!vdef || TREE_CODE (vdef) != SSA_NAME) return; ! FOR_EACH_IMM_USE_STMT (use_stmt, iter, vdef) { FOR_EACH_IMM_USE_ON_STMT (use_p, iter) ! SET_USE (use_p, vuse); } ! if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (vdef)) ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (vuse) = 1; } Index: gcc/tree-ssa-dom.c =================================================================== *** gcc/tree-ssa-dom.c.orig 2012-04-04 14:57:38.000000000 +0200 --- gcc/tree-ssa-dom.c 2012-04-04 15:02:16.055069581 +0200 *************** optimize_stmt (basic_block bb, gimple_st *** 2294,2303 **** && rhs == cached_lhs) { basic_block bb = gimple_bb (stmt); - int lp_nr = lookup_stmt_eh_lp (stmt); unlink_stmt_vdef (stmt); ! gsi_remove (&si, true); ! if (lp_nr != 0) { bitmap_set_bit (need_eh_cleanup, bb->index); if (dump_file && (dump_flags & TDF_DETAILS)) --- 2294,2301 ---- && rhs == cached_lhs) { basic_block bb = gimple_bb (stmt); unlink_stmt_vdef (stmt); ! if (gsi_remove (&si, true)) { bitmap_set_bit (need_eh_cleanup, bb->index); if (dump_file && (dump_flags & TDF_DETAILS)) Index: gcc/tree-ssa-dse.c =================================================================== *** gcc/tree-ssa-dse.c.orig 2012-04-04 14:57:38.000000000 +0200 --- gcc/tree-ssa-dse.c 2012-04-04 15:02:35.819279426 +0200 *************** dse_optimize_stmt (gimple_stmt_iterator *** 257,266 **** /* Then we need to fix the operand of the consuming stmt. */ unlink_stmt_vdef (stmt); - bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index); - /* Remove the dead store. */ ! gsi_remove (&gsi, true); /* And release any SSA_NAMEs set in this statement back to the SSA_NAME manager. */ --- 257,265 ---- /* Then we need to fix the operand of the consuming stmt. */ unlink_stmt_vdef (stmt); /* Remove the dead store. */ ! if (gsi_remove (&gsi, true)) ! bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index); /* And release any SSA_NAMEs set in this statement back to the SSA_NAME manager. */ Index: gcc/tree-ssa-forwprop.c =================================================================== *** gcc/tree-ssa-forwprop.c.orig 2012-04-04 14:57:38.000000000 +0200 --- gcc/tree-ssa-forwprop.c 2012-04-04 14:59:18.350183049 +0200 *************** remove_prop_source_from_use (tree name) *** 325,333 **** bb = gimple_bb (stmt); gsi = gsi_for_stmt (stmt); unlink_stmt_vdef (stmt); ! gsi_remove (&gsi, true); release_defs (stmt); - cfg_changed |= gimple_purge_dead_eh_edges (bb); name = is_gimple_assign (stmt) ? gimple_assign_rhs1 (stmt) : NULL_TREE; } while (name && TREE_CODE (name) == SSA_NAME); --- 325,333 ---- bb = gimple_bb (stmt); gsi = gsi_for_stmt (stmt); unlink_stmt_vdef (stmt); ! if (gsi_remove (&gsi, true)) ! cfg_changed |= gimple_purge_dead_eh_edges (bb); release_defs (stmt); name = is_gimple_assign (stmt) ? gimple_assign_rhs1 (stmt) : NULL_TREE; } while (name && TREE_CODE (name) == SSA_NAME); Index: gcc/tree-ssa-math-opts.c =================================================================== *** gcc/tree-ssa-math-opts.c.orig 2012-04-04 14:57:38.000000000 +0200 --- gcc/tree-ssa-math-opts.c 2012-04-04 15:03:35.227910166 +0200 *************** execute_optimize_widening_mul (void) *** 2658,2667 **** gimple_call_arg (stmt, 0))) { unlink_stmt_vdef (stmt); ! gsi_remove (&gsi, true); ! release_defs (stmt); ! if (gimple_purge_dead_eh_edges (bb)) cfg_changed = true; continue; } break; --- 2658,2667 ---- gimple_call_arg (stmt, 0))) { unlink_stmt_vdef (stmt); ! if (gsi_remove (&gsi, true) ! && gimple_purge_dead_eh_edges (bb)) cfg_changed = true; + release_defs (stmt); continue; } break; Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c.orig 2012-04-04 14:57:38.000000000 +0200 --- gcc/tree-ssa-pre.c 2012-04-04 15:04:00.221175331 +0200 *************** eliminate (void) *** 4629,4639 **** basic_block bb = gimple_bb (stmt); gsi = gsi_for_stmt (stmt); unlink_stmt_vdef (stmt); ! gsi_remove (&gsi, true); ! /* ??? gsi_remove doesn't tell us whether the stmt was ! in EH tables and thus whether we need to purge EH edges. ! Simply schedule the block for a cleanup. */ ! bitmap_set_bit (need_eh_cleanup, bb->index); if (TREE_CODE (lhs) == SSA_NAME) bitmap_clear_bit (inserted_exprs, SSA_NAME_VERSION (lhs)); release_defs (stmt); --- 4629,4636 ---- basic_block bb = gimple_bb (stmt); gsi = gsi_for_stmt (stmt); unlink_stmt_vdef (stmt); ! if (gsi_remove (&gsi, true)) ! bitmap_set_bit (need_eh_cleanup, bb->index); if (TREE_CODE (lhs) == SSA_NAME) bitmap_clear_bit (inserted_exprs, SSA_NAME_VERSION (lhs)); release_defs (stmt);