summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2002-04-10 00:15:58 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2002-04-10 00:15:58 +0000
commit8f8dcce4abc08b582f0124d0b5a053bf36a34db0 (patch)
tree3634a27519c3d4e86e699e40edd03e6636c09ae2
parent8c8eb75026520e93147a7dc390c59c41e432a749 (diff)
downloadgcc-8f8dcce4abc08b582f0124d0b5a053bf36a34db0.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@52100 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog31
-rw-r--r--gcc/basic-block.h4
-rw-r--r--gcc/cfg.c20
-rw-r--r--gcc/cfgcleanup.c25
-rw-r--r--gcc/cfgrtl.c16
-rw-r--r--gcc/except.c248
-rw-r--r--gcc/except.h7
-rw-r--r--gcc/jump.c7
-rw-r--r--gcc/loop.c33
-rw-r--r--gcc/sched-rgn.c2
10 files changed, 297 insertions, 96 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a7623708117..8aa89363064 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,36 @@
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_a_or_b, sbitmap_a_or_b_and_c, sbitmap_a_and_b_or_c):
Do not return changed status.
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index c9fc4b8e706..24d2af83575 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -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));
diff --git a/gcc/cfg.c b/gcc/cfg.c
index 0a718679a31..766c1b8ff3d 100644
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -223,6 +223,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
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index b6a7f0cc4ea..74a2256b5e2 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -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 ();
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index ef9a91c96b9..a56eea2e940 100644
--- a/gcc/cfgrtl.c
+++ b/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);
diff --git a/gcc/except.c b/gcc/except.c
index e5079f99e0d..d4a903e597c 100644
--- a/gcc/except.c
+++ b/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. */
diff --git a/gcc/except.h b/gcc/except.h
index 200210f31bc..ce91051d5b1 100644
--- a/gcc/except.h
+++ b/gcc/except.h
@@ -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));
diff --git a/gcc/jump.c b/gcc/jump.c
index a04a4f51ab4..f32b831c6df 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -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
diff --git a/gcc/loop.c b/gcc/loop.c
index b51b2a850d7..53b9caa3aa0 100644
--- a/gcc/loop.c
+++ b/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)
diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c
index 6ec2668bc32..ab65e2cec5e 100644
--- a/gcc/sched-rgn.c
+++ b/gcc/sched-rgn.c
@@ -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