aboutsummaryrefslogtreecommitdiff
path: root/gcc/except.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2002-01-14 22:06:26 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2002-01-14 22:06:26 +0100
commit655dd289ba24fa9f80a07c36431937e6f649a490 (patch)
treeec54cec524d78b39ae5d7136e8cd28a953bc4958 /gcc/except.c
parente6a5e4628761239be448d4dfd14eed42bc37383c (diff)
downloadgcc-655dd289ba24fa9f80a07c36431937e6f649a490.zip
gcc-655dd289ba24fa9f80a07c36431937e6f649a490.tar.gz
gcc-655dd289ba24fa9f80a07c36431937e6f649a490.tar.bz2
except.c (remove_unreachable_regions): New.
* except.c (remove_unreachable_regions): New. (free_eh_status): Clear exception_handler_labels. (convert_from_eh_region_ranges): Call remove_unreachable_regions. (find_exception_handler_labels): Don't add the same label more than once. (remove_exception_handler_label): Don't die if find_exception_handler_labels hasn't been called for the current function yet. From-SVN: r48845
Diffstat (limited to 'gcc/except.c')
-rw-r--r--gcc/except.c73
1 files changed, 72 insertions, 1 deletions
diff --git a/gcc/except.c b/gcc/except.c
index 6da82f7..2ce69f2 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -263,6 +263,7 @@ static rtx get_exception_filter PARAMS ((struct function *));
static void collect_eh_region_array PARAMS ((void));
static void resolve_fixup_regions PARAMS ((void));
static void remove_fixup_regions PARAMS ((void));
+static void remove_unreachable_regions PARAMS ((rtx));
static void convert_from_eh_region_ranges_1 PARAMS ((rtx *, int *, int));
static struct eh_region *duplicate_eh_region_1 PARAMS ((struct eh_region *,
@@ -632,6 +633,7 @@ free_eh_status (f)
free (eh);
f->eh = NULL;
+ exception_handler_labels = NULL;
}
@@ -1212,6 +1214,69 @@ remove_fixup_regions ()
}
}
+/* Remove all regions whose labels are not reachable from insns. */
+
+static void
+remove_unreachable_regions (insns)
+ rtx insns;
+{
+ int i, *uid_region_num;
+ bool *reachable;
+ struct eh_region *r;
+ rtx insn;
+
+ uid_region_num = xcalloc (get_max_uid (), sizeof(int));
+ reachable = xcalloc (cfun->eh->last_region_number + 1, sizeof(bool));
+
+ for (i = cfun->eh->last_region_number; i > 0; --i)
+ {
+ r = cfun->eh->region_array[i];
+ if (!r || r->region_number != i)
+ continue;
+
+ if (r->resume)
+ {
+ if (uid_region_num[INSN_UID (r->resume)])
+ abort ();
+ uid_region_num[INSN_UID (r->resume)] = i;
+ }
+ if (r->label)
+ {
+ if (uid_region_num[INSN_UID (r->label)])
+ abort ();
+ uid_region_num[INSN_UID (r->label)] = i;
+ }
+ if (r->type == ERT_TRY && r->u.try.continue_label)
+ {
+ if (uid_region_num[INSN_UID (r->u.try.continue_label)])
+ abort ();
+ uid_region_num[INSN_UID (r->u.try.continue_label)] = i;
+ }
+ }
+
+ for (insn = insns; insn; insn = NEXT_INSN (insn))
+ reachable[uid_region_num[INSN_UID (insn)]] = true;
+
+ for (i = cfun->eh->last_region_number; i > 0; --i)
+ {
+ r = cfun->eh->region_array[i];
+ if (r && r->region_number == i && !reachable[i])
+ {
+ /* Don't remove ERT_THROW regions if their outer region
+ is reachable. */
+ if (r->type == ERT_THROW
+ && r->outer
+ && reachable[r->outer->region_number])
+ continue;
+
+ remove_eh_handler (r);
+ }
+ }
+
+ free (reachable);
+ free (uid_region_num);
+}
+
/* Turn NOTE_INSN_EH_REGION notes into REG_EH_REGION notes for each
can_throw instruction in the region. */
@@ -1314,6 +1379,7 @@ convert_from_eh_region_ranges ()
free (stack);
remove_fixup_regions ();
+ remove_unreachable_regions (insns);
}
void
@@ -1332,7 +1398,7 @@ find_exception_handler_labels ()
struct eh_region *region = cfun->eh->region_array[i];
rtx lab;
- if (! region)
+ if (! region || region->region_number != i)
continue;
if (cfun->eh->built_landing_pads)
lab = region->landing_pad;
@@ -2427,6 +2493,11 @@ remove_exception_handler_label (label)
{
rtx *pl, l;
+ /* If exception_handler_labels was not built yet,
+ there is nothing to do. */
+ if (exception_handler_labels == NULL)
+ return;
+
for (pl = &exception_handler_labels, l = *pl;
XEXP (l, 0) != label;
pl = &XEXP (l, 1), l = *pl)