summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2005-05-12 19:29:21 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2005-05-12 19:29:21 +0000
commit0de999f197a88a5f7a1cd00f30d901228bab4558 (patch)
treee8fbec3fe9a12f57e69dd33bd03e77391cc8bc6b /gcc
parent81e19b315c09e2f08de19bd5838caa8221eb3a99 (diff)
downloadgcc-0de999f197a88a5f7a1cd00f30d901228bab4558.tar.gz
* except.c (duplicate_eh_region_1, duplicate_eh_region_2,
duplicate_eh_regions): New functions, based on old implementation removed with RTL inliner. (reachable_next_level): Modify behaviour pre-inline. * except.h (duplicate_eh_regions_map, duplicate_eh_regions): Declare. * function.h (struct function): Add after_inlining flag. * tree-optimize.c (tree_rest_of_compilation): Set it. * tree-eh.c (add_stmt_to_eh_region_fn): Initialize hashtable when needed. * tree-cfg.c (label_to_block_fn): Deal with cases where label was never insterted into code. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@99625 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/except.c151
-rw-r--r--gcc/except.h2
-rw-r--r--gcc/function.h1
-rw-r--r--gcc/tree-cfg.c2
-rw-r--r--gcc/tree-eh.c5
-rw-r--r--gcc/tree-optimize.c1
7 files changed, 177 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 56615851773..cb6bc1bc239 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+2005-05-12 Steven Bosscher <stevenb@suse.de>
+ Stuart Hastings <stuart@apple.com>
+ Jan Hubicka <jh@suse.cz>
+
+ * except.c (duplicate_eh_region_1, duplicate_eh_region_2,
+ duplicate_eh_regions): New functions, based on old
+ implementation removed with RTL inliner.
+ (reachable_next_level): Modify behaviour pre-inline.
+ * except.h (duplicate_eh_regions_map, duplicate_eh_regions):
+ Declare.
+ * function.h (struct function): Add after_inlining flag.
+ * tree-optimize.c (tree_rest_of_compilation): Set it.
+ * tree-eh.c (add_stmt_to_eh_region_fn): Initialize hashtable
+ when needed.
+ * tree-cfg.c (label_to_block_fn): Deal with cases where
+ label was never insterted into code.
+
2005-05-12 Zack Weinberg <zack@codesourcery.com>
* doc/cpp.texi: Document that #sccs is a synonym for #ident.
diff --git a/gcc/except.c b/gcc/except.c
index 35105f9d7ad..9f1bfe926af 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -853,6 +853,148 @@ current_function_has_exception_handlers (void)
return false;
}
+static struct eh_region *
+duplicate_eh_region_1 (struct eh_region *o)
+{
+ struct eh_region *n = ggc_alloc_cleared (sizeof (struct eh_region));
+
+ *n = *o;
+
+ n->region_number = o->region_number + cfun->eh->last_region_number;
+ gcc_assert (!o->aka);
+
+ return n;
+}
+
+static void
+duplicate_eh_region_2 (struct eh_region *o, struct eh_region **n_array,
+ struct eh_region *prev_try)
+{
+ struct eh_region *n = n_array[o->region_number];
+
+ switch (n->type)
+ {
+ case ERT_TRY:
+ if (o->u.try.catch)
+ n->u.try.catch = n_array[o->u.try.catch->region_number];
+ if (o->u.try.last_catch)
+ n->u.try.last_catch = n_array[o->u.try.last_catch->region_number];
+ break;
+
+ case ERT_CATCH:
+ if (o->u.catch.next_catch)
+ n->u.catch.next_catch = n_array[o->u.catch.next_catch->region_number];
+ if (o->u.catch.prev_catch)
+ n->u.catch.prev_catch = n_array[o->u.catch.prev_catch->region_number];
+ break;
+
+ case ERT_CLEANUP:
+ if (o->u.cleanup.prev_try)
+ n->u.cleanup.prev_try = n_array[o->u.cleanup.prev_try->region_number];
+ else
+ n->u.cleanup.prev_try = prev_try;
+ break;
+
+ default:
+ break;
+ }
+
+ if (o->outer)
+ n->outer = n_array[o->outer->region_number];
+ if (o->inner)
+ n->inner = n_array[o->inner->region_number];
+ if (o->next_peer)
+ n->next_peer = n_array[o->next_peer->region_number];
+}
+
+/* Duplicate the EH regions of IFUN into current function, root the tree in
+ OUTER_REGION and remap labels using MAP callback. */
+int
+duplicate_eh_regions (struct function *ifun, duplicate_eh_regions_map map,
+ void *data, int outer_region)
+{
+ int ifun_last_region_number = ifun->eh->last_region_number;
+ struct eh_region **n_array, *root, *cur, *prev_try;
+ int i;
+
+ if (ifun_last_region_number == 0 || !ifun->eh->region_tree)
+ return 0;
+
+ n_array = xcalloc (ifun_last_region_number + 1, sizeof (*n_array));
+
+ /* Search for the containing ERT_TRY region to fix up
+ the prev_try short-cuts for ERT_CLEANUP regions. */
+ prev_try = NULL;
+ if (outer_region > 0)
+ for (prev_try = cfun->eh->region_array[outer_region];
+ prev_try && prev_try->type != ERT_TRY;
+ prev_try = prev_try->outer)
+ ;
+
+ for (i = 1; i <= ifun_last_region_number; ++i)
+ {
+ cur = ifun->eh->region_array[i];
+ if (!cur || cur->region_number != i)
+ continue;
+ n_array[i] = duplicate_eh_region_1 (cur);
+ if (cur->tree_label)
+ {
+ tree newlabel = map (cur->tree_label, data);
+ n_array[i]->tree_label = newlabel;
+ }
+ else
+ n_array[i]->tree_label = NULL;
+ }
+ for (i = 1; i <= ifun_last_region_number; ++i)
+ {
+ cur = ifun->eh->region_array[i];
+ if (!cur || cur->region_number != i)
+ continue;
+ duplicate_eh_region_2 (cur, n_array, prev_try);
+ }
+
+ root = n_array[ifun->eh->region_tree->region_number];
+ gcc_assert (root->outer == NULL);
+ if (outer_region > 0)
+ {
+ struct eh_region *cur = cfun->eh->region_array[outer_region];
+ struct eh_region *p = cur->inner;
+
+ if (p)
+ {
+ while (p->next_peer)
+ p = p->next_peer;
+ p->next_peer = root;
+ }
+ else
+ cur->inner = root;
+ for (i = 1; i <= ifun_last_region_number; ++i)
+ if (n_array[i] && n_array[i]->outer == NULL)
+ n_array[i]->outer = cur;
+ }
+ else
+ {
+ struct eh_region *p = cfun->eh->region_tree;
+ if (p)
+ {
+ while (p->next_peer)
+ p = p->next_peer;
+ p->next_peer = root;
+ }
+ else
+ cfun->eh->region_tree = root;
+ }
+
+ free (n_array);
+
+ i = cfun->eh->last_region_number;
+ cfun->eh->last_region_number = i + ifun_last_region_number;
+
+ collect_eh_region_array ();
+
+ return i;
+}
+
static int
t2r_eq (const void *pentry, const void *pdata)
{
@@ -2273,8 +2415,13 @@ reachable_next_level (struct eh_region *region, tree type_thrown,
/* Here we end our search, since no exceptions may propagate.
If we've touched down at some landing pad previous, then the
explicit function call we generated may be used. Otherwise
- the call is made by the runtime. */
- if (info && info->saw_any_handlers)
+ the call is made by the runtime.
+
+ Before inlining, do not perform this optimization. We may
+ inline a subroutine that contains handlers, and that will
+ change the value of saw_any_handlers. */
+
+ if ((info && info->saw_any_handlers) || !cfun->after_inlining)
{
add_reachable_handler (info, region, region);
return RNL_CAUGHT;
diff --git a/gcc/except.h b/gcc/except.h
index 746b3d4aca8..9526b865909 100644
--- a/gcc/except.h
+++ b/gcc/except.h
@@ -81,6 +81,8 @@ extern void expand_eh_return (void);
extern rtx expand_builtin_extend_pointer (tree);
extern rtx get_exception_pointer (struct function *);
extern rtx get_exception_filter (struct function *);
+typedef tree (*duplicate_eh_regions_map) (tree, void *);
+extern int duplicate_eh_regions (struct function *, duplicate_eh_regions_map, void *, int);
extern void sjlj_emit_function_exit_after (rtx);
diff --git a/gcc/function.h b/gcc/function.h
index 4f6181aa08c..0720c12ca5d 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -168,6 +168,7 @@ struct function GTY(())
/* The control flow graph for this function. */
struct control_flow_graph *cfg;
+ bool after_inlining;
/* For tree-optimize.c. */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index c54305c898b..9860a29da00 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -823,6 +823,8 @@ label_to_block_fn (struct function *ifun, tree dest)
bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
uid = LABEL_DECL_UID (dest);
}
+ if (VARRAY_SIZE (ifun->cfg->x_label_to_block_map) <= (unsigned int)uid)
+ return NULL;
return VARRAY_BB (ifun->cfg->x_label_to_block_map, uid);
}
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 72644aa0b04..3bf58300d27 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -112,6 +112,11 @@ add_stmt_to_eh_region_fn (struct function *ifun, tree t, int num)
n->stmt = t;
n->region_nr = num;
+ if (!get_eh_throw_stmt_table (ifun))
+ set_eh_throw_stmt_table (ifun, htab_create_ggc (31, struct_ptr_hash,
+ struct_ptr_eq,
+ ggc_free));
+
slot = htab_find_slot (get_eh_throw_stmt_table (ifun), n, INSERT);
gcc_assert (!*slot);
*slot = n;
diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c
index 6e07a2b504f..c3ceb31f59c 100644
--- a/gcc/tree-optimize.c
+++ b/gcc/tree-optimize.c
@@ -675,6 +675,7 @@ tree_rest_of_compilation (tree fndecl)
We haven't necessarily assigned RTL to all variables yet, so it's
not safe to try to expand expressions involving them. */
cfun->x_dont_save_pending_sizes_p = 1;
+ cfun->after_inlining = true;
node = cgraph_node (fndecl);