diff options
author | steven <steven@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-03-05 14:45:23 +0000 |
---|---|---|
committer | steven <steven@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-03-05 14:45:23 +0000 |
commit | 390f4a4b5eb4ff6f4f06d7346d641729703bbad6 (patch) | |
tree | 4ff07f0d40ea5cef8af4fe46b0f91b0ca63c916a /gcc/except.c | |
parent | f5f9d87c0243ce7d99422290997432990a4d8de9 (diff) | |
download | gcc-390f4a4b5eb4ff6f4f06d7346d641729703bbad6.tar.gz |
gcc/
PR c++/55135
* except.h (remove_unreachable_eh_regions): New prototype.
* except.c (remove_eh_handler_splicer): New function, split out
of remove_eh_handler.
(remove_eh_handler): Use remove_eh_handler_splicer. Add comment
warning about running it on many EH regions one at a time.
(remove_unreachable_eh_regions_worker): New function, walk the
EH tree in depth-first order and remove non-marked regions.
(remove_unreachable_eh_regions): New function.
* tree-eh.c (mark_reachable_handlers): New function, split out
from remove_unreachable_handlers.
(remove_unreachable_handlers): Use mark_reachable_handlers and
remove_unreachable_eh_regions.
(remove_unreachable_handlers_no_lp): Use mark_reachable_handlers
and remove_unreachable_eh_regions.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@196464 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/except.c')
-rw-r--r-- | gcc/except.c | 71 |
1 files changed, 60 insertions, 11 deletions
diff --git a/gcc/except.c b/gcc/except.c index 3e424eb9d7f..4e85f731837 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -1505,12 +1505,12 @@ remove_eh_landing_pad (eh_landing_pad lp) (*cfun->eh->lp_array)[lp->index] = NULL; } -/* Splice REGION from the region tree. */ +/* Splice the EH region at PP from the region tree. */ -void -remove_eh_handler (eh_region region) +static void +remove_eh_handler_splicer (eh_region *pp) { - eh_region *pp, *pp_start, p, outer; + eh_region region = *pp; eh_landing_pad lp; for (lp = region->landing_pads; lp ; lp = lp->next_lp) @@ -1520,15 +1520,11 @@ remove_eh_handler (eh_region region) (*cfun->eh->lp_array)[lp->index] = NULL; } - outer = region->outer; - if (outer) - pp_start = &outer->inner; - else - pp_start = &cfun->eh->region_tree; - for (pp = pp_start, p = *pp; p != region; pp = &p->next_peer, p = *pp) - continue; if (region->inner) { + eh_region p, outer; + outer = region->outer; + *pp = p = region->inner; do { @@ -1543,6 +1539,59 @@ remove_eh_handler (eh_region region) (*cfun->eh->region_array)[region->index] = NULL; } +/* Splice a single EH region REGION from the region tree. + + To unlink REGION, we need to find the pointer to it with a relatively + expensive search in REGION's outer region. If you are going to + remove a number of handlers, using remove_unreachable_eh_regions may + be a better option. */ + +void +remove_eh_handler (eh_region region) +{ + eh_region *pp, *pp_start, p, outer; + + outer = region->outer; + if (outer) + pp_start = &outer->inner; + else + pp_start = &cfun->eh->region_tree; + for (pp = pp_start, p = *pp; p != region; pp = &p->next_peer, p = *pp) + continue; + + remove_eh_handler_splicer (pp); +} + +/* Worker for remove_unreachable_eh_regions. + PP is a pointer to the region to start a region tree depth-first + search from. R_REACHABLE is the set of regions that have to be + preserved. */ + +static void +remove_unreachable_eh_regions_worker (eh_region *pp, sbitmap r_reachable) +{ + while (*pp) + { + eh_region region = *pp; + remove_unreachable_eh_regions_worker (®ion->inner, r_reachable); + if (!bitmap_bit_p (r_reachable, region->index)) + remove_eh_handler_splicer (pp); + else + pp = ®ion->next_peer; + } +} + +/* Splice all EH regions *not* marked in R_REACHABLE from the region tree. + Do this by traversing the EH tree top-down and splice out regions that + are not marked. By removing regions from the leaves, we avoid costly + searches in the region tree. */ + +void +remove_unreachable_eh_regions (sbitmap r_reachable) +{ + remove_unreachable_eh_regions_worker (&cfun->eh->region_tree, r_reachable); +} + /* Invokes CALLBACK for every exception handler landing pad label. Only used by reload hackery; should not be used by new code. */ |