aboutsummaryrefslogtreecommitdiff
path: root/gcc/cgraphunit.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r--gcc/cgraphunit.c77
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:");