Makefile.in (cgraph.o, [...]): Add intl.h dependency.
* Makefile.in (cgraph.o, cgraphunit.o): Add intl.h dependency. * cgraph.c (create_edge, dump_cgraph): Update to use inline_failed * cgraph.h (cgraph_edge): Replace inline_call by inline_failed (cgraph_inline_p): Add extra argument reason. * cgraphunit.c: Minor formating fixes. cgraph_first_inlined_callee): New functions. (record_call_1): Record builtins too. (cgraph_analyze_function): Update inline_failed messages. (cgraph_mark_functions_to_output, cgraph_expand_function, cgraph_inlined_into, cgraph_inlined_callees, cgraph_estimate_growth): Update to use inline_failed. (cgraph_check_inline_limits): Likewise; Add argument reason. (cgraph_set_inline_failed): New static function. (cgraph_decide_inlining_of_small_function, cgraph_decide_inlining): Set reasons. (cgraph_inline_p): Add new argument reason. * tree-inline.c (expand_call_inline): Update warning. From-SVN: r75391
This commit is contained in:
parent
e42870dffe
commit
dc0bfe6a35
@ -1,3 +1,22 @@
|
||||
2004-01-04 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* Makefile.in (cgraph.o, cgraphunit.o): Add intl.h dependency.
|
||||
* cgraph.c (create_edge, dump_cgraph): Update to use inline_failed
|
||||
* cgraph.h (cgraph_edge): Replace inline_call by inline_failed
|
||||
(cgraph_inline_p): Add extra argument reason.
|
||||
* cgraphunit.c: Minor formating fixes.
|
||||
cgraph_first_inlined_callee): New functions.
|
||||
(record_call_1): Record builtins too.
|
||||
(cgraph_analyze_function): Update inline_failed messages.
|
||||
(cgraph_mark_functions_to_output, cgraph_expand_function, cgraph_inlined_into,
|
||||
cgraph_inlined_callees, cgraph_estimate_growth): Update to use inline_failed.
|
||||
(cgraph_check_inline_limits): Likewise; Add argument reason.
|
||||
(cgraph_set_inline_failed): New static function.
|
||||
(cgraph_decide_inlining_of_small_function, cgraph_decide_inlining): Set
|
||||
reasons.
|
||||
(cgraph_inline_p): Add new argument reason.
|
||||
* tree-inline.c (expand_call_inline): Update warning.
|
||||
|
||||
2004-01-03 Nathanael Nerode <neroden@gcc.gnu.org>
|
||||
|
||||
* configure.ac: Replace AC_INIT, AC_OUTPUT, AC_CANONICAL_SYSTEM
|
||||
|
@ -1633,9 +1633,10 @@ simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RT
|
||||
$(REGS_H) hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
|
||||
output.h function.h $(GGC_H) $(OBSTACK_H) $(TM_P_H) $(TREE_H) $(TARGET_H)
|
||||
cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
|
||||
langhooks.h toplev.h flags.h $(GGC_H) $(TARGET_H) cgraph.h gt-cgraph.h output.h
|
||||
langhooks.h toplev.h flags.h $(GGC_H) $(TARGET_H) cgraph.h gt-cgraph.h \
|
||||
output.h intl.h
|
||||
cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
|
||||
langhooks.h tree-inline.h toplev.h flags.h $(GGC_H) $(TARGET_H) cgraph.h
|
||||
langhooks.h tree-inline.h toplev.h flags.h $(GGC_H) $(TARGET_H) cgraph.h intl.h
|
||||
coverage.o : coverage.c gcov-io.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
$(TM_H) $(RTL_H) $(TREE_H) flags.h output.h $(REGS_H) $(EXPR_H) function.h \
|
||||
toplev.h $(GGC_H) $(TARGET_H) langhooks.h $(COVERAGE_H) libfuncs.h \
|
||||
|
15
gcc/cgraph.c
15
gcc/cgraph.c
@ -34,6 +34,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "cgraph.h"
|
||||
#include "varray.h"
|
||||
#include "output.h"
|
||||
#include "intl.h"
|
||||
|
||||
|
||||
/* Hash table used to convert declarations into nodes. */
|
||||
@ -156,7 +157,13 @@ create_edge (struct cgraph_node *caller, struct cgraph_node *callee)
|
||||
struct cgraph_edge *edge = ggc_alloc (sizeof (struct cgraph_edge));
|
||||
struct cgraph_edge *edge2;
|
||||
|
||||
edge->inline_call = false;
|
||||
if (!DECL_SAVED_TREE (callee->decl))
|
||||
edge->inline_failed = N_("function body not available");
|
||||
else if (callee->local.inlinable)
|
||||
edge->inline_failed = N_("function not considered for inlining");
|
||||
else
|
||||
edge->inline_failed = N_("function not inlinable");
|
||||
|
||||
/* At the moment we don't associate calls with specific CALL_EXPRs
|
||||
as we probably ought to, so we must preserve inline_call flags to
|
||||
be the same in all copies of the same edge. */
|
||||
@ -164,7 +171,7 @@ create_edge (struct cgraph_node *caller, struct cgraph_node *callee)
|
||||
for (edge2 = caller->callees; edge2; edge2 = edge2->next_callee)
|
||||
if (edge2->callee == callee)
|
||||
{
|
||||
edge->inline_call = edge2->inline_call;
|
||||
edge->inline_failed = edge2->inline_failed;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -381,7 +388,7 @@ dump_cgraph (FILE *f)
|
||||
for (edge = node->callers; edge; edge = edge->next_caller)
|
||||
{
|
||||
fprintf (f, "%s ", cgraph_node_name (edge->caller));
|
||||
if (edge->inline_call)
|
||||
if (!edge->inline_failed)
|
||||
fprintf(f, "(inlined) ");
|
||||
}
|
||||
|
||||
@ -389,7 +396,7 @@ dump_cgraph (FILE *f)
|
||||
for (edge = node->callees; edge; edge = edge->next_callee)
|
||||
{
|
||||
fprintf (f, "%s ", cgraph_node_name (edge->callee));
|
||||
if (edge->inline_call)
|
||||
if (!edge->inline_failed)
|
||||
fprintf(f, "(inlined) ");
|
||||
}
|
||||
fprintf (f, "\n");
|
||||
|
@ -119,7 +119,9 @@ struct cgraph_edge GTY(())
|
||||
struct cgraph_node *callee;
|
||||
struct cgraph_edge *next_caller;
|
||||
struct cgraph_edge *next_callee;
|
||||
bool inline_call;
|
||||
/* When NULL, inline this call. When non-NULL, points to the explanation
|
||||
why function was not inlined. */
|
||||
const char *inline_failed;
|
||||
};
|
||||
|
||||
/* The cgraph_varpool data structure.
|
||||
@ -181,6 +183,6 @@ void cgraph_create_edges (tree, tree);
|
||||
void cgraph_optimize (void);
|
||||
void cgraph_mark_needed_node (struct cgraph_node *);
|
||||
void cgraph_mark_reachable_node (struct cgraph_node *);
|
||||
bool cgraph_inline_p (tree, tree);
|
||||
bool cgraph_inline_p (tree, tree, const char **reason);
|
||||
|
||||
#endif /* GCC_CGRAPH_H */
|
||||
|
171
gcc/cgraphunit.c
171
gcc/cgraphunit.c
@ -38,6 +38,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "params.h"
|
||||
#include "fibheap.h"
|
||||
#include "c-common.h"
|
||||
#include "intl.h"
|
||||
|
||||
#define INSNS_PER_CALL 10
|
||||
|
||||
@ -257,8 +258,6 @@ record_call_1 (tree *tp, int *walk_subtrees, void *data)
|
||||
tree decl = get_callee_fndecl (*tp);
|
||||
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
|
||||
{
|
||||
if (DECL_BUILT_IN (decl))
|
||||
return NULL;
|
||||
cgraph_record_call (data, decl);
|
||||
|
||||
/* When we see a function call, we don't want to look at the
|
||||
@ -311,6 +310,7 @@ static void
|
||||
cgraph_analyze_function (struct cgraph_node *node)
|
||||
{
|
||||
tree decl = node->decl;
|
||||
struct cgraph_edge *e;
|
||||
|
||||
current_function_decl = decl;
|
||||
|
||||
@ -325,6 +325,10 @@ cgraph_analyze_function (struct cgraph_node *node)
|
||||
if (node->local.inlinable)
|
||||
node->local.disregard_inline_limits
|
||||
= (*lang_hooks.tree_inlining.disregard_inline_limits) (decl);
|
||||
for (e = node->callers; e; e = e->next_caller)
|
||||
if (e->inline_failed)
|
||||
e->inline_failed = (!node->local.inlinable ? N_("function not inlinable")
|
||||
: N_("function not considered for inlining"));
|
||||
if (flag_really_no_inline && !node->local.disregard_inline_limits)
|
||||
node->local.inlinable = 0;
|
||||
/* Inlining characteristics are maintained by the cgraph_mark_inline. */
|
||||
@ -442,11 +446,12 @@ cgraph_mark_functions_to_output (void)
|
||||
{
|
||||
tree decl = node->decl;
|
||||
struct cgraph_edge *e;
|
||||
|
||||
if (node->output)
|
||||
abort ();
|
||||
|
||||
for (e = node->callers; e; e = e->next_caller)
|
||||
if (!e->inline_call)
|
||||
if (e->inline_failed)
|
||||
break;
|
||||
|
||||
/* We need to output all local functions that are used and not
|
||||
@ -476,7 +481,7 @@ cgraph_optimize_function (struct cgraph_node *node)
|
||||
struct cgraph_edge *e;
|
||||
|
||||
for (e = node->callees; e; e = e->next_callee)
|
||||
if (e->inline_call || warn_inline)
|
||||
if (!e->inline_failed || warn_inline)
|
||||
break;
|
||||
if (e)
|
||||
optimize_inline_calls (decl);
|
||||
@ -512,6 +517,7 @@ cgraph_expand_function (struct cgraph_node *node)
|
||||
|
||||
/* Fill array order with all nodes with output flag set in the reverse
|
||||
topological order. */
|
||||
|
||||
static int
|
||||
cgraph_postorder (struct cgraph_node **order)
|
||||
{
|
||||
@ -594,7 +600,7 @@ cgraph_inlined_into (struct cgraph_node *node, struct cgraph_node **array)
|
||||
/* Fast path: since we traverse in mostly topological order, we will likely
|
||||
find no edges. */
|
||||
for (e = node->callers; e; e = e->next_caller)
|
||||
if (e->inline_call)
|
||||
if (!e->inline_failed)
|
||||
break;
|
||||
|
||||
if (!e)
|
||||
@ -626,8 +632,9 @@ cgraph_inlined_into (struct cgraph_node *node, struct cgraph_node **array)
|
||||
SET_INLINED_TIMES (caller, INLINED_TIMES (caller) + 1);
|
||||
|
||||
for (e1 = caller->callers; e1; e1 = e1->next_caller)
|
||||
if (e1->inline_call)
|
||||
if (!e1->inline_failed)
|
||||
break;
|
||||
|
||||
if (e1)
|
||||
stack[sp++] = e1;
|
||||
else
|
||||
@ -635,7 +642,7 @@ cgraph_inlined_into (struct cgraph_node *node, struct cgraph_node **array)
|
||||
while (true)
|
||||
{
|
||||
for (e1 = e->next_caller; e1; e1 = e1->next_caller)
|
||||
if (e1->inline_call)
|
||||
if (!e1->inline_failed)
|
||||
break;
|
||||
|
||||
if (e1)
|
||||
@ -692,7 +699,7 @@ cgraph_inlined_callees (struct cgraph_node *node, struct cgraph_node **array)
|
||||
/* Fast path: since we traverse in mostly topological order, we will likely
|
||||
find no edges. */
|
||||
for (e = node->callees; e; e = e->next_callee)
|
||||
if (e->inline_call)
|
||||
if (!e->inline_failed)
|
||||
break;
|
||||
|
||||
if (!e)
|
||||
@ -724,7 +731,7 @@ cgraph_inlined_callees (struct cgraph_node *node, struct cgraph_node **array)
|
||||
SET_INLINED_TIMES (callee, INLINED_TIMES (callee) + 1);
|
||||
|
||||
for (e1 = callee->callees; e1; e1 = e1->next_callee)
|
||||
if (e1->inline_call)
|
||||
if (!e1->inline_failed)
|
||||
break;
|
||||
if (e1)
|
||||
stack[sp++] = e1;
|
||||
@ -733,7 +740,7 @@ cgraph_inlined_callees (struct cgraph_node *node, struct cgraph_node **array)
|
||||
while (true)
|
||||
{
|
||||
for (e1 = e->next_callee; e1; e1 = e1->next_callee)
|
||||
if (e1->inline_call)
|
||||
if (!e1->inline_failed)
|
||||
break;
|
||||
|
||||
if (e1)
|
||||
@ -791,7 +798,7 @@ cgraph_estimate_growth (struct cgraph_node *node)
|
||||
struct cgraph_edge *e;
|
||||
|
||||
for (e = node->callers; e; e = e->next_caller)
|
||||
if (!e->inline_call)
|
||||
if (e->inline_failed)
|
||||
{
|
||||
growth += ((cgraph_estimate_size_after_inlining (1, e->caller, node)
|
||||
-
|
||||
@ -833,13 +840,13 @@ cgraph_mark_inline (struct cgraph_node *to, struct cgraph_node *what,
|
||||
{
|
||||
if (e->caller == to)
|
||||
{
|
||||
if (e->inline_call)
|
||||
abort ();
|
||||
e->inline_call = true;
|
||||
if (!e->inline_failed)
|
||||
continue;
|
||||
e->inline_failed = NULL;
|
||||
times++;
|
||||
clones += e->caller->global.cloned_times;
|
||||
}
|
||||
else if (!e->inline_call)
|
||||
else if (e->inline_failed)
|
||||
called = true;
|
||||
}
|
||||
if (!times)
|
||||
@ -884,7 +891,8 @@ cgraph_mark_inline (struct cgraph_node *to, struct cgraph_node *what,
|
||||
|
||||
static bool
|
||||
cgraph_check_inline_limits (struct cgraph_node *to, struct cgraph_node *what,
|
||||
struct cgraph_node **inlined, int ninlined)
|
||||
struct cgraph_node **inlined, int ninlined,
|
||||
const char **reason)
|
||||
{
|
||||
int i;
|
||||
int times = 0;
|
||||
@ -908,7 +916,10 @@ cgraph_check_inline_limits (struct cgraph_node *to, struct cgraph_node *what,
|
||||
newsize = cgraph_estimate_size_after_inlining (times, to, what);
|
||||
if (newsize > PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS)
|
||||
&& newsize > limit)
|
||||
return false;
|
||||
{
|
||||
*reason = N_("--param large-function-growth limit reached");
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < ninlined; i++)
|
||||
{
|
||||
newsize =
|
||||
@ -918,7 +929,10 @@ cgraph_check_inline_limits (struct cgraph_node *to, struct cgraph_node *what,
|
||||
&& newsize >
|
||||
inlined[i]->local.self_insns *
|
||||
(100 + PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH)) / 100)
|
||||
return false;
|
||||
{
|
||||
*reason = N_("--param large-function-growth limit reached while inlining the caller");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -936,6 +950,20 @@ cgraph_default_inline_p (struct cgraph_node *n)
|
||||
return n->global.insns < MAX_INLINE_INSNS_AUTO;
|
||||
}
|
||||
|
||||
/* Set inline_failed for all callers of given function to REASON. */
|
||||
|
||||
static void
|
||||
cgraph_set_inline_failed (struct cgraph_node *node, const char *reason)
|
||||
{
|
||||
struct cgraph_edge *e;
|
||||
|
||||
if (cgraph_dump_file)
|
||||
fprintf (cgraph_dump_file, "Inlining failed: %s\n", reason);
|
||||
for (e = node->callers; e; e = e->next_caller)
|
||||
if (e->inline_failed)
|
||||
e->inline_failed = reason;
|
||||
}
|
||||
|
||||
/* We use greedy algorithm for inlining of small functions:
|
||||
All inline candidates are put into prioritized heap based on estimated
|
||||
growth of the overall number of instructions and then update the estimates.
|
||||
@ -960,25 +988,23 @@ cgraph_decide_inlining_of_small_functions (struct cgraph_node **inlined,
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
struct cgraph_edge *e;
|
||||
|
||||
if (!node->local.inlinable || !node->callers
|
||||
|| !cgraph_default_inline_p (node))
|
||||
|| node->local.disregard_inline_limits)
|
||||
continue;
|
||||
|
||||
/* Rule out always_inline functions we dealt with earlier. */
|
||||
for (e = node->callers; e; e = e->next_caller)
|
||||
if (e->inline_call)
|
||||
break;
|
||||
if (e)
|
||||
continue;
|
||||
if (!cgraph_default_inline_p (node))
|
||||
{
|
||||
cgraph_set_inline_failed (node,
|
||||
N_("--param max-inline-insns-single limit reached"));
|
||||
continue;
|
||||
}
|
||||
heap_node[node->uid] =
|
||||
fibheap_insert (heap, cgraph_estimate_growth (node), node);
|
||||
}
|
||||
|
||||
if (cgraph_dump_file)
|
||||
fprintf (cgraph_dump_file, "\nDeciding on smaller functions:\n");
|
||||
while ((node = fibheap_extract_min (heap)) && overall_insns <= max_insns)
|
||||
while (overall_insns <= max_insns && (node = fibheap_extract_min (heap)))
|
||||
{
|
||||
struct cgraph_edge *e;
|
||||
int old_insns = overall_insns;
|
||||
@ -992,18 +1018,27 @@ cgraph_decide_inlining_of_small_functions (struct cgraph_node **inlined,
|
||||
cgraph_estimate_growth (node));
|
||||
if (!cgraph_default_inline_p (node))
|
||||
{
|
||||
if (cgraph_dump_file)
|
||||
fprintf (cgraph_dump_file, " Function too large.\n");
|
||||
cgraph_set_inline_failed (node,
|
||||
N_("--param max-inline-insns-single limit reached after inlining into the callee"));
|
||||
continue;
|
||||
}
|
||||
ninlined_callees = cgraph_inlined_callees (node, inlined_callees);
|
||||
for (e = node->callers; e; e = e->next_caller)
|
||||
if (!e->inline_call && e->caller != node)
|
||||
if (e->inline_failed)
|
||||
{
|
||||
/* Marking recursive function inlinine has sane semantic and
|
||||
thus we should not warn on it. */
|
||||
if (e->caller == node)
|
||||
{
|
||||
e->inline_failed = "";
|
||||
continue;
|
||||
}
|
||||
ninlined = cgraph_inlined_into (e->caller, inlined);
|
||||
if (e->callee->output)
|
||||
e->inline_failed = "";
|
||||
if (e->callee->output
|
||||
|| !cgraph_check_inline_limits (e->caller, node, inlined,
|
||||
ninlined))
|
||||
ninlined, &e->inline_failed))
|
||||
{
|
||||
for (i = 0; i < ninlined; i++)
|
||||
inlined[i]->output = 0, node->aux = 0;
|
||||
@ -1039,7 +1074,7 @@ cgraph_decide_inlining_of_small_functions (struct cgraph_node **inlined,
|
||||
are now called more times; update keys. */
|
||||
|
||||
for (e = node->callees; e; e = e->next_callee)
|
||||
if (!e->inline_call && heap_node[e->callee->uid])
|
||||
if (e->inline_failed && heap_node[e->callee->uid])
|
||||
fibheap_replace_key (heap, heap_node[e->callee->uid],
|
||||
cgraph_estimate_growth (e->callee));
|
||||
|
||||
@ -1048,7 +1083,7 @@ cgraph_decide_inlining_of_small_functions (struct cgraph_node **inlined,
|
||||
struct cgraph_edge *e;
|
||||
|
||||
for (e = inlined_callees[i]->callees; e; e = e->next_callee)
|
||||
if (!e->inline_call && heap_node[e->callee->uid])
|
||||
if (e->inline_failed && heap_node[e->callee->uid])
|
||||
fibheap_replace_key (heap, heap_node[e->callee->uid],
|
||||
cgraph_estimate_growth (e->callee));
|
||||
|
||||
@ -1059,8 +1094,9 @@ cgraph_decide_inlining_of_small_functions (struct cgraph_node **inlined,
|
||||
" Inlined %i times for a net change of %+i insns.\n",
|
||||
node->global.cloned_times, overall_insns - old_insns);
|
||||
}
|
||||
if (cgraph_dump_file && !fibheap_empty (heap))
|
||||
fprintf (cgraph_dump_file, "\nReached the inline-unit-growth limit.\n");
|
||||
while ((node = fibheap_extract_min (heap)) != NULL)
|
||||
if (!node->local.disregard_inline_limits)
|
||||
cgraph_set_inline_failed (node, N_("--param inline-unit-growth limit reached"));
|
||||
fibheap_delete (heap);
|
||||
free (heap_node);
|
||||
}
|
||||
@ -1122,10 +1158,14 @@ cgraph_decide_inlining (void)
|
||||
for (; e; e = e->next_callee)
|
||||
{
|
||||
old_insns = overall_insns;
|
||||
if (e->inline_call || !e->callee->local.disregard_inline_limits)
|
||||
continue;
|
||||
if (e->callee->output || e->callee == node)
|
||||
continue;
|
||||
if (!e->inline_failed || !e->callee->local.inlinable
|
||||
|| !e->callee->local.disregard_inline_limits)
|
||||
continue;
|
||||
if (e->callee->output || e->callee == node)
|
||||
{
|
||||
e->inline_failed = N_("recursive inlining");
|
||||
continue;
|
||||
}
|
||||
ninlined_callees =
|
||||
cgraph_inlined_callees (e->callee, inlined_callees);
|
||||
cgraph_mark_inline (node, e->callee, inlined, ninlined,
|
||||
@ -1160,7 +1200,7 @@ cgraph_decide_inlining (void)
|
||||
node = order[i];
|
||||
|
||||
if (node->callers && !node->callers->next_caller && !node->needed
|
||||
&& node->local.inlinable && !node->callers->inline_call
|
||||
&& node->local.inlinable && node->callers->inline_failed
|
||||
&& !DECL_EXTERNAL (node->decl) && !DECL_COMDAT (node->decl))
|
||||
{
|
||||
bool ok = true;
|
||||
@ -1168,12 +1208,13 @@ cgraph_decide_inlining (void)
|
||||
|
||||
/* Verify that we won't duplicate the caller. */
|
||||
for (node1 = node->callers->caller;
|
||||
node1->callers && node1->callers->inline_call
|
||||
node1->callers && node1->callers->inline_failed
|
||||
&& ok; node1 = node1->callers->caller)
|
||||
if (node1->callers->next_caller || node1->needed)
|
||||
ok = false;
|
||||
if (ok)
|
||||
{
|
||||
const char *dummy_reason;
|
||||
if (cgraph_dump_file)
|
||||
fprintf (cgraph_dump_file,
|
||||
"\nConsidering %s %i insns.\n"
|
||||
@ -1184,8 +1225,11 @@ cgraph_decide_inlining (void)
|
||||
ninlined = cgraph_inlined_into (node->callers->caller,
|
||||
inlined);
|
||||
old_insns = overall_insns;
|
||||
|
||||
/* Inlining functions once would never cause inlining warnings. */
|
||||
if (cgraph_check_inline_limits
|
||||
(node->callers->caller, node, inlined, ninlined))
|
||||
(node->callers->caller, node, inlined, ninlined,
|
||||
&dummy_reason))
|
||||
{
|
||||
ninlined_callees =
|
||||
cgraph_inlined_callees (node, inlined_callees);
|
||||
@ -1245,9 +1289,16 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node)
|
||||
|
||||
/* 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)
|
||||
if (e->callee->local.disregard_inline_limits && e->inline_failed
|
||||
/* ??? It is possible that renaming variable removed the function body
|
||||
in duplicate_decls. See gcc.c-torture/compile/20011119-2.c */
|
||||
&& DECL_SAVED_TREE (e->callee->decl))
|
||||
{
|
||||
if (e->callee->output || e->callee == node)
|
||||
{
|
||||
e->inline_failed = N_("recursive inlining");
|
||||
continue;
|
||||
}
|
||||
ninlined_callees = cgraph_inlined_callees (e->callee, inlined_callees);
|
||||
cgraph_mark_inline (node, e->callee, inlined, ninlined,
|
||||
inlined_callees, ninlined_callees);
|
||||
@ -1259,12 +1310,19 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node)
|
||||
{
|
||||
/* 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
|
||||
if (e->callee->local.inlinable && e->inline_failed
|
||||
&& cgraph_default_inline_p (e->callee)
|
||||
&& cgraph_check_inline_limits (node, e->callee, inlined,
|
||||
ninlined))
|
||||
ninlined, &e->inline_failed)
|
||||
&& DECL_SAVED_TREE (e->callee->decl))
|
||||
{
|
||||
/* Marking recursive function inlinine has sane semantic and thus
|
||||
we should not warn on it. */
|
||||
if (e->callee->output || e->callee == node)
|
||||
{
|
||||
e->inline_failed = "";
|
||||
continue;
|
||||
}
|
||||
ninlined_callees = cgraph_inlined_callees (e->callee,
|
||||
inlined_callees);
|
||||
cgraph_mark_inline (node, e->callee, inlined, ninlined,
|
||||
@ -1283,10 +1341,12 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node)
|
||||
}
|
||||
|
||||
|
||||
/* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */
|
||||
/* Return true when CALLER_DECL should be inlined into CALLEE_DECL.
|
||||
When returned false and reason is non-NULL, set it to the reason
|
||||
why the call was not inlined. */
|
||||
|
||||
bool
|
||||
cgraph_inline_p (tree caller_decl, tree callee_decl)
|
||||
cgraph_inline_p (tree caller_decl, tree callee_decl, const char **reason)
|
||||
{
|
||||
struct cgraph_node *caller = cgraph_node (caller_decl);
|
||||
struct cgraph_node *callee = cgraph_node (callee_decl);
|
||||
@ -1294,10 +1354,16 @@ cgraph_inline_p (tree caller_decl, tree callee_decl)
|
||||
|
||||
for (e = caller->callees; e; e = e->next_callee)
|
||||
if (e->callee == callee)
|
||||
return e->inline_call;
|
||||
{
|
||||
if (e->inline_failed && reason)
|
||||
*reason = e->inline_failed;
|
||||
return !e->inline_failed;
|
||||
}
|
||||
/* We do not record builtins in the callgraph. Perhaps it would make more
|
||||
sense to do so and then prune out those not overwritten by explicit
|
||||
function body. */
|
||||
if (reason)
|
||||
*reason = "originally indirect function calls never inlined";
|
||||
return false;
|
||||
}
|
||||
/* Expand all functions that must be output.
|
||||
@ -1340,7 +1406,8 @@ cgraph_expand_all_functions (void)
|
||||
/* Mark all local functions.
|
||||
|
||||
A local function is one whose calls can occur only in the
|
||||
current compilation unit, so we change its calling convention.
|
||||
current compilation unit and all it's calls are explicit,
|
||||
so we can change its calling convention.
|
||||
We simply mark all static functions whose address is not taken
|
||||
as local. */
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
2004-01-04 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* gcc.dg/winline[1-7].c: New tests.
|
||||
|
||||
2004-01-02 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||
|
||||
PR c++/13520
|
||||
|
13
gcc/testsuite/gcc.dg/winline-1.c
Normal file
13
gcc/testsuite/gcc.dg/winline-1.c
Normal file
@ -0,0 +1,13 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Winline -O2" } */
|
||||
|
||||
void q(void);
|
||||
inline int t(void)
|
||||
{
|
||||
int ret;
|
||||
q();
|
||||
ret = t(); /* We define sane semantics for inline keyword on recursive
|
||||
functions, so do not warn here. */
|
||||
q();
|
||||
return ret;
|
||||
}
|
8
gcc/testsuite/gcc.dg/winline-2.c
Normal file
8
gcc/testsuite/gcc.dg/winline-2.c
Normal file
@ -0,0 +1,8 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Winline -O2" } */
|
||||
|
||||
inline int q(void); /* { dg-warning "body not available" "" } */
|
||||
inline int t(void)
|
||||
{
|
||||
return q(); /* { dg-warning "called from here" "" } */
|
||||
}
|
21
gcc/testsuite/gcc.dg/winline-3.c
Normal file
21
gcc/testsuite/gcc.dg/winline-3.c
Normal file
@ -0,0 +1,21 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Winline -O2 --param max-inline-insns-single=1" } */
|
||||
|
||||
void big (void);
|
||||
inline int q(void)
|
||||
{ /* { dg-warning "max-inline-insns-single" "" } */
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
}
|
||||
inline int t (void)
|
||||
{
|
||||
return q (); /* { dg-warning "called from here" "" } */
|
||||
}
|
11
gcc/testsuite/gcc.dg/winline-4.c
Normal file
11
gcc/testsuite/gcc.dg/winline-4.c
Normal file
@ -0,0 +1,11 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Winline -O1 -fno-unit-at-a-time" } */
|
||||
|
||||
inline int q(void); /* { dg-warning "body not available" } */
|
||||
inline int t(void)
|
||||
{
|
||||
return q(); /* { dg-warning "called from here" } */
|
||||
}
|
||||
int q(void)
|
||||
{
|
||||
}
|
29
gcc/testsuite/gcc.dg/winline-5.c
Normal file
29
gcc/testsuite/gcc.dg/winline-5.c
Normal file
@ -0,0 +1,29 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Winline -O2 --param inline-unit-growth=0" } */
|
||||
|
||||
void big (void);
|
||||
inline int q(void)
|
||||
{ /* { dg-warning "inline-unit-growth" } */
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
}
|
||||
inline int q1(void)
|
||||
{
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
}
|
||||
int t (void)
|
||||
{
|
||||
/* We allow one inlining over limit. */
|
||||
q1();
|
||||
return q (); /* { dg-warning "called from here" } */
|
||||
}
|
21
gcc/testsuite/gcc.dg/winline-6.c
Normal file
21
gcc/testsuite/gcc.dg/winline-6.c
Normal file
@ -0,0 +1,21 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Winline -O2 --param large-function-growth=0 --param large-function-insns=1" } */
|
||||
|
||||
void big (void);
|
||||
inline int q(void)
|
||||
{ /* { dg-warning "large-function-growth" } */
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
big();
|
||||
}
|
||||
inline int t (void)
|
||||
{
|
||||
return q (); /* { dg-warning "called from here" } */
|
||||
}
|
12
gcc/testsuite/gcc.dg/winline-7.c
Normal file
12
gcc/testsuite/gcc.dg/winline-7.c
Normal file
@ -0,0 +1,12 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Winline -O2" } */
|
||||
|
||||
void big (void);
|
||||
inline int q(void)
|
||||
{ /* { dg-warning "(function not inlinable|alloca)" } */
|
||||
return (int)alloca(10);
|
||||
}
|
||||
inline int t (void)
|
||||
{
|
||||
return q (); /* { dg-warning "called from here" } */
|
||||
}
|
@ -1247,6 +1247,7 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
|
||||
splay_tree st;
|
||||
tree args;
|
||||
tree return_slot_addr;
|
||||
const char *reason;
|
||||
|
||||
/* See what we've got. */
|
||||
id = (inline_data *) data;
|
||||
@ -1327,12 +1328,13 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
|
||||
|
||||
/* Don't try to inline functions that are not well-suited to
|
||||
inlining. */
|
||||
if (!DECL_SAVED_TREE (fn) || !cgraph_inline_p (id->current_decl, fn))
|
||||
if (!cgraph_inline_p (id->current_decl, fn, &reason))
|
||||
{
|
||||
if (warn_inline && DECL_INLINE (fn) && DECL_DECLARED_INLINE_P (fn)
|
||||
&& !DECL_IN_SYSTEM_HEADER (fn))
|
||||
if (warn_inline && DECL_DECLARED_INLINE_P (fn)
|
||||
&& !DECL_IN_SYSTEM_HEADER (fn)
|
||||
&& strlen (reason))
|
||||
{
|
||||
warning ("%Jinlining failed in call to '%F'", fn, fn);
|
||||
warning ("%Jinlining failed in call to '%F': %s", fn, fn, reason);
|
||||
warning ("called from here");
|
||||
}
|
||||
return NULL_TREE;
|
||||
|
Loading…
Reference in New Issue
Block a user