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
This commit is contained in:
Jan Hubicka 2009-04-25 20:27:19 +02:00 committed by Jan Hubicka
parent 3764d512d5
commit a3710436b6
13 changed files with 594 additions and 18 deletions

View file

@ -1,3 +1,36 @@
2009-04-25 Jan Hubicka <jh@suse.cz>
* 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.
2009-04-25 Eric Botcazou <ebotcazou@adacore.com>
PR bootstrap/39645

View file

@ -2525,7 +2525,7 @@ except.o : except.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
langhooks.h insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
dwarf2asm.h dwarf2out.h $(TOPLEV_H) $(HASHTAB_H) intl.h $(GGC_H) \
gt-$(EXCEPT_H) $(CGRAPH_H) $(INTEGRATE_H) $(DIAGNOSTIC_H) dwarf2.h \
$(TARGET_H) $(TM_P_H) $(TREE_PASS_H) $(TIMEVAR_H)
$(TARGET_H) $(TM_P_H) $(TREE_PASS_H) $(TIMEVAR_H) $(TREE_FLOW_H)
expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) $(EXPR_H) $(OPTABS_H) \
libfuncs.h $(INSN_ATTR_H) insn-config.h $(RECOG_H) output.h \

View file

@ -147,8 +147,6 @@ struct GTY(()) edge_def {
in profile.c */
};
typedef struct edge_def *edge;
typedef const struct edge_def *const_edge;
DEF_VEC_P(edge);
DEF_VEC_ALLOC_P(edge,gc);
DEF_VEC_ALLOC_P(edge,heap);
@ -277,9 +275,6 @@ struct GTY(()) gimple_bb_info {
gimple_seq phi_nodes;
};
typedef struct basic_block_def *basic_block;
typedef const struct basic_block_def *const_basic_block;
DEF_VEC_P(basic_block);
DEF_VEC_ALLOC_P(basic_block,gc);
DEF_VEC_ALLOC_P(basic_block,heap);

View file

@ -97,6 +97,12 @@ enum tls_model {
TLS_MODEL_LOCAL_EXEC
};
struct edge_def;
typedef struct edge_def *edge;
typedef const struct edge_def *const_edge;
struct basic_block_def;
typedef struct basic_block_def *basic_block;
typedef const struct basic_block_def *const_basic_block;
#else
struct _dont_use_rtx_here_;

View file

@ -77,6 +77,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "tree-pass.h"
#include "timevar.h"
#include "tree-flow.h"
/* Provide defaults for stuff that may not be defined when using
sjlj exceptions. */
@ -628,6 +629,238 @@ bring_to_root (struct eh_region *r)
cfun->eh->region_tree = r;
}
/* Return true if region R2 can be replaced by R1. */
static bool
eh_region_replaceable_by_p (const struct eh_region *r1,
const struct eh_region *r2)
{
/* Regions are semantically same if they are of same type,
have same label and type. */
if (r1->type != r2->type)
return false;
if (r1->tree_label != r2->tree_label)
return false;
/* Verify that also region type dependent data are the same. */
switch (r1->type)
{
case ERT_MUST_NOT_THROW:
case ERT_CLEANUP:
break;
case ERT_TRY:
{
struct eh_region *c1, *c2;
for (c1 = r1->u.eh_try.eh_catch,
c2 = r2->u.eh_try.eh_catch;
c1 && c2;
c1 = c1->u.eh_catch.next_catch,
c2 = c2->u.eh_catch.next_catch)
if (!eh_region_replaceable_by_p (c1, c2))
return false;
if (c1 || c2)
return false;
}
break;
case ERT_CATCH:
if (!list_equal_p (r1->u.eh_catch.type_list, r2->u.eh_catch.type_list))
return false;
if (!list_equal_p (r1->u.eh_catch.filter_list,
r2->u.eh_catch.filter_list))
return false;
break;
case ERT_ALLOWED_EXCEPTIONS:
if (!list_equal_p (r1->u.allowed.type_list, r2->u.allowed.type_list))
return false;
if (r1->u.allowed.filter != r2->u.allowed.filter)
return false;
break;
case ERT_THROW:
if (r1->u.eh_throw.type != r2->u.eh_throw.type)
return false;
break;
default:
gcc_unreachable ();
}
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Regions %i and %i match\n", r1->region_number,
r2->region_number);
return true;
}
/* Replace region R2 by R1. */
static void
replace_region (struct eh_region *r1, struct eh_region *r2)
{
struct eh_region *next1 = r1->u.eh_try.eh_catch;
struct eh_region *next2 = r2->u.eh_try.eh_catch;
bool is_try = r1->type == ERT_TRY;
gcc_assert (r1->type != ERT_CATCH);
remove_eh_handler_and_replace (r2, r1, false);
if (is_try)
{
while (next1)
{
r1 = next1;
r2 = next2;
gcc_assert (next1->type == ERT_CATCH);
gcc_assert (next2->type == ERT_CATCH);
next1 = next1->u.eh_catch.next_catch;
next2 = next2->u.eh_catch.next_catch;
remove_eh_handler_and_replace (r2, r1, false);
}
}
}
/* Return hash value of type list T. */
static hashval_t
hash_type_list (tree t)
{
hashval_t val = 0;
for (; t; t = TREE_CHAIN (t))
val = iterative_hash_hashval_t (TREE_HASH (TREE_VALUE (t)), val);
return val;
}
/* Hash EH regions so semantically same regions get same hash value. */
static hashval_t
hash_eh_region (const void *r)
{
const struct eh_region *region = (const struct eh_region *)r;
hashval_t val = region->type;
if (region->tree_label)
val = iterative_hash_hashval_t (LABEL_DECL_UID (region->tree_label), val);
switch (region->type)
{
case ERT_MUST_NOT_THROW:
case ERT_CLEANUP:
break;
case ERT_TRY:
{
struct eh_region *c;
for (c = region->u.eh_try.eh_catch;
c; c = c->u.eh_catch.next_catch)
val = iterative_hash_hashval_t (hash_eh_region (c), val);
}
break;
case ERT_CATCH:
val = iterative_hash_hashval_t (hash_type_list
(region->u.eh_catch.type_list), val);
break;
case ERT_ALLOWED_EXCEPTIONS:
val = iterative_hash_hashval_t
(hash_type_list (region->u.allowed.type_list), val);
val = iterative_hash_hashval_t (region->u.allowed.filter, val);
break;
case ERT_THROW:
val |= iterative_hash_hashval_t (TYPE_UID (region->u.eh_throw.type), val);
break;
default:
gcc_unreachable ();
}
return val;
}
/* Return true if regions R1 and R2 are equal. */
static int
eh_regions_equal_p (const void *r1, const void *r2)
{
return eh_region_replaceable_by_p ((const struct eh_region *)r1,
(const struct eh_region *)r2);
}
/* Walk all peers of REGION and try to merge those regions
that are semantically equivalent. Look into subregions
recursively too. */
static bool
merge_peers (struct eh_region *region)
{
struct eh_region *r1, *r2, *outer = NULL, *next;
bool merged = false;
int num_regions = 0;
if (region)
outer = region->outer;
else
return false;
/* First see if there is inner region equivalent to region
in question. EH control flow is acyclic so we know we
can merge them. */
if (outer)
for (r1 = region; r1; r1 = next)
{
next = r1->next_peer;
if (r1->type == ERT_CATCH)
continue;
if (eh_region_replaceable_by_p (r1->outer, r1))
{
replace_region (r1->outer, r1);
merged = true;
}
else
num_regions ++;
}
/* Get new first region and try to match the peers
for equivalence. */
if (outer)
region = outer->inner;
else
region = cfun->eh->region_tree;
/* There are few regions to inspect:
N^2 loop matching each region with each region
will do the job well. */
if (num_regions < 10)
{
for (r1 = region; r1; r1 = r1->next_peer)
{
if (r1->type == ERT_CATCH)
continue;
for (r2 = r1->next_peer; r2; r2 = next)
{
next = r2->next_peer;
if (eh_region_replaceable_by_p (r1, r2))
{
replace_region (r1, r2);
merged = true;
}
}
}
}
/* Or use hashtable to avoid N^2 behaviour. */
else
{
htab_t hash;
hash = htab_create (num_regions, hash_eh_region,
eh_regions_equal_p, NULL);
for (r1 = region; r1; r1 = next)
{
void **slot;
next = r1->next_peer;
if (r1->type == ERT_CATCH)
continue;
slot = htab_find_slot (hash, r1, INSERT);
if (!*slot)
*slot = r1;
else
replace_region ((struct eh_region *)*slot, r1);
}
htab_delete (hash);
}
for (r1 = region; r1; r1 = r1->next_peer)
merged |= merge_peers (r1->inner);
return merged;
}
/* 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). */
@ -748,6 +981,7 @@ remove_unreachable_regions (sbitmap reachable, sbitmap contains_stmt)
else
bring_to_root (r);
}
merge_peers (cfun->eh->region_tree);
#ifdef ENABLE_CHECKING
verify_eh_tree (cfun);
#endif
@ -1140,6 +1374,238 @@ duplicate_eh_regions (struct function *ifun, duplicate_eh_regions_map map,
return eh_offset;
}
/* Return new copy of eh region OLD inside region NEW_OUTER.
Do not care about updating the tree otherwise. */
static struct eh_region *
copy_eh_region_1 (struct eh_region *old, struct eh_region *new_outer)
{
struct eh_region *new_eh = gen_eh_region (old->type, new_outer);
new_eh->u = old->u;
new_eh->tree_label = old->tree_label;
new_eh->may_contain_throw = old->may_contain_throw;
VEC_safe_grow (eh_region, gc, cfun->eh->region_array,
cfun->eh->last_region_number + 1);
VEC_replace (eh_region, cfun->eh->region_array, new_eh->region_number, new_eh);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Copying region %i to %i\n", old->region_number, new_eh->region_number);
return new_eh;
}
/* Return new copy of eh region OLD inside region NEW_OUTER.
Copy whole catch-try chain if neccesary and update cleanup region prev_try
pointers.
PREV_TRY_MAP points to outer TRY region if it was copied in trace already. */
static struct eh_region *
copy_eh_region (struct eh_region *old, struct eh_region *new_outer,
struct eh_region *prev_try_map)
{
struct eh_region *r, *n, *old_try, *new_try, *ret = NULL;
VEC(eh_region,heap) *catch_list = NULL;
if (old->type != ERT_CATCH)
{
gcc_assert (old->type != ERT_TRY);
r = copy_eh_region_1 (old, new_outer);
if (r->type == ERT_CLEANUP && prev_try_map)
{
gcc_assert (r->u.cleanup.prev_try);
r->u.cleanup.prev_try = prev_try_map;
}
return r;
}
/* Locate and copy corresponding TRY. */
for (old_try = old->next_peer; old_try->type == ERT_CATCH; old_try = old_try->next_peer)
continue;
gcc_assert (old_try->type == ERT_TRY);
new_try = gen_eh_region_try (new_outer);
new_try->tree_label = old_try->tree_label;
new_try->may_contain_throw = old_try->may_contain_throw;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Copying try-catch regions. Try: %i to %i\n",
old_try->region_number, new_try->region_number);
VEC_safe_grow (eh_region, gc, cfun->eh->region_array,
cfun->eh->last_region_number + 1);
VEC_replace (eh_region, cfun->eh->region_array, new_try->region_number, new_try);
/* In order to keep CATCH list in order, we need to copy in reverse order. */
for (r = old_try->u.eh_try.last_catch; r->type == ERT_CATCH; r = r->next_peer)
VEC_safe_push (eh_region, heap, catch_list, r);
while (VEC_length (eh_region, catch_list))
{
r = VEC_pop (eh_region, catch_list);
/* Duplicate CATCH. */
n = gen_eh_region_catch (new_try, r->u.eh_catch.type_list);
n->tree_label = r->tree_label;
n->may_contain_throw = r->may_contain_throw;
VEC_safe_grow (eh_region, gc, cfun->eh->region_array,
cfun->eh->last_region_number + 1);
VEC_replace (eh_region, cfun->eh->region_array, n->region_number, n);
n->tree_label = r->tree_label;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Copying try-catch regions. Catch: %i to %i\n",
r->region_number, n->region_number);
if (r == old)
ret = n;
}
VEC_free (eh_region, heap, catch_list);
gcc_assert (ret);
return ret;
}
/* Callback for forach_reachable_handler that push REGION into single VECtor DATA. */
static void
push_reachable_handler (struct eh_region *region, void *data)
{
VEC(eh_region,heap) **trace = (VEC(eh_region,heap) **) data;
VEC_safe_push (eh_region, heap, *trace, region);
}
/* Redirect EH edge E that to NEW_DEST_LABEL.
IS_RESX, INLINABLE_CALL and REGION_NMUBER match the parameter of
foreach_reachable_handler. */
struct eh_region *
redirect_eh_edge_to_label (edge e, tree new_dest_label, bool is_resx,
bool inlinable_call, int region_number)
{
struct eh_region *outer, *prev_try_map = NULL;
struct eh_region *region;
VEC (eh_region, heap) * trace = NULL;
int i;
int start_here = -1;
basic_block old_bb = e->dest;
struct eh_region *old, *r = NULL;
bool update_inplace = true;
edge_iterator ei;
edge e2;
/* If there is only one EH edge, we don't need to duplicate;
just update labels in the tree. */
FOR_EACH_EDGE (e2, ei, old_bb->preds)
if ((e2->flags & EDGE_EH) && e2 != e)
{
update_inplace = false;
break;
}
region = VEC_index (eh_region, cfun->eh->region_array, region_number);
gcc_assert (region);
foreach_reachable_handler (region_number, is_resx, inlinable_call,
push_reachable_handler, &trace);
if (dump_file && (dump_flags & TDF_DETAILS))
{
dump_eh_tree (dump_file, cfun);
fprintf (dump_file, "Trace: ");
for (i = 0; i < (int) VEC_length (eh_region, trace); i++)
fprintf (dump_file, " %i", VEC_index (eh_region, trace, i)->region_number);
fprintf (dump_file, " inplace: %i\n", update_inplace);
}
if (update_inplace)
{
/* In easy route just walk trace and update all occurences of the label. */
for (i = 0; i < (int) VEC_length (eh_region, trace); i++)
{
r = VEC_index (eh_region, trace, i);
if (r->tree_label && label_to_block (r->tree_label) == old_bb)
{
r->tree_label = new_dest_label;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Updating label for region %i\n",
r->region_number);
}
}
r = region;
}
else
{
/* Now look for outermost handler that reffers to the basic block in question.
We start our duplication there. */
for (i = 0; i < (int) VEC_length (eh_region, trace); i++)
{
r = VEC_index (eh_region, trace, i);
if (r->tree_label && label_to_block (r->tree_label) == old_bb)
start_here = i;
}
outer = VEC_index (eh_region, trace, start_here)->outer;
gcc_assert (start_here >= 0);
/* And now do the dirty job! */
for (i = start_here; i >= 0; i--)
{
old = VEC_index (eh_region, trace, i);
gcc_assert (!outer || old->outer != outer->outer);
/* Copy region and update label. */
r = copy_eh_region (old, outer, prev_try_map);
VEC_replace (eh_region, trace, i, r);
if (r->tree_label && label_to_block (r->tree_label) == old_bb)
{
r->tree_label = new_dest_label;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Updating label for region %i\n",
r->region_number);
}
/* We got into copying CATCH. copy_eh_region already did job
of copying all catch blocks corresponding to the try. Now
we need to update labels in all of them and see trace.
We continue nesting into TRY region corresponding to CATCH:
When duplicating EH tree contaiing subregions of CATCH,
the CATCH region itself is never inserted to trace so we
never get here anyway. */
if (r->type == ERT_CATCH)
{
/* Walk other catch regions we copied and update labels as needed. */
for (r = r->next_peer; r->type == ERT_CATCH; r = r->next_peer)
if (r->tree_label && label_to_block (r->tree_label) == old_bb)
{
r->tree_label = new_dest_label;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Updating label for region %i\n",
r->region_number);
}
gcc_assert (r->type == ERT_TRY);
/* Skip sibling catch regions from the trace.
They are already updated. */
while (i > 0 && VEC_index (eh_region, trace, i - 1)->outer == old->outer)
{
gcc_assert (VEC_index (eh_region, trace, i - 1)->type == ERT_CATCH);
i--;
}
}
/* Cleanup regions points to outer TRY blocks. */
if (r->type == ERT_TRY)
prev_try_map = r;
outer = r;
}
if (is_resx || region->type == ERT_THROW)
r = copy_eh_region (region, outer, prev_try_map);
}
VEC_free (eh_region, heap, trace);
if (dump_file && (dump_flags & TDF_DETAILS))
{
dump_eh_tree (dump_file, cfun);
fprintf (dump_file, "New region: %i\n", r->region_number);
}
return r;
}
/* Return region number of region that is outer to both if REGION_A and
REGION_B in IFUN. */
@ -1478,6 +1944,12 @@ build_post_landing_pads (void)
switch (region->type)
{
case ERT_TRY:
/* It is possible that TRY region is kept alive only because some of
contained catch region still have RESX instruction but they are
reached via their copies. In this case we need to do nothing. */
if (!region->u.eh_try.eh_catch->label)
break;
/* ??? Collect the set of all non-overlapping catch handlers
all the way up the chain until blocked by a cleanup. */
/* ??? Outer try regions can share landing pads with inner
@ -1537,6 +2009,8 @@ build_post_landing_pads (void)
break;
case ERT_ALLOWED_EXCEPTIONS:
if (!region->label)
break;
region->post_landing_pad = gen_label_rtx ();
start_sequence ();
@ -1679,6 +2153,9 @@ dw2_build_landing_pads (void)
&& region->type != ERT_ALLOWED_EXCEPTIONS)
continue;
if (!region->post_landing_pad)
continue;
start_sequence ();
region->landing_pad = gen_label_rtx ();

View file

@ -278,4 +278,5 @@ extern void set_eh_throw_stmt_table (struct function *, struct htab *);
extern void remove_unreachable_regions (sbitmap, sbitmap);
extern VEC(int,heap) * label_to_region_map (void);
extern int num_eh_regions (void);
extern struct eh_region *redirect_eh_edge_to_label (struct edge_def *, tree, bool, bool, int);
extern int get_next_region_sharing_label (int);

View file

@ -1,3 +1,7 @@
2009-04-25 Jan Hubicka <jh@suse.cz>
* g++.dg/tree-ssa/ehcleanup-1.C: Update.
2009-04-25 Janus Weil <janus@gcc.gnu.org>
PR fortran/39688

View file

@ -1,4 +1,4 @@
// { dg-options "-O2 -fdump-tree-ehcleanup1" }
// { dg-options "-O2 -fdump-tree-ehcleanup1-details" }
extern void can_throw ();
class a
{

View file

@ -4800,6 +4800,9 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
if (e->dest == dest)
return NULL;
if (e->flags & EDGE_EH)
return redirect_eh_edge (e, dest);
gsi = gsi_last_bb (bb);
stmt = gsi_end_p (gsi) ? NULL : gsi_stmt (gsi);

View file

@ -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;

View file

@ -32,13 +32,6 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-reference.h"
#include "tree-ssa-alias.h"
/* Forward declare structures for the garbage collector GTY markers. */
#ifndef GCC_BASIC_BLOCK_H
struct edge_def;
typedef struct edge_def *edge;
struct basic_block_def;
typedef struct basic_block_def *basic_block;
#endif
struct static_var_ann_d;
@ -974,5 +967,6 @@ unsigned int execute_fixup_cfg (void);
void swap_tree_operands (gimple, tree *, tree *);
int least_common_multiple (int, int);
edge redirect_eh_edge (edge e, basic_block new_bb);
#endif /* _TREE_FLOW_H */

View file

@ -9320,4 +9320,16 @@ block_ultimate_origin (const_tree block)
}
}
/* Return true if T1 and T2 are equivalent lists. */
bool
list_equal_p (const_tree t1, const_tree t2)
{
for (; t1 && t2; t1 = TREE_CHAIN (t1) , t2 = TREE_CHAIN (t2))
if (TREE_VALUE (t1) != TREE_VALUE (t2))
return false;
return !t1 && !t2;
}
#include "gt-tree.h"

View file

@ -5134,6 +5134,7 @@ struct GTY(()) tree_map_base {
extern int tree_map_base_eq (const void *, const void *);
extern unsigned int tree_map_base_hash (const void *);
extern int tree_map_base_marked_p (const void *);
extern bool list_equal_p (const_tree, const_tree);
/* Map from a tree to another tree. */