* basic-block.h (flow_delete_block_noexpunge): Declare.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 10 Apr 2002 00:15:58 +0000 (00:15 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 10 Apr 2002 00:15:58 +0000 (00:15 +0000)
(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

gcc/ChangeLog
gcc/basic-block.h
gcc/cfg.c
gcc/cfgcleanup.c
gcc/cfgrtl.c
gcc/except.c
gcc/except.h
gcc/jump.c
gcc/loop.c
gcc/sched-rgn.c

index a762370..8aa8936 100644 (file)
@@ -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.
index c9fc4b8..24d2af8 100644 (file)
@@ -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));
index 0a71867..766c1b8 100644 (file)
--- 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);
 }
 \f
 /* Create an edge connecting SRC and DST with FLAGS optionally using
index b6a7f0c..74a2256 100644 (file)
@@ -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 ();
index ef9a91c..a56eea2 100644 (file)
@@ -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);
 
index e5079f9..d4a903e 100644 (file)
@@ -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
 
 \f
 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;
+    }
 }
 
 \f
@@ -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);
 }
 \f
+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;
+}
 \f
 /* This section describes CFG exception edges for flow.  */
 
index 200210f..ce91051 100644 (file)
@@ -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));
index a04a4f5..f32b831 100644 (file)
@@ -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))++;
 }
 \f
 /* Some old code expects exactly one BARRIER as the NEXT_INSN of a
index b51b2a8..53b9caa 100644 (file)
@@ -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)
     }
 }
 \f
+/* 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)
index 6ec2668..ab65e2c 100644 (file)
@@ -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