diff options
author | Jan Hubicka <jh@suse.cz> | 2009-04-25 20:27:19 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2009-04-25 18:27:19 +0000 |
commit | a3710436b62ad4c025de1b3b5a97e6d3eb820edf (patch) | |
tree | f9735ec8c3866c20255be203e45595367cbbe8e4 /gcc/tree-eh.c | |
parent | 3764d512d514c5011bf6473075444d49de284e05 (diff) | |
download | gcc-a3710436b62ad4c025de1b3b5a97e6d3eb820edf.zip gcc-a3710436b62ad4c025de1b3b5a97e6d3eb820edf.tar.gz gcc-a3710436b62ad4c025de1b3b5a97e6d3eb820edf.tar.bz2 |
tree.c (list_equal_p): New function.
* tree.c (list_equal_p): New function.
* tree.h (list_equal_p): Declare.
* coretypes.h (edge_def, edge, const_edge, basic_block_def
basic_block_def, basic_block, const_basic_block): New.
* tree-eh.c (make_eh_edge): EH edges are not abnormal.
(redirect_eh_edge): New function.
(make_eh_edge_update_phi): EH edges are not abnormal.
* except.c: Include tree-flow.h.
(list_match): New function.
(eh_region_replaceable_by_p): New function.
(replace_region): New function.
(hash_type_list): New function.
(hash_eh_region): New function.
(eh_regions_equal_p): New function.
(merge_peers): New function.
(remove_unreachable_regions): Verify EH tree when checking;
merge peers.
(copy_eh_region_1): New function.
(copy_eh_region): New function.
(push_reachable_handler): New function.
(build_post_landing_pads, dw2_build_landing_pads): Be ready for
regions without label but with live RESX.
* except.h (redirect_eh_edge_to_label): New.
* tree-flow.h (redirect_eh_edge): New.
* coretypes.h (edge_def, edge, const_edge, basic_block_def
basic_block_def, basic_block, const_basic_block): Remove.
* Makefile.in (except.o): Add dependency on tree-flow.h
* tree-cfg.c (gimple_redirect_edge_and_branch): Handle EH edges.
* basic-block.h (edge, const_edge, basic_block, const_basic_block):
Remove.
From-SVN: r146776
Diffstat (limited to 'gcc/tree-eh.c')
-rw-r--r-- | gcc/tree-eh.c | 58 |
1 files changed, 54 insertions, 4 deletions
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index c9268f9..80014e112 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -1962,7 +1962,7 @@ make_eh_edge (struct eh_region *region, void *data) src = gimple_bb (stmt); dst = label_to_block (lab); - make_edge (src, dst, EDGE_ABNORMAL | EDGE_EH); + make_edge (src, dst, EDGE_EH); } /* See if STMT is call that might be inlined. */ @@ -2019,6 +2019,50 @@ make_eh_edges (gimple stmt) EDGE_SUCC (bb, 0)->probability = REG_BR_PROB_BASE; } +/* Redirect EH edge E to NEW_BB. */ + +edge +redirect_eh_edge (edge e, basic_block new_bb) +{ + gimple stmt = gsi_stmt (gsi_last_bb (e->src)); + int region_nr, new_region_nr; + bool is_resx; + bool inlinable = false; + tree label = gimple_block_label (new_bb); + struct eh_region *r; + + if (gimple_code (stmt) == GIMPLE_RESX) + { + region_nr = gimple_resx_region (stmt); + is_resx = true; + } + else + { + region_nr = lookup_stmt_eh_region (stmt); + gcc_assert (region_nr >= 0); + is_resx = false; + inlinable = inlinable_call_p (stmt); + } + + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Redirecting EH edge %i->%i to %i, region %i, resx %i\n", + e->src->index, e->dest->index, new_bb->index, region_nr, is_resx); + r = redirect_eh_edge_to_label (e, label, is_resx, inlinable, region_nr); + new_region_nr = get_eh_region_number (r); + if (new_region_nr != region_nr) + { + if (is_resx) + gimple_resx_set_region (stmt, new_region_nr); + else + { + remove_stmt_from_eh_region (stmt); + add_stmt_to_eh_region (stmt, new_region_nr); + } + } + e = ssa_redirect_edge (e, new_bb); + return e; +} + static bool mark_eh_edge_found_error; /* Mark edge make_eh_edge would create for given region by setting it aux @@ -2702,7 +2746,9 @@ tree_remove_unreachable_handlers (void) SET_BIT (reachable, region); } if (gimple_code (stmt) == GIMPLE_RESX) - SET_BIT (reachable, gimple_resx_region (stmt)); + SET_BIT (reachable, + VEC_index (eh_region, cfun->eh->region_array, + gimple_resx_region (stmt))->region_number); if ((region = lookup_stmt_eh_region (stmt)) >= 0) SET_BIT (contains_stmt, region); } @@ -2937,7 +2983,7 @@ make_eh_edge_and_update_phi (struct eh_region *region, void *data) } dominance_info_invalidated = true; e2 = find_edge (info->bb_to_remove, dst); - e = make_edge (src, dst, EDGE_ABNORMAL | EDGE_EH); + e = make_edge (src, dst, EDGE_EH); e->aux = e; gcc_assert (e2); for (si = gsi_start_phis (dst); !gsi_end_p (si); gsi_next (&si)) @@ -3091,7 +3137,11 @@ cleanup_empty_eh (basic_block bb, VEC(int,heap) * label_to_region) is really dead. */ if (found && !has_non_eh_preds) - remove_eh_region (region); + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Empty EH handler %i removed.\n", region); + remove_eh_region (region); + } else if (!removed_some) return false; |