If a nested subroutine calls another nested subroutine that follows it
lexically, then convert_all_function_calls will force the called function to
take a static chain even though it may not need one. The most trivial example
of this is a recursive nested subroutine, as in example n1.c:
void n1(void) { void a(void) { a(); } }
$ gcc -c n1.c -fdump-tree-nested
$ grep chain n1.c.*nested
a () [static-chain: CHAIN.1];
A pointless static chain has been created.
Here's an example n2.c in which the caller and callee disagree about whether a
static chain is needed or not: the caller thinks it is needed, the callee does
not.
void n2(void) {
auto void a(void);
void b(void) { a(); }
void a(void) {}
}
This might seem fairly harmless, but can become expensive when trampolines are
needlessly created. Example n3.c:
void n3(void) {
auto void a(void *);
void b(void) { a(b); }
void a(void *f) {}
}
$ gcc -c n3.c -fdump-tree-nested
$ grep trampoline n3.c.*nested
struct __builtin_trampoline * D.1631;
D.1632 = __builtin_adjust_trampoline (D.1631);
__builtin_init_trampoline (&FRAME.0.b, b, &FRAME.0);
In Ada, nested subroutines are widely used, and unneeded static chains are
frequently being created by gcc: I first noticed this problem while
bootstrapping the compiler with a patch that happened to print a warning in
case n2.c: the warning fired hundreds of times during the Ada build. The most
common reason for this seems to be due to the instantiation of generic packages
inside library level procedures.
--
Summary: tree-nested creates pointless static chains and
trampolines when the callgraph is non-trivial
Product: gcc
Version: 4.3.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: baldrick at gcc dot gnu dot org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30927