Commit 6a58eee9 by Richard Henderson Committed by Richard Henderson

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
parent 4fc4e478
2002-04-09 Richard Henderson <rth@redhat.com> 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, * sbitmap.c (sbitmap_union_of_diff, sbitmap_a_and_b, sbitmap_a_xor_b,
sbitmap_a_or_b, sbitmap_a_or_b_and_c, sbitmap_a_and_b_or_c): sbitmap_a_or_b, sbitmap_a_or_b_and_c, sbitmap_a_and_b_or_c):
Do not return changed status. Do not return changed status.
......
/* Define control and data flow tables, and regsets. /* 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. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -316,6 +316,7 @@ extern void redirect_edge_pred PARAMS ((edge, basic_block)); ...@@ -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_structure PARAMS ((int, rtx, rtx, rtx));
extern basic_block create_basic_block PARAMS ((int, 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 PARAMS ((basic_block));
extern int flow_delete_block_noexpunge PARAMS ((basic_block));
extern void clear_bb_flags PARAMS ((void)); extern void clear_bb_flags PARAMS ((void));
extern void merge_blocks_nomove PARAMS ((basic_block, basic_block)); extern void merge_blocks_nomove PARAMS ((basic_block, basic_block));
extern void tidy_fallthru_edge PARAMS ((edge, basic_block, extern void tidy_fallthru_edge PARAMS ((edge, basic_block,
...@@ -637,6 +638,7 @@ extern void debug_regset PARAMS ((regset)); ...@@ -637,6 +638,7 @@ extern void debug_regset PARAMS ((regset));
extern void allocate_reg_life_data PARAMS ((void)); extern void allocate_reg_life_data PARAMS ((void));
extern void allocate_bb_life_data PARAMS ((void)); extern void allocate_bb_life_data PARAMS ((void));
extern void expunge_block PARAMS ((basic_block)); extern void expunge_block PARAMS ((basic_block));
extern void expunge_block_nocompact PARAMS ((basic_block));
extern basic_block alloc_block PARAMS ((void)); extern basic_block alloc_block PARAMS ((void));
extern void find_unreachable_blocks PARAMS ((void)); extern void find_unreachable_blocks PARAMS ((void));
extern int delete_noop_moves PARAMS ((rtx)); extern int delete_noop_moves PARAMS ((rtx));
......
...@@ -223,6 +223,17 @@ alloc_block () ...@@ -223,6 +223,17 @@ alloc_block ()
/* Remove block B from the basic block array and compact behind it. */ /* Remove block B from the basic block array and compact behind it. */
void 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) expunge_block (b)
basic_block b; basic_block b;
{ {
...@@ -235,13 +246,10 @@ expunge_block (b) ...@@ -235,13 +246,10 @@ expunge_block (b)
x->index = i; 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--; n_basic_blocks--;
b->succ = (edge) first_deleted_block; basic_block_info->num_elements--;
first_deleted_block = (basic_block) b;
expunge_block_nocompact (b);
} }
/* Create an edge connecting SRC and DST with FLAGS optionally using /* Create an edge connecting SRC and DST with FLAGS optionally using
......
/* Control flow optimization code for GNU compiler. /* Control flow optimization code for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 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. This file is part of GCC.
...@@ -1751,22 +1751,33 @@ try_optimize_cfg (mode) ...@@ -1751,22 +1751,33 @@ try_optimize_cfg (mode)
static bool static bool
delete_unreachable_blocks () delete_unreachable_blocks ()
{ {
int i; int i, j;
bool changed = false; bool changed = false;
find_unreachable_blocks (); find_unreachable_blocks ();
/* Delete all unreachable basic blocks. Count down so that we /* Delete all unreachable basic blocks. Do compaction concurrently,
don't interfere with the block renumbering that happens in as otherwise we can wind up with O(N^2) behaviour here when we
flow_delete_block. */ 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); basic_block b = BASIC_BLOCK (i);
if (!(b->flags & BB_REACHABLE)) 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) if (changed)
tidy_fallthru_edges (); tidy_fallthru_edges ();
......
/* Control flow graph manipulation code for GNU compiler. /* Control flow graph manipulation code for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 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. This file is part of GCC.
...@@ -102,8 +102,7 @@ can_delete_label_p (label) ...@@ -102,8 +102,7 @@ can_delete_label_p (label)
/* User declared labels must be preserved. */ /* User declared labels must be preserved. */
&& LABEL_NAME (label) == 0 && LABEL_NAME (label) == 0
&& !in_expr_list_p (forced_labels, label) && !in_expr_list_p (forced_labels, label)
&& !in_expr_list_p (label_value_list, label) && !in_expr_list_p (label_value_list, label));
&& !in_expr_list_p (exception_handler_labels, label));
} }
/* Delete INSN by patching it out. Return the next insn. */ /* Delete INSN by patching it out. Return the next insn. */
...@@ -363,7 +362,7 @@ create_basic_block (index, head, end) ...@@ -363,7 +362,7 @@ create_basic_block (index, head, end)
to post-process the stream to remove empty blocks, loops, ranges, etc. */ to post-process the stream to remove empty blocks, loops, ranges, etc. */
int int
flow_delete_block (b) flow_delete_block_noexpunge (b)
basic_block b; basic_block b;
{ {
int deleted_handler = 0; int deleted_handler = 0;
...@@ -412,6 +411,15 @@ flow_delete_block (b) ...@@ -412,6 +411,15 @@ flow_delete_block (b)
b->pred = NULL; b->pred = NULL;
b->succ = 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. */ /* Remove the basic block from the array, and compact behind it. */
expunge_block (b); expunge_block (b);
......
...@@ -98,8 +98,15 @@ int (*lang_eh_type_covers) PARAMS ((tree a, tree b)); ...@@ -98,8 +98,15 @@ int (*lang_eh_type_covers) PARAMS ((tree a, tree b));
/* Map a type to a runtime object to match type. */ /* Map a type to a runtime object to match type. */
tree (*lang_eh_runtime_type) PARAMS ((tree)); tree (*lang_eh_runtime_type) PARAMS ((tree));
/* A list of labels used for exception handlers. */ /* A hash table of label to region number. */
rtx exception_handler_labels;
struct ehl_map_entry
{
rtx label;
struct eh_region *region;
};
static htab_t exception_handler_label_map;
static int call_site_base; static int call_site_base;
static unsigned int sjlj_funcdef_number; static unsigned int sjlj_funcdef_number;
...@@ -126,6 +133,10 @@ struct eh_region ...@@ -126,6 +133,10 @@ struct eh_region
/* An identifier for this region. */ /* An identifier for this region. */
int region_number; 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. */ /* Each region does exactly one thing. */
enum eh_region_type enum eh_region_type
{ {
...@@ -242,6 +253,10 @@ struct eh_status ...@@ -242,6 +253,10 @@ struct eh_status
static void mark_eh_region PARAMS ((struct eh_region *)); 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, static int t2r_eq PARAMS ((const PTR,
const PTR)); const PTR));
...@@ -292,8 +307,15 @@ static void sjlj_emit_dispatch_table ...@@ -292,8 +307,15 @@ static void sjlj_emit_dispatch_table
PARAMS ((rtx, struct sjlj_lp_info *)); PARAMS ((rtx, struct sjlj_lp_info *));
static void sjlj_build_landing_pads PARAMS ((void)); 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_exception_handler_label PARAMS ((rtx));
static void remove_eh_handler PARAMS ((struct eh_region *)); static void remove_eh_handler PARAMS ((struct eh_region *));
static int for_each_eh_label_1 PARAMS ((PTR *, PTR));
struct reachable_info; struct reachable_info;
...@@ -364,7 +386,7 @@ doing_eh (do_warn) ...@@ -364,7 +386,7 @@ doing_eh (do_warn)
void void
init_eh () 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) if (! flag_exceptions)
return; return;
...@@ -511,6 +533,25 @@ mark_eh_region (region) ...@@ -511,6 +533,25 @@ mark_eh_region (region)
ggc_mark_rtx (region->post_landing_pad); 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 void
mark_eh_status (eh) mark_eh_status (eh)
struct eh_status *eh; struct eh_status *eh;
...@@ -572,6 +613,16 @@ mark_eh_status (eh) ...@@ -572,6 +613,16 @@ mark_eh_status (eh)
ggc_mark_rtx (eh->sjlj_exit_after); 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 void
free_eh_status (f) free_eh_status (f)
struct function *f; struct function *f;
...@@ -586,7 +637,7 @@ free_eh_status (f) ...@@ -586,7 +637,7 @@ free_eh_status (f)
struct eh_region *r = eh->region_array[i]; struct eh_region *r = eh->region_array[i];
/* Mind we don't free a region struct more than once. */ /* Mind we don't free a region struct more than once. */
if (r && r->region_number == i) if (r && r->region_number == i)
free (r); free_region (r);
} }
free (eh->region_array); free (eh->region_array);
} }
...@@ -600,20 +651,20 @@ free_eh_status (f) ...@@ -600,20 +651,20 @@ free_eh_status (f)
else if (r->next_peer) else if (r->next_peer)
{ {
next = r->next_peer; next = r->next_peer;
free (r); free_region (r);
r = next; r = next;
} }
else else
{ {
do { do {
next = r->outer; next = r->outer;
free (r); free_region (r);
r = next; r = next;
if (r == NULL) if (r == NULL)
goto tree_done; goto tree_done;
} while (r->next_peer == NULL); } while (r->next_peer == NULL);
next = r->next_peer; next = r->next_peer;
free (r); free_region (r);
r = next; r = next;
} }
} }
...@@ -628,7 +679,12 @@ free_eh_status (f) ...@@ -628,7 +679,12 @@ free_eh_status (f)
free (eh); free (eh);
f->eh = NULL; 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 () ...@@ -1312,13 +1368,50 @@ convert_from_eh_region_ranges ()
remove_unreachable_regions (insns); 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 void
find_exception_handler_labels () find_exception_handler_labels ()
{ {
rtx list = NULL_RTX;
int i; 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) if (cfun->eh->region_tree == NULL)
return; return;
...@@ -1336,15 +1429,13 @@ find_exception_handler_labels () ...@@ -1336,15 +1429,13 @@ find_exception_handler_labels ()
lab = region->label; lab = region->label;
if (lab) 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 /* For sjlj exceptions, need the return label to remain live until
after landing pad generation. */ after landing pad generation. */
if (USING_SJLJ_EXCEPTIONS && ! cfun->eh->built_landing_pads) if (USING_SJLJ_EXCEPTIONS && ! cfun->eh->built_landing_pads)
list = alloc_EXPR_LIST (0, return_label, list); add_ehl_entry (return_label, NULL);
exception_handler_labels = list;
} }
bool bool
...@@ -2430,28 +2521,50 @@ finish_eh_generation () ...@@ -2430,28 +2521,50 @@ finish_eh_generation ()
cleanup_cfg (CLEANUP_PRE_LOOP); 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. */ /* 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 static void
remove_exception_handler_label (label) remove_exception_handler_label (label)
rtx 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. */ there is nothing to do. */
if (exception_handler_labels == NULL) if (exception_handler_label_map == NULL)
return; return;
for (pl = &exception_handler_labels, l = *pl; tmp.label = label;
XEXP (l, 0) != label; slot = (struct ehl_map_entry **)
pl = &XEXP (l, 1), l = *pl) htab_find_slot (exception_handler_label_map, &tmp, NO_INSERT);
continue; if (! slot)
abort ();
*pl = XEXP (l, 1); htab_clear_slot (exception_handler_label_map, (void **) slot);
free_EXPR_LIST_node (l);
} }
/* Splice REGION from the region tree etc. */ /* Splice REGION from the region tree etc. */
...@@ -2462,16 +2575,29 @@ remove_eh_handler (region) ...@@ -2462,16 +2575,29 @@ remove_eh_handler (region)
{ {
struct eh_region **pp, *p; struct eh_region **pp, *p;
rtx lab; rtx lab;
int i;
/* For the benefit of efficiently handling REG_EH_REGION notes, /* For the benefit of efficiently handling REG_EH_REGION notes,
replace this region in the region array with its containing replace this region in the region array with its containing
region. Note that previous region deletions may result in region. Note that previous region deletions may result in
multiple copies of this region in the array, so we have to multiple copies of this region in the array, so we have a
search the whole thing. */ list of alternate numbers by which we are known. */
for (i = cfun->eh->last_region_number; i > 0; --i)
if (cfun->eh->region_array[i] == region) cfun->eh->region_array[region->region_number] = region->outer;
cfun->eh->region_array[i] = 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) if (cfun->eh->built_landing_pads)
lab = region->landing_pad; lab = region->landing_pad;
...@@ -2526,7 +2652,7 @@ remove_eh_handler (region) ...@@ -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 /* LABEL heads a basic block that is about to be deleted. If this
...@@ -2537,7 +2663,8 @@ void ...@@ -2537,7 +2663,8 @@ void
maybe_remove_eh_handler (label) maybe_remove_eh_handler (label)
rtx 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 /* ??? After generating landing pads, it's not so simple to determine
if the region data is completely unused. One must examine the if the region data is completely unused. One must examine the
...@@ -2546,27 +2673,50 @@ maybe_remove_eh_handler (label) ...@@ -2546,27 +2673,50 @@ maybe_remove_eh_handler (label)
if (cfun->eh->built_landing_pads) if (cfun->eh->built_landing_pads)
return; 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]; htab_clear_slot (exception_handler_label_map, (void **) slot);
if (region && region->label == label) region->label = NULL_RTX;
{
/* 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;
}
} }
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. */ /* This section describes CFG exception edges for flow. */
......
/* Exception Handling interface routines. /* 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. Free Software Foundation, Inc.
Contributed by Mike Stump <mrs@cygnus.com>. Contributed by Mike Stump <mrs@cygnus.com>.
...@@ -83,8 +83,9 @@ extern void expand_eh_region_end_throw PARAMS ((tree)); ...@@ -83,8 +83,9 @@ extern void expand_eh_region_end_throw PARAMS ((tree));
destroying an object twice. */ destroying an object twice. */
extern void expand_eh_region_end_fixup PARAMS ((tree)); extern void expand_eh_region_end_fixup PARAMS ((tree));
/* A list of labels used for exception handlers. */ /* Invokes CALLBACK for every exception handler label. Only used by old
extern rtx exception_handler_labels; 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. */ /* Determine if the given INSN can throw an exception. */
extern bool can_throw_internal PARAMS ((rtx)); extern bool can_throw_internal PARAMS ((rtx));
......
...@@ -91,13 +91,6 @@ rebuild_jump_labels (f) ...@@ -91,13 +91,6 @@ rebuild_jump_labels (f)
for (insn = forced_labels; insn; insn = XEXP (insn, 1)) for (insn = forced_labels; insn; insn = XEXP (insn, 1))
if (GET_CODE (XEXP (insn, 0)) == CODE_LABEL) if (GET_CODE (XEXP (insn, 0)) == CODE_LABEL)
LABEL_NUSES (XEXP (insn, 0))++; 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 /* Some old code expects exactly one BARRIER as the NEXT_INSN of a
......
...@@ -235,6 +235,7 @@ FILE *loop_dump_stream; ...@@ -235,6 +235,7 @@ FILE *loop_dump_stream;
/* Forward declarations. */ /* Forward declarations. */
static void invalidate_loops_containing_label PARAMS ((rtx));
static void find_and_verify_loops PARAMS ((rtx, struct loops *)); static void find_and_verify_loops PARAMS ((rtx, struct loops *));
static void mark_loop_jump PARAMS ((rtx, struct loop *)); static void mark_loop_jump PARAMS ((rtx, struct loop *));
static void prescan_loop PARAMS ((struct loop *)); static void prescan_loop PARAMS ((struct loop *));
...@@ -2609,6 +2610,17 @@ prescan_loop (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. /* 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 Also mark as invalid loops any loops that contain a setjmp or are branched
to from outside the loop. */ to from outside the loop. */
...@@ -2695,23 +2707,12 @@ find_and_verify_loops (f, loops) ...@@ -2695,23 +2707,12 @@ find_and_verify_loops (f, loops)
/* Any loop containing a label used in an initializer must be invalidated, /* Any loop containing a label used in an initializer must be invalidated,
because it can be jumped into from anywhere. */ because it can be jumped into from anywhere. */
for (label = forced_labels; label; label = XEXP (label, 1)) for (label = forced_labels; label; label = XEXP (label, 1))
{ invalidate_loops_containing_label (XEXP (label, 0));
for (loop = uid_loop[INSN_UID (XEXP (label, 0))];
loop; loop = loop->outer)
loop->invalid = 1;
}
/* Any loop containing a label used for an exception handler must be /* Any loop containing a label used for an exception handler must be
invalidated, because it can be jumped into from anywhere. */ invalidated, because it can be jumped into from anywhere. */
for_each_eh_label (invalidate_loops_containing_label);
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;
}
/* Now scan all insn's in the function. If any JUMP_INSN branches into a /* 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. loop that it is not contained within, that loop is marked invalid.
...@@ -2735,11 +2736,7 @@ find_and_verify_loops (f, loops) ...@@ -2735,11 +2736,7 @@ find_and_verify_loops (f, loops)
{ {
rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX); rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX);
if (note) if (note)
{ invalidate_loops_containing_label (XEXP (note, 0));
for (loop = uid_loop[INSN_UID (XEXP (note, 0))];
loop; loop = loop->outer)
loop->invalid = 1;
}
} }
if (GET_CODE (insn) != JUMP_INSN) if (GET_CODE (insn) != JUMP_INSN)
......
...@@ -339,7 +339,7 @@ is_cfg_nonregular () ...@@ -339,7 +339,7 @@ is_cfg_nonregular ()
/* If we have exception handlers, then we consider the cfg not well /* If we have exception handlers, then we consider the cfg not well
structured. ?!? We should be able to handle this now that flow.c structured. ?!? We should be able to handle this now that flow.c
computes an accurate cfg for EH. */ computes an accurate cfg for EH. */
if (exception_handler_labels) if (current_function_has_exception_handlers ())
return 1; return 1;
/* If we have non-jumping insns which refer to labels, then we consider /* If we have non-jumping insns which refer to labels, then we consider
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment