aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-eh.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2009-04-25 20:27:19 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2009-04-25 18:27:19 +0000
commita3710436b62ad4c025de1b3b5a97e6d3eb820edf (patch)
treef9735ec8c3866c20255be203e45595367cbbe8e4 /gcc/tree-eh.c
parent3764d512d514c5011bf6473075444d49de284e05 (diff)
downloadgcc-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.c58
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;