diff options
author | Richard Guenther <rguenther@suse.de> | 2005-07-15 09:31:39 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2005-07-15 09:31:39 +0000 |
commit | 0691d1d4a31ff0a426d2ba07c64acbac5df6b8ae (patch) | |
tree | 2e0dd485a84563f4c7093a4d5ed09ecd19507784 /gcc/ipa-inline.c | |
parent | 7c22afcba12417a2dcb10ceb358966447f07f5ef (diff) | |
download | gcc-0691d1d4a31ff0a426d2ba07c64acbac5df6b8ae.zip gcc-0691d1d4a31ff0a426d2ba07c64acbac5df6b8ae.tar.gz gcc-0691d1d4a31ff0a426d2ba07c64acbac5df6b8ae.tar.bz2 |
c-common.c (handle_flatten_attribute): New function.
2005-07-15 Richard Guenther <rguenther@suse.de>
* c-common.c (handle_flatten_attribute): New function.
Add flatten function attribute.
* doc/extend.texi: Document flatten function attribute.
* Makefile.in (ipa-inline.o): Depend on hashtab.h.
* ipa-inline.c (cgraph_find_cycles, cgraph_flatten_node):
New functions.
(cgraph_decide_inlining): Handle functions with flatten
attribute.
* gcc.dg/tree-ssa/flatten-1.c: New testcase.
* gcc.dg/tree-ssa/flatten-2.c: Likewise.
From-SVN: r102051
Diffstat (limited to 'gcc/ipa-inline.c')
-rw-r--r-- | gcc/ipa-inline.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index cb71047..df57ccc 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -78,6 +78,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "fibheap.h" #include "intl.h" #include "tree-pass.h" +#include "hashtab.h" #include "coverage.h" #include "ggc.h" @@ -438,6 +439,65 @@ lookup_recursive_calls (struct cgraph_node *node, struct cgraph_node *where, lookup_recursive_calls (node, e->callee, heap); } +/* Find callgraph nodes closing a circle in the graph. The + resulting hashtab can be used to avoid walking the circles. + Uses the cgraph nodes ->aux field which needs to be zero + before and will be zero after operation. */ + +static void +cgraph_find_cycles (struct cgraph_node *node, htab_t cycles) +{ + struct cgraph_edge *e; + + if (node->aux) + { + void **slot; + slot = htab_find_slot (cycles, node, INSERT); + if (!*slot) + { + if (dump_file) + fprintf (dump_file, "Cycle contains %s\n", cgraph_node_name (node)); + *slot = node; + } + return; + } + + node->aux = node; + for (e = node->callees; e; e = e->next_callee) + cgraph_find_cycles (e->callee, cycles); + node->aux = 0; +} + +/* Leafify the cgraph node. We have to be careful in recursing + as to not run endlessly in circles of the callgraph. + We do so by using a hashtab of cycle entering nodes as generated + by cgraph_find_cycles. */ + +static void +cgraph_flatten_node (struct cgraph_node *node, htab_t cycles) +{ + struct cgraph_edge *e; + + for (e = node->callees; e; e = e->next_callee) + { + /* Inline call, if possible, and recurse. Be sure we are not + entering callgraph circles here. */ + if (e->inline_failed + && e->callee->local.inlinable + && !cgraph_recursive_inlining_p (node, e->callee, + &e->inline_failed) + && !htab_find (cycles, e->callee)) + { + if (dump_file) + fprintf (dump_file, " inlining %s", cgraph_node_name (e->callee)); + cgraph_mark_inline_edge (e); + cgraph_flatten_node (e->callee, cycles); + } + else if (dump_file) + fprintf (dump_file, " !inlining %s", cgraph_node_name (e->callee)); + } +} + /* Decide on recursive inlining: in the case function has recursive calls, inline until body size reaches given argument. */ @@ -769,6 +829,24 @@ cgraph_decide_inlining (void) node = order[i]; + /* Handle nodes to be flattened, but don't update overall unit size. */ + if (lookup_attribute ("flatten", DECL_ATTRIBUTES (node->decl)) != NULL) + { + int old_overall_insns = overall_insns; + htab_t cycles; + if (dump_file) + fprintf (dump_file, + "Leafifying %s\n", cgraph_node_name (node)); + cycles = htab_create (7, htab_hash_pointer, htab_eq_pointer, NULL); + cgraph_find_cycles (node, cycles); + cgraph_flatten_node (node, cycles); + htab_delete (cycles); + overall_insns = old_overall_insns; + /* We don't need to consider always_inline functions inside the flattened + function anymore. */ + continue; + } + if (!node->local.disregard_inline_limits) continue; if (dump_file) |