diff options
author | Jan Hubicka <jh@suse.cz> | 2003-03-08 14:26:37 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2003-03-08 13:26:37 +0000 |
commit | 18d13f34175f157bc3152afdf48da798452afc1b (patch) | |
tree | 8a4f34953d22192851b98b6fb46d7a44532ecfc0 /gcc/cgraphunit.c | |
parent | 4a07c08a47f2a4fbce5634b93834ed824ebafc79 (diff) | |
download | gcc-18d13f34175f157bc3152afdf48da798452afc1b.zip gcc-18d13f34175f157bc3152afdf48da798452afc1b.tar.gz gcc-18d13f34175f157bc3152afdf48da798452afc1b.tar.bz2 |
inline-3.c: New test.
* gcc.dg/inline-3.c: New test.
* c-decl.c: (finish_function): Update call of tree_inlinable_function_p.
* cgraph.h: (cgraph_local_info): Add can_inline_once
(cgraph_global_info): Add inline_once.
(cgraph_node): Add previous.
(cgraph_remove_node): New.
* cgraphunit.c (cgraph_mark_functions_to_inline_once): New static
function.
(cgraph_optimize): Call it.
(cgraph_finalize_function): Set inlinable flags.
(cgraph_finalize_compilation_unit): Actually remove the reclaimed nodes.
(cgraph_mark_functions_to_output): Use new inlining heuristics flags.
(cgraph_expand_function): Likewise.
* cgraph.c
(cgraph_node): Put nodes into doubly linked chain.
(cgraph_remove_node): New function.
* flags.h (flag_inline_functions_called_once): Declare.
* tree-inline.c: Include cgraph.h
(inlinable_functions_p): Add extra argument to bypass limits.
(expand_call_inline): Obey cgraph flag.
* tree-inline.h (tree_inlinable_function_p): Update prototype.
From-SVN: r63983
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r-- | gcc/cgraphunit.c | 77 |
1 files changed, 71 insertions, 6 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 81a8b2e..c01bba6 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -40,6 +40,8 @@ static void cgraph_mark_functions_to_output PARAMS ((void)); static void cgraph_expand_function PARAMS ((struct cgraph_node *)); static tree record_call_1 PARAMS ((tree *, int *, void *)); static void cgraph_mark_local_functions PARAMS ((void)); +static void cgraph_mark_functions_to_inline_once PARAMS ((void)); +static void cgraph_optimize_function PARAMS ((struct cgraph_node *)); /* Analyze function once it is parsed. Set up the local information available - create cgraph edges for function calles via BODY. */ @@ -53,8 +55,9 @@ cgraph_finalize_function (decl, body) node->decl = decl; + node->local.can_inline_once = tree_inlinable_function_p (decl, 1); if (flag_inline_trees) - node->local.inline_many = tree_inlinable_function_p (decl); + node->local.inline_many = tree_inlinable_function_p (decl, 0); else node->local.inline_many = 0; @@ -200,7 +203,7 @@ cgraph_finalize_compilation_unit () if (!node->reachable && DECL_SAVED_TREE (decl)) { - DECL_SAVED_TREE (decl) = NULL; + cgraph_remove_node (node); announce_function (decl); } } @@ -221,7 +224,8 @@ cgraph_mark_functions_to_output () if (DECL_SAVED_TREE (decl) && (node->needed - || (!node->local.inline_many && node->reachable) + || (!node->local.inline_many && !node->global.inline_once + && node->reachable) || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) && !TREE_ASM_WRITTEN (decl) && !node->origin && !DECL_EXTERNAL (decl)) @@ -229,6 +233,22 @@ cgraph_mark_functions_to_output () } } +/* Optimize the function before expansion. */ +static void +cgraph_optimize_function (node) + struct cgraph_node *node; +{ + tree decl = node->decl; + + if (flag_inline_trees) + optimize_inline_calls (decl); + if (node->nested) + { + for (node = node->nested; node; node = node->next_nested) + cgraph_optimize_function (node); + } +} + /* Expand function specified by NODE. */ static void cgraph_expand_function (node) @@ -237,12 +257,18 @@ cgraph_expand_function (node) tree decl = node->decl; announce_function (decl); - if (flag_inline_trees) - optimize_inline_calls (decl); + + cgraph_optimize_function (node); /* Avoid RTL inlining from taking place. */ (*lang_hooks.callgraph.expand_function) (decl); - if (DECL_UNINLINABLE (decl)) + + /* When we decided to inline the function once, we never ever should need to + output it separately. */ + if (node->global.inline_once) + abort (); + if (!node->local.inline_many + || !node->callers) DECL_SAVED_TREE (decl) = NULL; current_function_decl = NULL; } @@ -354,6 +380,43 @@ cgraph_mark_local_functions () } } +/* Decide what function should be inlined because they are invoked once + (so inlining won't result in duplication of the code). */ + +static void +cgraph_mark_functions_to_inline_once () +{ + struct cgraph_node *node, *node1; + + if (!quiet_flag) + fprintf (stderr, "\n\nMarking functions to inline once:"); + + /* Now look for function called only once and mark them to inline. From this + point number of calls to given function won't grow. */ + for (node = cgraph_nodes; node; node = node->next) + { + if (node->callers && !node->callers->next_caller && !node->needed + && node->local.can_inline_once) + { + bool ok = true; + + /* Verify that we won't duplicate the caller. */ + for (node1 = node->callers->caller; + node1->local.inline_many + && node1->callers + && ok; + node1 = node1->callers->caller) + if (node1->callers->next_caller || node1->needed) + ok = false; + if (ok) + { + node->global.inline_once = true; + announce_function (node->decl); + } + } + } +} + /* Perform simple optimizations based on callgraph. */ @@ -365,6 +428,8 @@ cgraph_optimize () cgraph_mark_local_functions (); + cgraph_mark_functions_to_inline_once (); + cgraph_global_info_ready = true; if (!quiet_flag) fprintf (stderr, "\n\nAssembling functions:"); |