static void cgraph_optimize_function (struct cgraph_node *);
static bool cgraph_default_inline_p (struct cgraph_node *n);
static void cgraph_analyze_function (struct cgraph_node *node);
+static void cgraph_decide_inlining_incrementally (struct cgraph_node *);
/* Statistics we collect about inlining algorithm. */
static int ncalls_inlined;
/* When declared inline, defer even the uninlinable functions.
This allows them to be eliminated when unused. */
&& !DECL_DECLARED_INLINE_P (decl)
- && (node->local.inlinable || !cgraph_default_inline_p (node))))
+ && (!node->local.inlinable || !cgraph_default_inline_p (node))))
return true;
return false;
/* If not unit at a time, then we need to create the call graph
now, so that called functions can be queued and emitted now. */
if (!flag_unit_at_a_time)
- cgraph_analyze_function (node);
+ {
+ cgraph_analyze_function (node);
+ cgraph_decide_inlining_incrementally (node);
+ }
if (decide_is_function_needed (node, decl))
cgraph_mark_needed_node (node);
cgraph_expand_function (struct cgraph_node *node)
{
tree decl = node->decl;
- struct cgraph_edge *e;
if (flag_unit_at_a_time)
announce_function (decl);
via lang_expand_decl_stmt. */
(*lang_hooks.callgraph.expand_function) (decl);
- if (!flag_unit_at_a_time)
- {
- if (!node->local.inlinable
- || (!node->local.disregard_inline_limits
- && !cgraph_default_inline_p (node)))
- DECL_SAVED_TREE (node->decl) = NULL;
- }
- else
- {
- for (e = node->callers; e; e = e->next_caller)
- if (e->inline_call)
- break;
- if (!e)
- DECL_SAVED_TREE (decl) = NULL;
- }
+ if (!cgraph_function_possibly_inlined_p (decl))
+ DECL_SAVED_TREE (decl) = NULL;
current_function_decl = NULL;
}
bool called = false;
int new_insns;
+ what->global.inlined = 1;
for (e = what->callers; e; e = e->next_caller)
{
if (e->caller == to)
to->global.insns = new_insns;
if (!called && !what->needed && !what->origin
+ && flag_unit_at_a_time
&& !DECL_EXTERNAL (what->decl))
{
if (!what->global.will_be_output)
All inline candidates are put into prioritized heap based on estimated
growth of the overall number of instructions and then update the estimates.
- INLINED and INLINED_CALEES are just pointers to arrays large enought
+ INLINED and INLINED_CALEES are just pointers to arrays large enough
to be passed to cgraph_inlined_into and cgraph_inlined_callees. */
static void
xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
int ninlined;
int ninlined_callees;
- int old_insns;
+ int old_insns = 0;
int i, y;
for (node = cgraph_nodes; node; node = node->next)
free (inlined_callees);
}
+/* Decide on the inlining. We do so in the topological order to avoid
+ expenses on updating datastructures. */
+
+static void
+cgraph_decide_inlining_incrementally (struct cgraph_node *node)
+{
+ struct cgraph_edge *e;
+ struct cgraph_node **inlined =
+ xmalloc (sizeof (struct cgraph_node *) * cgraph_n_nodes);
+ struct cgraph_node **inlined_callees =
+ xmalloc (sizeof (struct cgraph_node *) * cgraph_n_nodes);
+ int ninlined;
+ int ninlined_callees;
+ int y;
+
+ ninlined = cgraph_inlined_into (node, inlined);
+
+ /* First of all look for always inline functions. */
+ for (e = node->callees; e; e = e->next_callee)
+ if (e->callee->local.disregard_inline_limits && !e->callee->output
+ && e->callee != node && !e->inline_call)
+ {
+ ninlined_callees = cgraph_inlined_callees (e->callee, inlined_callees);
+ cgraph_mark_inline (node, e->callee, inlined, ninlined,
+ inlined_callees, ninlined_callees);
+ for (y = 0; y < ninlined_callees; y++)
+ inlined_callees[y]->output = 0, node->aux = 0;
+ }
+
+ /* Now do the automatic inlining. */
+ for (e = node->callees; e; e = e->next_callee)
+ if (e->callee->local.inlinable && !e->callee->output
+ && e->callee != node && !e->inline_call
+ && cgraph_default_inline_p (e->callee)
+ && cgraph_check_inline_limits (node, e->callee, inlined,
+ ninlined))
+ {
+ ninlined_callees = cgraph_inlined_callees (e->callee, inlined_callees);
+ cgraph_mark_inline (node, e->callee, inlined, ninlined,
+ inlined_callees, ninlined_callees);
+ for (y = 0; y < ninlined_callees; y++)
+ inlined_callees[y]->output = 0, node->aux = 0;
+ }
+
+ /* Clear the flags set by cgraph_inlined_into. */
+ for (y = 0; y < ninlined; y++)
+ inlined[y]->output = 0, node->aux = 0;
+
+ free (inlined);
+ free (inlined_callees);
+}
+
+
/* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */
bool