Memory usage
Mark Mitchell
mark@codesourcery.com
Fri Apr 9 12:58:00 GMT 1999
There's another problem with the way we implement inlining that is
quite embarassing. Unfortunately, I don't know quite how to fix it,
given our current architecture. Given:
inline void f() {}
inline void g() { f(); }
inline void h() { g(); }
void k() { h(); }
we first expand `f' into `g', and then expand the result into h. This
means that we copy all of the declarations and code in `f' twice, even
though we really only need to do it once, since `g' is never output.
This represents a *huge* amount of memory; one test I have that takes
over 300MB to compile would take only 50MB if we didn't make this
mistake.
The "right thing" is to leave the un-inlined call in the `g', only
expanding the call if we ever get to the point where we need to outupt
`g'. Then, when we output `h', we inline `g', notice the un-inlined
call, and go inline `f' at that point, directly into `h'.
This would be a huge win both in time and space. Does anyone have any
ideas about how to do this? I was thinking:
o If we're currently processing a function that we don't know that
we have to output yet, let expand_inline_function get as far as
expanding the arguments, but then squirrel them away in a
CALL_EXPR (new RTL code). Make a new dummy piece of RTL for the
function result, and pretend that's the output.
o Then, when outputting a previously-deferred function, scan for
this CALL_EXPR and finish the work of expand_inline_function.
o When expanding an inline, recursively expand the functions
indicated by the CALL_EXPRs.
But, how do we save all the weird global state required? It's a shame
that are data structures don't make this easier. Any ideas?
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
More information about the Gcc-bugs
mailing list