diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-25 09:02:05 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-25 09:02:05 +0000 |
commit | 3d1eacdb7e7d943c99ac9f18181eab26d3e03cd1 (patch) | |
tree | d9aa3a1c938bc4df3cbd34eb918dde4d83d84237 /gcc/except.c | |
parent | a15d1cafc1d164f1995f143feb46ea2ee4e85017 (diff) | |
download | gcc-3d1eacdb7e7d943c99ac9f18181eab26d3e03cd1.tar.gz |
* tree-eh.c (tree_remove_unreachable_handlers): Handle shared labels.
(tree_empty_eh_handler_p): Allow non-EH predecestors; allow region
to be reached by different label than left.
(update_eh_edges): Update comment; remove edge_to_remove if possible
and return true if suceeded.
(cleanup_empty_eh): Accept sharing map; handle shared regions.
(cleanup_eh): Compute sharing map.
* except.c (remove_eh_handler_and_replace): Add argument if we should
update regions.
(remove_unreachable_regions): Update for label sharing.
(label_to_region_map): Likewise.
(get_next_region_sharing_label): New function.
(remove_eh_handler_and_replace): Add update_catch_try parameter; update
prev_try pointers.
(remove_eh_handler): Update.
(remove_eh_region_and_replace_by_outer_of): New function.
* except.h (struct eh_region): Add next_region_sharing_label.
(remove_eh_region_and_replace_by_outer_of,
get_next_region_sharing_label): Declare.
* tree-cfgcleanup.c (tree_forwarder_block_p): Simplify.
* tree-cfg.c (split_critical_edges): Split also edges where we can't
insert code even if they are not critical.
* tree-cfg.c (gimple_can_merge_blocks_p): EH edges are unmergable.
(gimple_can_remove_branch_p): EH edges won't remove branch by
redirection.
* tree-inline.c (update_ssa_across_abnormal_edges): Do handle
updating of non-abnormal EH edges.
* tree-cfg.c (gimple_can_merge_blocks_p): EH edges are unmergable.
(gimple_can_remove_branch_p): EH edges are unremovable by redirection.
(split_critical_edges): Split also edges where emitting code on them
will lead to splitting later.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@146763 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/except.c')
-rw-r--r-- | gcc/except.c | 83 |
1 files changed, 74 insertions, 9 deletions
diff --git a/gcc/except.c b/gcc/except.c index 0a2bf3284c0..599ad6fe0c6 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -145,7 +145,7 @@ static void sjlj_build_landing_pads (void); static void remove_eh_handler (struct eh_region *); static void remove_eh_handler_and_replace (struct eh_region *, - struct eh_region *); + struct eh_region *, bool); /* The return value of reachable_next_level. */ enum reachable_code @@ -742,7 +742,7 @@ remove_unreachable_regions (sbitmap reachable, sbitmap contains_stmt) fprintf (dump_file, "Replacing MUST_NOT_THROW region %i by %i\n", r->region_number, first_must_not_throw->region_number); - remove_eh_handler_and_replace (r, first_must_not_throw); + remove_eh_handler_and_replace (r, first_must_not_throw, false); first_must_not_throw->may_contain_throw |= r->may_contain_throw; } else @@ -757,11 +757,12 @@ remove_unreachable_regions (sbitmap reachable, sbitmap contains_stmt) /* Return array mapping LABEL_DECL_UID to region such that region's tree_label is identical to label. */ -VEC(int,heap) * +VEC (int, heap) * label_to_region_map (void) { - VEC(int,heap) * label_to_region = NULL; + VEC (int, heap) * label_to_region = NULL; int i; + int idx; VEC_safe_grow_cleared (int, heap, label_to_region, cfun->cfg->last_label_uid + 1); @@ -769,8 +770,14 @@ label_to_region_map (void) { struct eh_region *r = VEC_index (eh_region, cfun->eh->region_array, i); if (r && r->region_number == i - && r->tree_label && LABEL_DECL_UID (r->tree_label) >= 0) + && r->tree_label && LABEL_DECL_UID (r->tree_label) >= 0) { + if ((idx = VEC_index (int, label_to_region, + LABEL_DECL_UID (r->tree_label))) != 0) + r->next_region_sharing_label = + VEC_index (eh_region, cfun->eh->region_array, idx); + else + r->next_region_sharing_label = NULL; VEC_replace (int, label_to_region, LABEL_DECL_UID (r->tree_label), i); } @@ -785,6 +792,20 @@ num_eh_regions (void) return cfun->eh->last_region_number + 1; } +/* Return next region sharing same label as REGION. */ + +int +get_next_region_sharing_label (int region) +{ + struct eh_region *r; + if (!region) + return 0; + r = VEC_index (eh_region, cfun->eh->region_array, region); + if (!r || !r->next_region_sharing_label) + return 0; + return r->next_region_sharing_label->region_number; +} + /* Set up EH labels for RTL. */ void @@ -2161,16 +2182,46 @@ finish_eh_generation (void) /* This section handles removing dead code for flow. */ -/* Splice REGION from the region tree and replace it by REPLACE etc. */ +/* Splice REGION from the region tree and replace it by REPLACE etc. + When UPDATE_CATCH_TRY is true mind updating links from catch to try + region.*/ static void remove_eh_handler_and_replace (struct eh_region *region, - struct eh_region *replace) + struct eh_region *replace, + bool update_catch_try) { struct eh_region **pp, **pp_start, *p, *outer, *inner; rtx lab; outer = region->outer; + + /* When we are moving the region in EH tree, update prev_try pointers. */ + if (outer != replace && region->inner) + { + struct eh_region *prev_try = find_prev_try (replace); + p = region->inner; + while (p != region) + { + if (p->type == ERT_CLEANUP) + p->u.cleanup.prev_try = prev_try; + if (p->type != ERT_TRY + && p->type != ERT_MUST_NOT_THROW + && (p->type != ERT_ALLOWED_EXCEPTIONS + || p->u.allowed.type_list) + && p->inner) + p = p->inner; + else if (p->next_peer) + p = p->next_peer; + else + { + while (p != region && !p->next_peer) + p = p->outer; + if (p != region) + p = p->next_peer; + } + } + } /* For the benefit of efficiently handling REG_EH_REGION notes, replace this region in the region array with its containing region. Note that previous region deletions may result in @@ -2226,7 +2277,8 @@ remove_eh_handler_and_replace (struct eh_region *region, *pp_start = inner; } - if (region->type == ERT_CATCH) + if (region->type == ERT_CATCH + && update_catch_try) { struct eh_region *eh_try, *next, *prev; @@ -2260,7 +2312,7 @@ remove_eh_handler_and_replace (struct eh_region *region, static void remove_eh_handler (struct eh_region *region) { - remove_eh_handler_and_replace (region, region->outer); + remove_eh_handler_and_replace (region, region->outer, true); } /* Remove Eh region R that has turned out to have no code in its handler. */ @@ -2274,6 +2326,19 @@ remove_eh_region (int r) remove_eh_handler (region); } +/* Remove Eh region R that has turned out to have no code in its handler + and replace in by R2. */ + +void +remove_eh_region_and_replace_by_outer_of (int r, int r2) +{ + struct eh_region *region, *region2; + + region = VEC_index (eh_region, cfun->eh->region_array, r); + region2 = VEC_index (eh_region, cfun->eh->region_array, r2); + remove_eh_handler_and_replace (region, region2->outer, true); +} + /* Invokes CALLBACK for every exception handler label. Only used by old loop hackery; should not be used by new code. */ |