mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-20 19:10:13 +08:00
basic-block.h (flow_delete_block_noexpunge): Declare.
* basic-block.h (flow_delete_block_noexpunge): Declare. (expunge_block_nocompact): Declare. * cfg.c (expunge_block_nocompact): Split out from ... (expunge_block): ... here. * cfgrtl.c (can_delete_label_p): Don't use exception_handler_labels. (flow_delete_block_noexpunge): Split out from ... (flow_delete_block): ... here. * cfgcleanup.c (delete_unreachable_blocks): Compact while removing dead blocks. * except.c (exception_handler_labels): Remove. (exception_handler_label_map): New. (struct eh_region): Add aka member. (mark_ehl_map_entry, mark_ehl_map, free_region): New. (ehl_hash, ehl_eq, ehl_free, add_ehl_entry): New. (for_each_eh_label, for_each_eh_label_1): New. (init_eh): Register exception_handler_label_map. (free_eh_status): Use free_region. (find_exception_handler_labels): Use the map, not the list. (remove_exception_handler_label): Likewise. (maybe_remove_eh_handler): Likewise. (remove_eh_handler): Use the region aka bitmap. * except.h (exception_handler_labels): Remove. (for_each_eh_label): Declare. * jump.c (rebuild_jump_labels): Don't check exception_handler_labels. * loop.c (invalidate_loops_containing_label): New. (find_and_verify_loops): Use it. Use for_each_eh_label. * sched-rgn.c (is_cfg_nonregular): Use current_function_has_exception_handlers. From-SVN: r52100
This commit is contained in:
parent
4fc4e47839
commit
6a58eee93d
@ -1,3 +1,34 @@
|
||||
2002-04-09 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* basic-block.h (flow_delete_block_noexpunge): Declare.
|
||||
(expunge_block_nocompact): Declare.
|
||||
* cfg.c (expunge_block_nocompact): Split out from ...
|
||||
(expunge_block): ... here.
|
||||
* cfgrtl.c (can_delete_label_p): Don't use exception_handler_labels.
|
||||
(flow_delete_block_noexpunge): Split out from ...
|
||||
(flow_delete_block): ... here.
|
||||
* cfgcleanup.c (delete_unreachable_blocks): Compact while
|
||||
removing dead blocks.
|
||||
* except.c (exception_handler_labels): Remove.
|
||||
(exception_handler_label_map): New.
|
||||
(struct eh_region): Add aka member.
|
||||
(mark_ehl_map_entry, mark_ehl_map, free_region): New.
|
||||
(ehl_hash, ehl_eq, ehl_free, add_ehl_entry): New.
|
||||
(for_each_eh_label, for_each_eh_label_1): New.
|
||||
(init_eh): Register exception_handler_label_map.
|
||||
(free_eh_status): Use free_region.
|
||||
(find_exception_handler_labels): Use the map, not the list.
|
||||
(remove_exception_handler_label): Likewise.
|
||||
(maybe_remove_eh_handler): Likewise.
|
||||
(remove_eh_handler): Use the region aka bitmap.
|
||||
* except.h (exception_handler_labels): Remove.
|
||||
(for_each_eh_label): Declare.
|
||||
* jump.c (rebuild_jump_labels): Don't check exception_handler_labels.
|
||||
* loop.c (invalidate_loops_containing_label): New.
|
||||
(find_and_verify_loops): Use it. Use for_each_eh_label.
|
||||
* sched-rgn.c (is_cfg_nonregular): Use
|
||||
current_function_has_exception_handlers.
|
||||
|
||||
2002-04-09 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* sbitmap.c (sbitmap_union_of_diff, sbitmap_a_and_b, sbitmap_a_xor_b,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Define control and data flow tables, and regsets.
|
||||
Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001
|
||||
Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001, 2002
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -316,6 +316,7 @@ extern void redirect_edge_pred PARAMS ((edge, basic_block));
|
||||
extern basic_block create_basic_block_structure PARAMS ((int, rtx, rtx, rtx));
|
||||
extern basic_block create_basic_block PARAMS ((int, rtx, rtx));
|
||||
extern int flow_delete_block PARAMS ((basic_block));
|
||||
extern int flow_delete_block_noexpunge PARAMS ((basic_block));
|
||||
extern void clear_bb_flags PARAMS ((void));
|
||||
extern void merge_blocks_nomove PARAMS ((basic_block, basic_block));
|
||||
extern void tidy_fallthru_edge PARAMS ((edge, basic_block,
|
||||
@ -637,6 +638,7 @@ extern void debug_regset PARAMS ((regset));
|
||||
extern void allocate_reg_life_data PARAMS ((void));
|
||||
extern void allocate_bb_life_data PARAMS ((void));
|
||||
extern void expunge_block PARAMS ((basic_block));
|
||||
extern void expunge_block_nocompact PARAMS ((basic_block));
|
||||
extern basic_block alloc_block PARAMS ((void));
|
||||
extern void find_unreachable_blocks PARAMS ((void));
|
||||
extern int delete_noop_moves PARAMS ((rtx));
|
||||
|
20
gcc/cfg.c
20
gcc/cfg.c
@ -222,6 +222,17 @@ alloc_block ()
|
||||
|
||||
/* Remove block B from the basic block array and compact behind it. */
|
||||
|
||||
void
|
||||
expunge_block_nocompact (b)
|
||||
basic_block b;
|
||||
{
|
||||
/* Invalidate data to make bughunting easier. */
|
||||
memset (b, 0, sizeof *b);
|
||||
b->index = -3;
|
||||
b->succ = (edge) first_deleted_block;
|
||||
first_deleted_block = (basic_block) b;
|
||||
}
|
||||
|
||||
void
|
||||
expunge_block (b)
|
||||
basic_block b;
|
||||
@ -235,13 +246,10 @@ expunge_block (b)
|
||||
x->index = i;
|
||||
}
|
||||
|
||||
/* Invalidate data to make bughunting easier. */
|
||||
memset (b, 0, sizeof *b);
|
||||
b->index = -3;
|
||||
basic_block_info->num_elements--;
|
||||
n_basic_blocks--;
|
||||
b->succ = (edge) first_deleted_block;
|
||||
first_deleted_block = (basic_block) b;
|
||||
basic_block_info->num_elements--;
|
||||
|
||||
expunge_block_nocompact (b);
|
||||
}
|
||||
|
||||
/* Create an edge connecting SRC and DST with FLAGS optionally using
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Control flow optimization code for GNU compiler.
|
||||
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -1751,22 +1751,33 @@ try_optimize_cfg (mode)
|
||||
static bool
|
||||
delete_unreachable_blocks ()
|
||||
{
|
||||
int i;
|
||||
int i, j;
|
||||
bool changed = false;
|
||||
|
||||
find_unreachable_blocks ();
|
||||
|
||||
/* Delete all unreachable basic blocks. Count down so that we
|
||||
don't interfere with the block renumbering that happens in
|
||||
flow_delete_block. */
|
||||
/* Delete all unreachable basic blocks. Do compaction concurrently,
|
||||
as otherwise we can wind up with O(N^2) behaviour here when we
|
||||
have oodles of dead code. */
|
||||
|
||||
for (i = n_basic_blocks - 1; i >= 0; --i)
|
||||
for (i = j = 0; i < n_basic_blocks; ++i)
|
||||
{
|
||||
basic_block b = BASIC_BLOCK (i);
|
||||
|
||||
if (!(b->flags & BB_REACHABLE))
|
||||
flow_delete_block (b), changed = true;
|
||||
{
|
||||
flow_delete_block_noexpunge (b);
|
||||
expunge_block_nocompact (b);
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
BASIC_BLOCK (j) = b;
|
||||
b->index = j++;
|
||||
}
|
||||
}
|
||||
n_basic_blocks = j;
|
||||
basic_block_info->num_elements = j;
|
||||
|
||||
if (changed)
|
||||
tidy_fallthru_edges ();
|
||||
|
16
gcc/cfgrtl.c
16
gcc/cfgrtl.c
@ -1,6 +1,6 @@
|
||||
/* Control flow graph manipulation code for GNU compiler.
|
||||
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -102,8 +102,7 @@ can_delete_label_p (label)
|
||||
/* User declared labels must be preserved. */
|
||||
&& LABEL_NAME (label) == 0
|
||||
&& !in_expr_list_p (forced_labels, label)
|
||||
&& !in_expr_list_p (label_value_list, label)
|
||||
&& !in_expr_list_p (exception_handler_labels, label));
|
||||
&& !in_expr_list_p (label_value_list, label));
|
||||
}
|
||||
|
||||
/* Delete INSN by patching it out. Return the next insn. */
|
||||
@ -363,7 +362,7 @@ create_basic_block (index, head, end)
|
||||
to post-process the stream to remove empty blocks, loops, ranges, etc. */
|
||||
|
||||
int
|
||||
flow_delete_block (b)
|
||||
flow_delete_block_noexpunge (b)
|
||||
basic_block b;
|
||||
{
|
||||
int deleted_handler = 0;
|
||||
@ -412,6 +411,15 @@ flow_delete_block (b)
|
||||
b->pred = NULL;
|
||||
b->succ = NULL;
|
||||
|
||||
return deleted_handler;
|
||||
}
|
||||
|
||||
int
|
||||
flow_delete_block (b)
|
||||
basic_block b;
|
||||
{
|
||||
int deleted_handler = flow_delete_block_noexpunge (b);
|
||||
|
||||
/* Remove the basic block from the array, and compact behind it. */
|
||||
expunge_block (b);
|
||||
|
||||
|
248
gcc/except.c
248
gcc/except.c
@ -98,8 +98,15 @@ int (*lang_eh_type_covers) PARAMS ((tree a, tree b));
|
||||
/* Map a type to a runtime object to match type. */
|
||||
tree (*lang_eh_runtime_type) PARAMS ((tree));
|
||||
|
||||
/* A list of labels used for exception handlers. */
|
||||
rtx exception_handler_labels;
|
||||
/* A hash table of label to region number. */
|
||||
|
||||
struct ehl_map_entry
|
||||
{
|
||||
rtx label;
|
||||
struct eh_region *region;
|
||||
};
|
||||
|
||||
static htab_t exception_handler_label_map;
|
||||
|
||||
static int call_site_base;
|
||||
static unsigned int sjlj_funcdef_number;
|
||||
@ -126,6 +133,10 @@ struct eh_region
|
||||
/* An identifier for this region. */
|
||||
int region_number;
|
||||
|
||||
/* When a region is deleted, its parents inherit the REG_EH_REGION
|
||||
numbers already assigned. */
|
||||
bitmap aka;
|
||||
|
||||
/* Each region does exactly one thing. */
|
||||
enum eh_region_type
|
||||
{
|
||||
@ -242,6 +253,10 @@ struct eh_status
|
||||
|
||||
|
||||
static void mark_eh_region PARAMS ((struct eh_region *));
|
||||
static int mark_ehl_map_entry PARAMS ((PTR *, PTR));
|
||||
static void mark_ehl_map PARAMS ((void *));
|
||||
|
||||
static void free_region PARAMS ((struct eh_region *));
|
||||
|
||||
static int t2r_eq PARAMS ((const PTR,
|
||||
const PTR));
|
||||
@ -292,8 +307,15 @@ static void sjlj_emit_dispatch_table
|
||||
PARAMS ((rtx, struct sjlj_lp_info *));
|
||||
static void sjlj_build_landing_pads PARAMS ((void));
|
||||
|
||||
static hashval_t ehl_hash PARAMS ((const PTR));
|
||||
static int ehl_eq PARAMS ((const PTR,
|
||||
const PTR));
|
||||
static void ehl_free PARAMS ((PTR));
|
||||
static void add_ehl_entry PARAMS ((rtx,
|
||||
struct eh_region *));
|
||||
static void remove_exception_handler_label PARAMS ((rtx));
|
||||
static void remove_eh_handler PARAMS ((struct eh_region *));
|
||||
static int for_each_eh_label_1 PARAMS ((PTR *, PTR));
|
||||
|
||||
struct reachable_info;
|
||||
|
||||
@ -364,7 +386,7 @@ doing_eh (do_warn)
|
||||
void
|
||||
init_eh ()
|
||||
{
|
||||
ggc_add_rtx_root (&exception_handler_labels, 1);
|
||||
ggc_add_root (&exception_handler_label_map, 1, 1, mark_ehl_map);
|
||||
|
||||
if (! flag_exceptions)
|
||||
return;
|
||||
@ -511,6 +533,25 @@ mark_eh_region (region)
|
||||
ggc_mark_rtx (region->post_landing_pad);
|
||||
}
|
||||
|
||||
static int
|
||||
mark_ehl_map_entry (pentry, data)
|
||||
PTR *pentry;
|
||||
PTR data ATTRIBUTE_UNUSED;
|
||||
{
|
||||
struct ehl_map_entry *entry = *(struct ehl_map_entry **) pentry;
|
||||
ggc_mark_rtx (entry->label);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
mark_ehl_map (pp)
|
||||
void *pp;
|
||||
{
|
||||
htab_t map = *(htab_t *) pp;
|
||||
if (map)
|
||||
htab_traverse (map, mark_ehl_map_entry, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
mark_eh_status (eh)
|
||||
struct eh_status *eh;
|
||||
@ -572,6 +613,16 @@ mark_eh_status (eh)
|
||||
ggc_mark_rtx (eh->sjlj_exit_after);
|
||||
}
|
||||
|
||||
static inline void
|
||||
free_region (r)
|
||||
struct eh_region *r;
|
||||
{
|
||||
/* Note that the aka bitmap is freed by regset_release_memory. But if
|
||||
we ever replace with a non-obstack implementation, this would be
|
||||
the place to do it. */
|
||||
free (r);
|
||||
}
|
||||
|
||||
void
|
||||
free_eh_status (f)
|
||||
struct function *f;
|
||||
@ -586,7 +637,7 @@ free_eh_status (f)
|
||||
struct eh_region *r = eh->region_array[i];
|
||||
/* Mind we don't free a region struct more than once. */
|
||||
if (r && r->region_number == i)
|
||||
free (r);
|
||||
free_region (r);
|
||||
}
|
||||
free (eh->region_array);
|
||||
}
|
||||
@ -600,20 +651,20 @@ free_eh_status (f)
|
||||
else if (r->next_peer)
|
||||
{
|
||||
next = r->next_peer;
|
||||
free (r);
|
||||
free_region (r);
|
||||
r = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
do {
|
||||
next = r->outer;
|
||||
free (r);
|
||||
free_region (r);
|
||||
r = next;
|
||||
if (r == NULL)
|
||||
goto tree_done;
|
||||
} while (r->next_peer == NULL);
|
||||
next = r->next_peer;
|
||||
free (r);
|
||||
free_region (r);
|
||||
r = next;
|
||||
}
|
||||
}
|
||||
@ -628,7 +679,12 @@ free_eh_status (f)
|
||||
|
||||
free (eh);
|
||||
f->eh = NULL;
|
||||
exception_handler_labels = NULL;
|
||||
|
||||
if (exception_handler_label_map)
|
||||
{
|
||||
htab_delete (exception_handler_label_map);
|
||||
exception_handler_label_map = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1312,13 +1368,50 @@ convert_from_eh_region_ranges ()
|
||||
remove_unreachable_regions (insns);
|
||||
}
|
||||
|
||||
static void
|
||||
add_ehl_entry (label, region)
|
||||
rtx label;
|
||||
struct eh_region *region;
|
||||
{
|
||||
struct ehl_map_entry **slot, *entry;
|
||||
|
||||
LABEL_PRESERVE_P (label) = 1;
|
||||
|
||||
entry = (struct ehl_map_entry *) xmalloc (sizeof (*entry));
|
||||
entry->label = label;
|
||||
entry->region = region;
|
||||
|
||||
slot = (struct ehl_map_entry **)
|
||||
htab_find_slot (exception_handler_label_map, entry, INSERT);
|
||||
if (*slot)
|
||||
abort ();
|
||||
*slot = entry;
|
||||
}
|
||||
|
||||
static void
|
||||
ehl_free (pentry)
|
||||
PTR pentry;
|
||||
{
|
||||
struct ehl_map_entry *entry = (struct ehl_map_entry *)pentry;
|
||||
LABEL_PRESERVE_P (entry->label) = 0;
|
||||
free (entry);
|
||||
}
|
||||
|
||||
void
|
||||
find_exception_handler_labels ()
|
||||
{
|
||||
rtx list = NULL_RTX;
|
||||
int i;
|
||||
|
||||
free_EXPR_LIST_list (&exception_handler_labels);
|
||||
if (exception_handler_label_map)
|
||||
htab_empty (exception_handler_label_map);
|
||||
else
|
||||
{
|
||||
/* ??? The expansion factor here (3/2) must be greater than the htab
|
||||
occupancy factor (4/3) to avoid unnecessary resizing. */
|
||||
exception_handler_label_map
|
||||
= htab_create (cfun->eh->last_region_number * 3 / 2,
|
||||
ehl_hash, ehl_eq, ehl_free);
|
||||
}
|
||||
|
||||
if (cfun->eh->region_tree == NULL)
|
||||
return;
|
||||
@ -1336,15 +1429,13 @@ find_exception_handler_labels ()
|
||||
lab = region->label;
|
||||
|
||||
if (lab)
|
||||
list = alloc_EXPR_LIST (0, lab, list);
|
||||
add_ehl_entry (lab, region);
|
||||
}
|
||||
|
||||
/* For sjlj exceptions, need the return label to remain live until
|
||||
after landing pad generation. */
|
||||
if (USING_SJLJ_EXCEPTIONS && ! cfun->eh->built_landing_pads)
|
||||
list = alloc_EXPR_LIST (0, return_label, list);
|
||||
|
||||
exception_handler_labels = list;
|
||||
add_ehl_entry (return_label, NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2430,28 +2521,50 @@ finish_eh_generation ()
|
||||
cleanup_cfg (CLEANUP_PRE_LOOP);
|
||||
}
|
||||
|
||||
static hashval_t
|
||||
ehl_hash (pentry)
|
||||
const PTR pentry;
|
||||
{
|
||||
struct ehl_map_entry *entry = (struct ehl_map_entry *) pentry;
|
||||
|
||||
/* 2^32 * ((sqrt(5) - 1) / 2) */
|
||||
const hashval_t scaled_golden_ratio = 0x9e3779b9;
|
||||
return CODE_LABEL_NUMBER (entry->label) * scaled_golden_ratio;
|
||||
}
|
||||
|
||||
static int
|
||||
ehl_eq (pentry, pdata)
|
||||
const PTR pentry;
|
||||
const PTR pdata;
|
||||
{
|
||||
struct ehl_map_entry *entry = (struct ehl_map_entry *) pentry;
|
||||
struct ehl_map_entry *data = (struct ehl_map_entry *) pdata;
|
||||
|
||||
return entry->label == data->label;
|
||||
}
|
||||
|
||||
/* This section handles removing dead code for flow. */
|
||||
|
||||
/* Remove LABEL from the exception_handler_labels list. */
|
||||
/* Remove LABEL from exception_handler_label_map. */
|
||||
|
||||
static void
|
||||
remove_exception_handler_label (label)
|
||||
rtx label;
|
||||
{
|
||||
rtx *pl, l;
|
||||
struct ehl_map_entry **slot, tmp;
|
||||
|
||||
/* If exception_handler_labels was not built yet,
|
||||
/* If exception_handler_label_map was not built yet,
|
||||
there is nothing to do. */
|
||||
if (exception_handler_labels == NULL)
|
||||
if (exception_handler_label_map == NULL)
|
||||
return;
|
||||
|
||||
for (pl = &exception_handler_labels, l = *pl;
|
||||
XEXP (l, 0) != label;
|
||||
pl = &XEXP (l, 1), l = *pl)
|
||||
continue;
|
||||
tmp.label = label;
|
||||
slot = (struct ehl_map_entry **)
|
||||
htab_find_slot (exception_handler_label_map, &tmp, NO_INSERT);
|
||||
if (! slot)
|
||||
abort ();
|
||||
|
||||
*pl = XEXP (l, 1);
|
||||
free_EXPR_LIST_node (l);
|
||||
htab_clear_slot (exception_handler_label_map, (void **) slot);
|
||||
}
|
||||
|
||||
/* Splice REGION from the region tree etc. */
|
||||
@ -2462,16 +2575,29 @@ remove_eh_handler (region)
|
||||
{
|
||||
struct eh_region **pp, *p;
|
||||
rtx lab;
|
||||
int i;
|
||||
|
||||
/* 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 to
|
||||
search the whole thing. */
|
||||
for (i = cfun->eh->last_region_number; i > 0; --i)
|
||||
if (cfun->eh->region_array[i] == region)
|
||||
cfun->eh->region_array[i] = region->outer;
|
||||
multiple copies of this region in the array, so we have a
|
||||
list of alternate numbers by which we are known. */
|
||||
|
||||
cfun->eh->region_array[region->region_number] = region->outer;
|
||||
if (region->aka)
|
||||
{
|
||||
int i;
|
||||
EXECUTE_IF_SET_IN_BITMAP (region->aka, 0, i,
|
||||
{ cfun->eh->region_array[i] = region->outer; });
|
||||
}
|
||||
|
||||
if (region->outer)
|
||||
{
|
||||
if (!region->outer->aka)
|
||||
region->outer->aka = BITMAP_XMALLOC ();
|
||||
if (region->aka)
|
||||
bitmap_a_or_b (region->outer->aka, region->outer->aka, region->aka);
|
||||
bitmap_set_bit (region->outer->aka, region->region_number);
|
||||
}
|
||||
|
||||
if (cfun->eh->built_landing_pads)
|
||||
lab = region->landing_pad;
|
||||
@ -2526,7 +2652,7 @@ remove_eh_handler (region)
|
||||
}
|
||||
}
|
||||
|
||||
free (region);
|
||||
free_region (region);
|
||||
}
|
||||
|
||||
/* LABEL heads a basic block that is about to be deleted. If this
|
||||
@ -2537,7 +2663,8 @@ void
|
||||
maybe_remove_eh_handler (label)
|
||||
rtx label;
|
||||
{
|
||||
int i;
|
||||
struct ehl_map_entry **slot, tmp;
|
||||
struct eh_region *region;
|
||||
|
||||
/* ??? After generating landing pads, it's not so simple to determine
|
||||
if the region data is completely unused. One must examine the
|
||||
@ -2546,27 +2673,50 @@ maybe_remove_eh_handler (label)
|
||||
if (cfun->eh->built_landing_pads)
|
||||
return;
|
||||
|
||||
for (i = cfun->eh->last_region_number; i > 0; --i)
|
||||
tmp.label = label;
|
||||
slot = (struct ehl_map_entry **)
|
||||
htab_find_slot (exception_handler_label_map, &tmp, NO_INSERT);
|
||||
if (! slot)
|
||||
return;
|
||||
region = (*slot)->region;
|
||||
if (! region)
|
||||
return;
|
||||
|
||||
/* Flow will want to remove MUST_NOT_THROW regions as unreachable
|
||||
because there is no path to the fallback call to terminate.
|
||||
But the region continues to affect call-site data until there
|
||||
are no more contained calls, which we don't see here. */
|
||||
if (region->type == ERT_MUST_NOT_THROW)
|
||||
{
|
||||
struct eh_region *region = cfun->eh->region_array[i];
|
||||
if (region && region->label == label)
|
||||
{
|
||||
/* Flow will want to remove MUST_NOT_THROW regions as unreachable
|
||||
because there is no path to the fallback call to terminate.
|
||||
But the region continues to affect call-site data until there
|
||||
are no more contained calls, which we don't see here. */
|
||||
if (region->type == ERT_MUST_NOT_THROW)
|
||||
{
|
||||
remove_exception_handler_label (region->label);
|
||||
region->label = NULL_RTX;
|
||||
}
|
||||
else
|
||||
remove_eh_handler (region);
|
||||
break;
|
||||
}
|
||||
htab_clear_slot (exception_handler_label_map, (void **) slot);
|
||||
region->label = NULL_RTX;
|
||||
}
|
||||
else
|
||||
remove_eh_handler (region);
|
||||
}
|
||||
|
||||
/* Invokes CALLBACK for every exception handler label. Only used by old
|
||||
loop hackery; should not be used by new code. */
|
||||
|
||||
void
|
||||
for_each_eh_label (callback)
|
||||
void (*callback) PARAMS ((rtx));
|
||||
{
|
||||
htab_traverse (exception_handler_label_map, for_each_eh_label_1,
|
||||
(void *)callback);
|
||||
}
|
||||
|
||||
static int
|
||||
for_each_eh_label_1 (pentry, data)
|
||||
PTR *pentry;
|
||||
PTR data;
|
||||
{
|
||||
struct ehl_map_entry *entry = *(struct ehl_map_entry **)pentry;
|
||||
void (*callback) PARAMS ((rtx)) = (void (*) PARAMS ((rtx))) data;
|
||||
|
||||
(*callback) (entry->label);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This section describes CFG exception edges for flow. */
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Exception Handling interface routines.
|
||||
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
|
||||
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Mike Stump <mrs@cygnus.com>.
|
||||
|
||||
@ -83,8 +83,9 @@ extern void expand_eh_region_end_throw PARAMS ((tree));
|
||||
destroying an object twice. */
|
||||
extern void expand_eh_region_end_fixup PARAMS ((tree));
|
||||
|
||||
/* A list of labels used for exception handlers. */
|
||||
extern rtx exception_handler_labels;
|
||||
/* Invokes CALLBACK for every exception handler label. Only used by old
|
||||
loop hackery; should not be used by new code. */
|
||||
extern void for_each_eh_label PARAMS ((void (*) (rtx)));
|
||||
|
||||
/* Determine if the given INSN can throw an exception. */
|
||||
extern bool can_throw_internal PARAMS ((rtx));
|
||||
|
@ -91,13 +91,6 @@ rebuild_jump_labels (f)
|
||||
for (insn = forced_labels; insn; insn = XEXP (insn, 1))
|
||||
if (GET_CODE (XEXP (insn, 0)) == CODE_LABEL)
|
||||
LABEL_NUSES (XEXP (insn, 0))++;
|
||||
|
||||
/* Keep track of labels used for marking handlers for exception
|
||||
regions; they cannot usually be deleted. */
|
||||
|
||||
for (insn = exception_handler_labels; insn; insn = XEXP (insn, 1))
|
||||
if (GET_CODE (XEXP (insn, 0)) == CODE_LABEL)
|
||||
LABEL_NUSES (XEXP (insn, 0))++;
|
||||
}
|
||||
|
||||
/* Some old code expects exactly one BARRIER as the NEXT_INSN of a
|
||||
|
33
gcc/loop.c
33
gcc/loop.c
@ -235,6 +235,7 @@ FILE *loop_dump_stream;
|
||||
|
||||
/* Forward declarations. */
|
||||
|
||||
static void invalidate_loops_containing_label PARAMS ((rtx));
|
||||
static void find_and_verify_loops PARAMS ((rtx, struct loops *));
|
||||
static void mark_loop_jump PARAMS ((rtx, struct loop *));
|
||||
static void prescan_loop PARAMS ((struct loop *));
|
||||
@ -2609,6 +2610,17 @@ prescan_loop (loop)
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalidate all loops containing LABEL. */
|
||||
|
||||
static void
|
||||
invalidate_loops_containing_label (label)
|
||||
rtx label;
|
||||
{
|
||||
struct loop *loop;
|
||||
for (loop = uid_loop[INSN_UID (label)]; loop; loop = loop->outer)
|
||||
loop->invalid = 1;
|
||||
}
|
||||
|
||||
/* Scan the function looking for loops. Record the start and end of each loop.
|
||||
Also mark as invalid loops any loops that contain a setjmp or are branched
|
||||
to from outside the loop. */
|
||||
@ -2695,23 +2707,12 @@ find_and_verify_loops (f, loops)
|
||||
|
||||
/* Any loop containing a label used in an initializer must be invalidated,
|
||||
because it can be jumped into from anywhere. */
|
||||
|
||||
for (label = forced_labels; label; label = XEXP (label, 1))
|
||||
{
|
||||
for (loop = uid_loop[INSN_UID (XEXP (label, 0))];
|
||||
loop; loop = loop->outer)
|
||||
loop->invalid = 1;
|
||||
}
|
||||
invalidate_loops_containing_label (XEXP (label, 0));
|
||||
|
||||
/* Any loop containing a label used for an exception handler must be
|
||||
invalidated, because it can be jumped into from anywhere. */
|
||||
|
||||
for (label = exception_handler_labels; label; label = XEXP (label, 1))
|
||||
{
|
||||
for (loop = uid_loop[INSN_UID (XEXP (label, 0))];
|
||||
loop; loop = loop->outer)
|
||||
loop->invalid = 1;
|
||||
}
|
||||
for_each_eh_label (invalidate_loops_containing_label);
|
||||
|
||||
/* Now scan all insn's in the function. If any JUMP_INSN branches into a
|
||||
loop that it is not contained within, that loop is marked invalid.
|
||||
@ -2735,11 +2736,7 @@ find_and_verify_loops (f, loops)
|
||||
{
|
||||
rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX);
|
||||
if (note)
|
||||
{
|
||||
for (loop = uid_loop[INSN_UID (XEXP (note, 0))];
|
||||
loop; loop = loop->outer)
|
||||
loop->invalid = 1;
|
||||
}
|
||||
invalidate_loops_containing_label (XEXP (note, 0));
|
||||
}
|
||||
|
||||
if (GET_CODE (insn) != JUMP_INSN)
|
||||
|
@ -339,7 +339,7 @@ is_cfg_nonregular ()
|
||||
/* If we have exception handlers, then we consider the cfg not well
|
||||
structured. ?!? We should be able to handle this now that flow.c
|
||||
computes an accurate cfg for EH. */
|
||||
if (exception_handler_labels)
|
||||
if (current_function_has_exception_handlers ())
|
||||
return 1;
|
||||
|
||||
/* If we have non-jumping insns which refer to labels, then we consider
|
||||
|
Loading…
Reference in New Issue
Block a user