Updated version of -Winline warnings patch
Jan Hubicka
jh@suse.cz
Sat Jan 3 16:53:00 GMT 2004
Hi,
I've managed to forget to commit the patch for proper -Winline warning. Since
this is a regression relative to older GCC versions that used to produce
usefull messages, I've updated the patch and will commit it tomorrow. I will
also prepare tree-ssa branch version.
Bootstrapped/regtested i686-pc-gnu-linux
Honza
/* { 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 keywork on recursive
functions, so do not warn here. */
q();
return ret;
}
/* { 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" "" } */
}
/* { 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" "" } */
}
/* { 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)
{
}
/* { 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" } */
}
/* { 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" } */
}
Tue Sep 9 18:50:42 CEST 2003 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.
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1213
diff -c -3 -p -r1.1213 Makefile.in
*** Makefile.in 30 Dec 2003 10:40:46 -0000 1.1213
--- Makefile.in 3 Jan 2004 12:23:27 -0000
*************** simplify-rtx.o : simplify-rtx.c $(CONFIG
*** 1633,1641 ****
$(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
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
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 \
--- 1633,1642 ----
$(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 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 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 \
Index: cgraph.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.c,v
retrieving revision 1.39
diff -c -3 -p -r1.39 cgraph.c
*** cgraph.c 1 Jan 2004 13:58:56 -0000 1.39
--- cgraph.c 3 Jan 2004 12:23:35 -0000
*************** Software Foundation, 59 Temple Place - S
*** 34,39 ****
--- 34,40 ----
#include "cgraph.h"
#include "varray.h"
#include "output.h"
+ #include "intl.h"
/* Hash table used to convert declarations into nodes. */
*************** create_edge (struct cgraph_node *caller,
*** 156,162 ****
struct cgraph_edge *edge = ggc_alloc (sizeof (struct cgraph_edge));
struct cgraph_edge *edge2;
! edge->inline_call = false;
/* 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. */
--- 157,169 ----
struct cgraph_edge *edge = ggc_alloc (sizeof (struct cgraph_edge));
struct cgraph_edge *edge2;
! 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. */
*************** create_edge (struct cgraph_node *caller,
*** 164,170 ****
for (edge2 = caller->callees; edge2; edge2 = edge2->next_callee)
if (edge2->callee == callee)
{
! edge->inline_call = edge2->inline_call;
break;
}
--- 171,177 ----
for (edge2 = caller->callees; edge2; edge2 = edge2->next_callee)
if (edge2->callee == callee)
{
! edge->inline_failed = edge2->inline_failed;
break;
}
*************** dump_cgraph (FILE *f)
*** 381,387 ****
for (edge = node->callers; edge; edge = edge->next_caller)
{
fprintf (f, "%s ", cgraph_node_name (edge->caller));
! if (edge->inline_call)
fprintf(f, "(inlined) ");
}
--- 388,394 ----
for (edge = node->callers; edge; edge = edge->next_caller)
{
fprintf (f, "%s ", cgraph_node_name (edge->caller));
! if (!edge->inline_failed)
fprintf(f, "(inlined) ");
}
*************** dump_cgraph (FILE *f)
*** 389,395 ****
for (edge = node->callees; edge; edge = edge->next_callee)
{
fprintf (f, "%s ", cgraph_node_name (edge->callee));
! if (edge->inline_call)
fprintf(f, "(inlined) ");
}
fprintf (f, "\n");
--- 396,402 ----
for (edge = node->callees; edge; edge = edge->next_callee)
{
fprintf (f, "%s ", cgraph_node_name (edge->callee));
! if (!edge->inline_failed)
fprintf(f, "(inlined) ");
}
fprintf (f, "\n");
Index: cgraph.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.h,v
retrieving revision 1.24
diff -c -3 -p -r1.24 cgraph.h
*** cgraph.h 13 Dec 2003 04:11:19 -0000 1.24
--- cgraph.h 3 Jan 2004 12:23:35 -0000
*************** struct cgraph_edge GTY(())
*** 119,125 ****
struct cgraph_node *callee;
struct cgraph_edge *next_caller;
struct cgraph_edge *next_callee;
! bool inline_call;
};
/* The cgraph_varpool data structure.
--- 119,127 ----
struct cgraph_node *callee;
struct cgraph_edge *next_caller;
struct cgraph_edge *next_callee;
! /* 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.
*************** void cgraph_create_edges (tree, tree);
*** 181,186 ****
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);
#endif /* GCC_CGRAPH_H */
--- 183,188 ----
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, const char **reason);
#endif /* GCC_CGRAPH_H */
Index: cgraphunit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraphunit.c,v
retrieving revision 1.41
diff -c -3 -p -r1.41 cgraphunit.c
*** cgraphunit.c 2 Jan 2004 18:06:16 -0000 1.41
--- cgraphunit.c 3 Jan 2004 12:23:35 -0000
*************** Software Foundation, 59 Temple Place - S
*** 38,43 ****
--- 38,44 ----
#include "params.h"
#include "fibheap.h"
#include "c-common.h"
+ #include "intl.h"
#define INSNS_PER_CALL 10
*************** record_call_1 (tree *tp, int *walk_subtr
*** 257,264 ****
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
--- 258,263 ----
*************** static void
*** 311,316 ****
--- 310,316 ----
cgraph_analyze_function (struct cgraph_node *node)
{
tree decl = node->decl;
+ struct cgraph_edge *e;
current_function_decl = decl;
*************** cgraph_analyze_function (struct cgraph_n
*** 325,330 ****
--- 325,334 ----
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. */
*************** cgraph_mark_functions_to_output (void)
*** 442,452 ****
{
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)
break;
/* We need to output all local functions that are used and not
--- 446,457 ----
{
tree decl = node->decl;
struct cgraph_edge *e;
+
if (node->output)
abort ();
for (e = node->callers; e; e = e->next_caller)
! if (e->inline_failed)
break;
/* We need to output all local functions that are used and not
*************** cgraph_optimize_function (struct cgraph_
*** 476,482 ****
struct cgraph_edge *e;
for (e = node->callees; e; e = e->next_callee)
! if (e->inline_call || warn_inline)
break;
if (e)
optimize_inline_calls (decl);
--- 481,487 ----
struct cgraph_edge *e;
for (e = node->callees; e; e = e->next_callee)
! if (!e->inline_failed || warn_inline)
break;
if (e)
optimize_inline_calls (decl);
*************** cgraph_expand_function (struct cgraph_no
*** 512,517 ****
--- 517,523 ----
/* Fill array order with all nodes with output flag set in the reverse
topological order. */
+
static int
cgraph_postorder (struct cgraph_node **order)
{
*************** cgraph_inlined_into (struct cgraph_node
*** 594,600 ****
/* 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)
break;
if (!e)
--- 600,606 ----
/* 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_failed)
break;
if (!e)
*************** cgraph_inlined_into (struct cgraph_node
*** 626,633 ****
SET_INLINED_TIMES (caller, INLINED_TIMES (caller) + 1);
for (e1 = caller->callers; e1; e1 = e1->next_caller)
! if (e1->inline_call)
break;
if (e1)
stack[sp++] = e1;
else
--- 632,640 ----
SET_INLINED_TIMES (caller, INLINED_TIMES (caller) + 1);
for (e1 = caller->callers; e1; e1 = e1->next_caller)
! if (!e1->inline_failed)
break;
+
if (e1)
stack[sp++] = e1;
else
*************** cgraph_inlined_into (struct cgraph_node
*** 635,641 ****
while (true)
{
for (e1 = e->next_caller; e1; e1 = e1->next_caller)
! if (e1->inline_call)
break;
if (e1)
--- 642,648 ----
while (true)
{
for (e1 = e->next_caller; e1; e1 = e1->next_caller)
! if (!e1->inline_failed)
break;
if (e1)
*************** cgraph_inlined_callees (struct cgraph_no
*** 692,698 ****
/* 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)
break;
if (!e)
--- 699,705 ----
/* 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_failed)
break;
if (!e)
*************** cgraph_inlined_callees (struct cgraph_no
*** 724,730 ****
SET_INLINED_TIMES (callee, INLINED_TIMES (callee) + 1);
for (e1 = callee->callees; e1; e1 = e1->next_callee)
! if (e1->inline_call)
break;
if (e1)
stack[sp++] = e1;
--- 731,737 ----
SET_INLINED_TIMES (callee, INLINED_TIMES (callee) + 1);
for (e1 = callee->callees; e1; e1 = e1->next_callee)
! if (!e1->inline_failed)
break;
if (e1)
stack[sp++] = e1;
*************** cgraph_inlined_callees (struct cgraph_no
*** 733,739 ****
while (true)
{
for (e1 = e->next_callee; e1; e1 = e1->next_callee)
! if (e1->inline_call)
break;
if (e1)
--- 740,746 ----
while (true)
{
for (e1 = e->next_callee; e1; e1 = e1->next_callee)
! if (!e1->inline_failed)
break;
if (e1)
*************** cgraph_estimate_growth (struct cgraph_no
*** 791,797 ****
struct cgraph_edge *e;
for (e = node->callers; e; e = e->next_caller)
! if (!e->inline_call)
{
growth += ((cgraph_estimate_size_after_inlining (1, e->caller, node)
-
--- 798,804 ----
struct cgraph_edge *e;
for (e = node->callers; e; e = e->next_caller)
! if (e->inline_failed)
{
growth += ((cgraph_estimate_size_after_inlining (1, e->caller, node)
-
*************** cgraph_mark_inline (struct cgraph_node *
*** 833,845 ****
{
if (e->caller == to)
{
! if (e->inline_call)
! abort ();
! e->inline_call = true;
times++;
clones += e->caller->global.cloned_times;
}
! else if (!e->inline_call)
called = true;
}
if (!times)
--- 840,852 ----
{
if (e->caller == to)
{
! if (!e->inline_failed)
! continue;
! e->inline_failed = NULL;
times++;
clones += e->caller->global.cloned_times;
}
! else if (e->inline_failed)
called = true;
}
if (!times)
*************** cgraph_mark_inline (struct cgraph_node *
*** 884,890 ****
static bool
cgraph_check_inline_limits (struct cgraph_node *to, struct cgraph_node *what,
! struct cgraph_node **inlined, int ninlined)
{
int i;
int times = 0;
--- 891,898 ----
static bool
cgraph_check_inline_limits (struct cgraph_node *to, struct cgraph_node *what,
! struct cgraph_node **inlined, int ninlined,
! const char **reason)
{
int i;
int times = 0;
*************** cgraph_check_inline_limits (struct cgrap
*** 908,914 ****
newsize = cgraph_estimate_size_after_inlining (times, to, what);
if (newsize > PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS)
&& newsize > limit)
! return false;
for (i = 0; i < ninlined; i++)
{
newsize =
--- 916,925 ----
newsize = cgraph_estimate_size_after_inlining (times, to, what);
if (newsize > PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS)
&& newsize > limit)
! {
! *reason = N_("--param large-function-growth limit reached");
! return false;
! }
for (i = 0; i < ninlined; i++)
{
newsize =
*************** cgraph_check_inline_limits (struct cgrap
*** 918,924 ****
&& newsize >
inlined[i]->local.self_insns *
(100 + PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH)) / 100)
! return false;
}
return true;
}
--- 929,938 ----
&& newsize >
inlined[i]->local.self_insns *
(100 + PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH)) / 100)
! {
! *reason = N_("--param large-function-growth limit reached while inlining the caller");
! return false;
! }
}
return true;
}
*************** cgraph_default_inline_p (struct cgraph_n
*** 936,941 ****
--- 950,969 ----
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.
*************** cgraph_decide_inlining_of_small_function
*** 960,984 ****
for (node = cgraph_nodes; node; node = node->next)
{
- struct cgraph_edge *e;
-
if (!node->local.inlinable || !node->callers
! || !cgraph_default_inline_p (node))
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;
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)
{
struct cgraph_edge *e;
int old_insns = overall_insns;
--- 988,1010 ----
for (node = cgraph_nodes; node; node = node->next)
{
if (!node->local.inlinable || !node->callers
! || node->local.disregard_inline_limits)
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 (overall_insns <= max_insns && (node = fibheap_extract_min (heap)))
{
struct cgraph_edge *e;
int old_insns = overall_insns;
*************** cgraph_decide_inlining_of_small_function
*** 992,1009 ****
cgraph_estimate_growth (node));
if (!cgraph_default_inline_p (node))
{
! if (cgraph_dump_file)
! fprintf (cgraph_dump_file, " Function too large.\n");
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)
{
ninlined = cgraph_inlined_into (e->caller, inlined);
if (e->callee->output
|| !cgraph_check_inline_limits (e->caller, node, inlined,
! ninlined))
{
for (i = 0; i < ninlined; i++)
inlined[i]->output = 0, node->aux = 0;
--- 1018,1044 ----
cgraph_estimate_growth (node));
if (!cgraph_default_inline_p (node))
{
! 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_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, &e->inline_failed))
{
for (i = 0; i < ninlined; i++)
inlined[i]->output = 0, node->aux = 0;
*************** cgraph_decide_inlining_of_small_function
*** 1039,1045 ****
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])
fibheap_replace_key (heap, heap_node[e->callee->uid],
cgraph_estimate_growth (e->callee));
--- 1074,1080 ----
are now called more times; update keys. */
for (e = node->callees; e; e = e->next_callee)
! if (e->inline_failed && heap_node[e->callee->uid])
fibheap_replace_key (heap, heap_node[e->callee->uid],
cgraph_estimate_growth (e->callee));
*************** cgraph_decide_inlining_of_small_function
*** 1048,1054 ****
struct cgraph_edge *e;
for (e = inlined_callees[i]->callees; e; e = e->next_callee)
! if (!e->inline_call && heap_node[e->callee->uid])
fibheap_replace_key (heap, heap_node[e->callee->uid],
cgraph_estimate_growth (e->callee));
--- 1083,1089 ----
struct cgraph_edge *e;
for (e = inlined_callees[i]->callees; e; e = e->next_callee)
! if (e->inline_failed && heap_node[e->callee->uid])
fibheap_replace_key (heap, heap_node[e->callee->uid],
cgraph_estimate_growth (e->callee));
*************** cgraph_decide_inlining_of_small_function
*** 1059,1066 ****
" 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");
fibheap_delete (heap);
free (heap_node);
}
--- 1094,1102 ----
" Inlined %i times for a net change of %+i insns.\n",
node->global.cloned_times, overall_insns - old_insns);
}
! 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);
}
*************** cgraph_decide_inlining (void)
*** 1122,1131 ****
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;
ninlined_callees =
cgraph_inlined_callees (e->callee, inlined_callees);
cgraph_mark_inline (node, e->callee, inlined, ninlined,
--- 1158,1171 ----
for (; e; e = e->next_callee)
{
old_insns = overall_insns;
! 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,
*************** cgraph_decide_inlining (void)
*** 1160,1166 ****
node = order[i];
if (node->callers && !node->callers->next_caller && !node->needed
! && node->local.inlinable && !node->callers->inline_call
&& !DECL_EXTERNAL (node->decl) && !DECL_COMDAT (node->decl))
{
bool ok = true;
--- 1200,1206 ----
node = order[i];
if (node->callers && !node->callers->next_caller && !node->needed
! && node->local.inlinable && node->callers->inline_failed
&& !DECL_EXTERNAL (node->decl) && !DECL_COMDAT (node->decl))
{
bool ok = true;
*************** cgraph_decide_inlining (void)
*** 1168,1179 ****
/* Verify that we won't duplicate the caller. */
for (node1 = node->callers->caller;
! node1->callers && node1->callers->inline_call
&& ok; node1 = node1->callers->caller)
if (node1->callers->next_caller || node1->needed)
ok = false;
if (ok)
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
"\nConsidering %s %i insns.\n"
--- 1208,1220 ----
/* Verify that we won't duplicate the caller. */
for (node1 = node->callers->caller;
! 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"
*************** cgraph_decide_inlining (void)
*** 1184,1191 ****
ninlined = cgraph_inlined_into (node->callers->caller,
inlined);
old_insns = overall_insns;
if (cgraph_check_inline_limits
! (node->callers->caller, node, inlined, ninlined))
{
ninlined_callees =
cgraph_inlined_callees (node, inlined_callees);
--- 1225,1235 ----
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,
! &dummy_reason))
{
ninlined_callees =
cgraph_inlined_callees (node, inlined_callees);
*************** cgraph_decide_inlining_incrementally (st
*** 1245,1253 ****
/* 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);
--- 1289,1304 ----
/* 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->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);
*************** cgraph_decide_inlining_incrementally (st
*** 1259,1270 ****
{
/* 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,
--- 1310,1328 ----
{
/* Now do the automatic inlining. */
for (e = node->callees; e; e = e->next_callee)
! if (e->callee->local.inlinable && e->inline_failed
&& cgraph_default_inline_p (e->callee)
&& cgraph_check_inline_limits (node, e->callee, inlined,
! 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,
*************** cgraph_decide_inlining_incrementally (st
*** 1283,1292 ****
}
! /* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */
bool
! cgraph_inline_p (tree caller_decl, tree callee_decl)
{
struct cgraph_node *caller = cgraph_node (caller_decl);
struct cgraph_node *callee = cgraph_node (callee_decl);
--- 1341,1352 ----
}
! /* 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, const char **reason)
{
struct cgraph_node *caller = cgraph_node (caller_decl);
struct cgraph_node *callee = cgraph_node (callee_decl);
*************** cgraph_inline_p (tree caller_decl, tree
*** 1294,1303 ****
for (e = caller->callees; e; e = e->next_callee)
if (e->callee == callee)
! return e->inline_call;
/* 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. */
return false;
}
/* Expand all functions that must be output.
--- 1354,1369 ----
for (e = caller->callees; e; e = e->next_callee)
if (e->callee == callee)
! {
! 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.
*************** cgraph_expand_all_functions (void)
*** 1340,1346 ****
/* 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.
We simply mark all static functions whose address is not taken
as local. */
--- 1406,1413 ----
/* Mark all local functions.
A local function is one whose calls can occur only in the
! 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. */
Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.88
diff -c -3 -p -r1.88 tree-inline.c
*** tree-inline.c 13 Nov 2003 20:50:40 -0000 1.88
--- tree-inline.c 3 Jan 2004 12:24:01 -0000
*************** expand_call_inline (tree *tp, int *walk_
*** 1247,1252 ****
--- 1247,1253 ----
splay_tree st;
tree args;
tree return_slot_addr;
+ const char *reason;
/* See what we've got. */
id = (inline_data *) data;
*************** expand_call_inline (tree *tp, int *walk_
*** 1327,1338 ****
/* 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 (warn_inline && DECL_INLINE (fn) && DECL_DECLARED_INLINE_P (fn)
! && !DECL_IN_SYSTEM_HEADER (fn))
{
! warning ("%Jinlining failed in call to '%F'", fn, fn);
warning ("called from here");
}
return NULL_TREE;
--- 1328,1340 ----
/* Don't try to inline functions that are not well-suited to
inlining. */
! if (!cgraph_inline_p (id->current_decl, fn, &reason))
{
! if (warn_inline && DECL_DECLARED_INLINE_P (fn)
! && !DECL_IN_SYSTEM_HEADER (fn)
! && strlen (reason))
{
! warning ("%Jinlining failed in call to '%F': %s", fn, fn, reason);
warning ("called from here");
}
return NULL_TREE;
More information about the Gcc-patches
mailing list