aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/except.c14
-rw-r--r--gcc/except.h3
-rw-r--r--gcc/tree-cfg.c34
4 files changed, 59 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7771f78..bb08ea4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2004-06-04 Steven Bosscher <stevenb@suse.de>
+
+ * except.c (for_each_eh_region): New function.
+ * except.h (for_each_eh_region): Add a prototype for it.
+ * tree-cfg.c (update_eh_labels): New function, callback for
+ for_each_eh_region.
+ (label_for_bb): Make global static, unfortunately.
+ (cleanup_dead_labels): Also update label references for
+ exception regions.
+
2004-06-03 Chris Demetriou <cgd@broadcom.com>
* config/mips/mips.c (struct irix_section_align_entry): Fix
@@ -19,7 +29,7 @@
documentation to reflect the new macro name and to clarify its
meaning.
-2004-06-04 Steven Bosscher <stevenb@suse.de>
+2004-06-03 Steven Bosscher <stevenb@suse.de>
* rtl.def (VAR_LOCATION): Make RTX_EXTRA.
diff --git a/gcc/except.c b/gcc/except.c
index f3bc4ef..65aa8b5 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -2742,6 +2742,20 @@ for_each_eh_label_1 (void **pentry, void *data)
(*callback) (entry->label);
return 1;
}
+
+/* Invoke CALLBACK for every exception region in the current function. */
+
+void
+for_each_eh_region (void (*callback) (struct eh_region *))
+{
+ int i, n = cfun->eh->last_region_number;
+ for (i = 1; i <= n; ++i)
+ {
+ struct eh_region *region = cfun->eh->region_array[i];
+ if (region)
+ (*callback) (region);
+ }
+}
/* This section describes CFG exception edges for flow. */
diff --git a/gcc/except.h b/gcc/except.h
index 2fed79f..4c596a9 100644
--- a/gcc/except.h
+++ b/gcc/except.h
@@ -90,6 +90,9 @@ extern void note_current_region_may_contain_throw (void);
loop hackery; should not be used by new code. */
extern void for_each_eh_label (void (*) (rtx));
+/* Invokes CALLBACK for every exception region in the current function. */
+extern void for_each_eh_region (void (*) (struct eh_region *));
+
/* Determine if the given INSN can throw an exception. */
extern bool can_throw_internal_1 (int);
extern bool can_throw_internal (rtx);
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 21277d8..d6823cb 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -762,13 +762,38 @@ cleanup_tree_cfg (void)
}
-/* Cleanup useless labels from the flow graph. */
+/* Cleanup useless labels in basic blocks. This is something we wish
+ to do early because it allows us to group case labels before creating
+ the edges for the CFG, and it speeds up block statement iterators in
+ all passes later on.
+ We only run this pass once, running it more than once is probably not
+ profitable. */
+
+/* A map from basic block index to the leading label of that block. */
+static tree *label_for_bb;
+
+/* Callback for for_each_eh_region. Helper for cleanup_dead_labels. */
+static void
+update_eh_label (struct eh_region *region)
+{
+ tree old_label = get_eh_region_tree_label (region);
+ if (old_label)
+ {
+ tree new_label = label_for_bb[label_to_block (old_label)->index];
+ set_eh_region_tree_label (region, new_label);
+ }
+}
+
+/* Cleanup redundant labels. This is a three-steo process:
+ 1) Find the leading label for each block.
+ 2) Redirect all references to labels to the leading labels.
+ 3) Cleanup all useless labels. */
static void
cleanup_dead_labels (void)
{
basic_block bb;
- tree *label_for_bb = xcalloc (last_basic_block, sizeof (tree));
+ label_for_bb = xcalloc (last_basic_block, sizeof (tree));
/* Find a suitable label for each block. We use the first user-defined
label is there is one, or otherwise just the first label we see. */
@@ -805,7 +830,8 @@ cleanup_dead_labels (void)
}
}
- /* Now redirect all jumps/branches to the selected label for each block. */
+ /* Now redirect all jumps/branches to the selected label.
+ First do so for each block ending in a control statement. */
FOR_EACH_BB (bb)
{
tree stmt = last_stmt (bb);
@@ -864,6 +890,8 @@ cleanup_dead_labels (void)
}
}
+ for_each_eh_region (update_eh_label);
+
/* Finally, purge dead labels. All user-defined labels and labels that
can be the target of non-local gotos are preserved. */
FOR_EACH_BB (bb)