except.c (remove_eh_handler_and_replace): Break out from ...

* except.c (remove_eh_handler_and_replace): Break out from ...
	(remove_eh_handler): ... here.
	(bring_to_root): New function.
	(remove_unreachable_regions): Collect MUST_NOT_THROW, unify runtime
	handled ones, bring others to root of tree.

From-SVN: r145545
This commit is contained in:
Jan Hubicka 2009-04-04 19:15:31 +02:00 committed by Jan Hubicka
parent 4cb735f794
commit 14925fcd47
2 changed files with 110 additions and 14 deletions

View File

@ -1,3 +1,11 @@
2009-04-04 Jan Hubicka <jh@suse.cz>
* except.c (remove_eh_handler_and_replace): Break out from ...
(remove_eh_handler): ... here.
(bring_to_root): New function.
(remove_unreachable_regions): Collect MUST_NOT_THROW, unify runtime
handled ones, bring others to root of tree.
2009-04-04 Jan Hubicka <jh@suse.cz>
* tree-eh.c (tree_empty_eh_handler_p): Pattern match more curefully.

View File

@ -208,6 +208,7 @@ struct call_site_record GTY(())
DEF_VEC_P(eh_region);
DEF_VEC_ALLOC_P(eh_region, gc);
DEF_VEC_ALLOC_P(eh_region, heap);
/* Used to save exception status for each function. */
struct eh_status GTY(())
@ -252,6 +253,8 @@ static int ehl_eq (const void *, const void *);
static void add_ehl_entry (rtx, struct eh_region *);
static void remove_exception_handler_label (rtx);
static void remove_eh_handler (struct eh_region *);
static void remove_eh_handler_and_replace (struct eh_region *,
struct eh_region *);
static int for_each_eh_label_1 (void **, void *);
/* The return value of reachable_next_level. */
@ -718,21 +721,42 @@ can_be_reached_by_runtime (sbitmap contains_stmt, struct eh_region *r)
}
}
/* Bring region R to the root of tree. */
static void
bring_to_root (struct eh_region *r)
{
struct eh_region **pp;
struct eh_region *outer = r->outer;
if (!r->outer)
return;
for (pp = &outer->inner; *pp != r; pp = &(*pp)->next_peer)
continue;
*pp = r->next_peer;
r->outer = NULL;
r->next_peer = cfun->eh->region_tree;
cfun->eh->region_tree = r;
}
/* Remove all regions whose labels are not reachable.
REACHABLE is bitmap of all regions that are used by the function
CONTAINS_STMT is bitmap of all regions that contains stmt (or NULL). */
void
remove_unreachable_regions (sbitmap reachable, sbitmap contains_stmt)
{
int i;
struct eh_region *r;
VEC(eh_region,heap) *must_not_throws = VEC_alloc (eh_region, heap, 16);
struct eh_region *local_must_not_throw = NULL;
struct eh_region *first_must_not_throw = NULL;
for (i = cfun->eh->last_region_number; i > 0; --i)
{
r = VEC_index (eh_region, cfun->eh->region_array, i);
if (!r)
if (!r || r->region_number != i)
continue;
if (r->region_number == i && !TEST_BIT (reachable, i) && !r->resume)
if (!TEST_BIT (reachable, i) && !r->resume)
{
bool kill_it = true;
@ -783,11 +807,60 @@ remove_unreachable_regions (sbitmap reachable, sbitmap contains_stmt)
r->region_number);
remove_eh_handler (r);
}
else if (r->type == ERT_MUST_NOT_THROW)
{
if (!first_must_not_throw)
first_must_not_throw = r;
VEC_safe_push (eh_region, heap, must_not_throws, r);
}
}
else
if (r->type == ERT_MUST_NOT_THROW)
{
if (!local_must_not_throw)
local_must_not_throw = r;
if (r->outer)
VEC_safe_push (eh_region, heap, must_not_throws, r);
}
}
/* MUST_NOT_THROW regions without local handler are all the same; they
trigger terminate call in runtime.
MUST_NOT_THROW handled locally can differ in debug info associated
to std::terminate () call or if one is coming from Java and other
from C++ whether they call terminate or abort.
We merge all MUST_NOT_THROW regions handled by the run-time into one.
We alsobring all local MUST_NOT_THROW regions to the roots of EH tree
(since unwinding never continues to the outer region anyway).
If MUST_NOT_THROW with local handler is present in the tree, we use
that region to merge into, since it will remain in tree anyway;
otherwise we use first MUST_NOT_THROW.
Merging of locally handled regions needs changes to the CFG. Crossjumping
should take care of this, by looking at the actual code and
ensuring that the cleanup actions are really the same. */
if (local_must_not_throw)
first_must_not_throw = local_must_not_throw;
for (i = 0; VEC_iterate (eh_region, must_not_throws, i, r); i++)
{
if (!r->label && !r->tree_label && r != first_must_not_throw)
{
if (dump_file)
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);
}
else
bring_to_root (r);
}
#ifdef ENABLE_CHECKING
verify_eh_tree (cfun);
#endif
VEC_free (eh_region, heap, must_not_throws);
}
/* Return array mapping LABEL_DECL_UID to region such that region's tree_label
@ -2352,22 +2425,24 @@ remove_exception_handler_label (rtx label)
htab_clear_slot (crtl->eh.exception_handler_label_map, (void **) slot);
}
/* Splice REGION from the region tree etc. */
/* Splice REGION from the region tree and replace it by REPLACE etc. */
static void
remove_eh_handler (struct eh_region *region)
remove_eh_handler_and_replace (struct eh_region *region,
struct eh_region *replace)
{
struct eh_region **pp, **pp_start, *p, *outer, *inner;
rtx lab;
outer = region->outer;
/* 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
multiple copies of this region in the array, so we have a
list of alternate numbers by which we are known. */
outer = region->outer;
VEC_replace (eh_region, cfun->eh->region_array, region->region_number, outer);
VEC_replace (eh_region, cfun->eh->region_array, region->region_number,
replace);
if (region->aka)
{
unsigned i;
@ -2375,17 +2450,17 @@ remove_eh_handler (struct eh_region *region)
EXECUTE_IF_SET_IN_BITMAP (region->aka, 0, i, bi)
{
VEC_replace (eh_region, cfun->eh->region_array, i, outer);
VEC_replace (eh_region, cfun->eh->region_array, i, replace);
}
}
if (outer)
if (replace)
{
if (!outer->aka)
outer->aka = BITMAP_GGC_ALLOC ();
if (!replace->aka)
replace->aka = BITMAP_GGC_ALLOC ();
if (region->aka)
bitmap_ior_into (outer->aka, region->aka);
bitmap_set_bit (outer->aka, region->region_number);
bitmap_ior_into (replace->aka, region->aka);
bitmap_set_bit (replace->aka, region->region_number);
}
if (crtl->eh.built_landing_pads)
@ -2403,12 +2478,16 @@ remove_eh_handler (struct eh_region *region)
continue;
*pp = region->next_peer;
if (replace)
pp_start = &replace->inner;
else
pp_start = &cfun->eh->region_tree;
inner = region->inner;
if (inner)
{
for (p = inner; p->next_peer ; p = p->next_peer)
p->outer = outer;
p->outer = outer;
p->outer = replace;
p->outer = replace;
p->next_peer = *pp_start;
*pp_start = inner;
@ -2442,6 +2521,15 @@ remove_eh_handler (struct eh_region *region)
}
}
/* Splice REGION from the region tree and replace it by the outer region
etc. */
static void
remove_eh_handler (struct eh_region *region)
{
remove_eh_handler_and_replace (region, region->outer);
}
/* LABEL heads a basic block that is about to be deleted. If this
label corresponds to an exception region, we may be able to
delete the region. */