Whole-file compilation in gfortran
Michael Matz
matz@suse.de
Wed Aug 15 14:47:00 GMT 2007
Hi,
On Tue, 14 Aug 2007, FX Coudert wrote:
> A short mail about the topic of whole-file compilation.
Actually it's more about enabling whole program compilation. Of the most
interest (performance wise) is inlining over module borders (i.e. inlining
a function F defined in module A, into a call in a different module B).
For that to happen it's obviously necessary to
1) have the body of F available at the call site in module B
2) detect that the call in B actually refers to the function we think it
refers to (namely F)
[beware of me not being a fortran expert, so my terminology might be
completely wrong, e.g. when I talk about modules, but I hope to get the
idea across anyway]
GCC can only compile (currently) one file at a time (let's ignore the
C-only whole-program mode), so solving (1) normally requires quite some
work, if the modules are compiled separately. But fortran is a thankful
language in that we can simply physically cat together all files of a
program (hence all modules) and still have a valid input file for the
compiler. That then trivially solves problem (1), as the whole file is
the program, hence all bodies of all functions remain available all time
(from the point of definition). This is obviously a hack, and instead of
pre-catting the files before invoking the compiler it would be better if
the compiler could do that for us. That would also help debug generation
as with the hack all debug info is relative to that special cat-together
file, not referring to the originial source files.
But even with that problem solved, we still wouldn't get nice inlining
because of problem (2). That's because the fortran frontend generates a
new FUNCTION_DECL for each get_extern_function_decl call, which is used
for each function definition and each function call. Hence all calls will
have different FUNCTION_DECLs, in turn being all different to all decls
for the function definitions. Calls to the same function name will happen
to have different FUNCTION_DECLs, but with the same name.
That is a problem because the call graph code determines the function
"calls-this-function" based on the FUNCTION_DECL nodes itself. So call
graph doesn't see that we actually have a function definition for the
calls, hence no inlining occurs.
So my patch was to target that problem (2). The eventual goal is, that
after the frontend is finished, there should be only exactly one
FUNCTION_DECL node for each function definition, and that very function
decl should be used in CALL_EXPRs (if the calls are not to undefined
functions obviously. In that case we need to generate a new
FUNCTION_DECL, but it's good if other calls to the same undefined
function would use the same FUNCTION_DECL node).
To do that we have to enter the merge-decl business. That is because it
can happen that we first see a call to a yet unknown function (hence
generating a new FUNCTION_DECL), but later see a definition which would
match that. In that case we would have to merge the new information (for
instance that we now have that function defined at that place) into the
old FUNCTION_DECL node. The same can happen if we see two calls with
different argument lists. As long as we don't have the definition we
can't be sure of the formal argument types of that FUNCTION_DECL.
And as you say it might expose some deficiencies in the current compiler,
ala ICEing when we see a call to a FUNCTION_DECL but the arguments don't
match. There might be other corner cases in fortran where my simple
approach can not be used, I don't know.
> As far as I understood, there are 3 different issues to be tackled that this
> would help us :
> (a) perform better inter-file checking of interfaces,
> (b) inline non-contained procedures, and
> (c) module loading performance
I believe (a) and (c) are only a problem if you want to solve my problem
(1) for real, i.e. when you really want to support multiple files for
whole program mode. That would be the best of course.
> I will not talk about (a) here, as it's probably the most tricky. As far
> as I see, (c) requires us to store modules into memory in addition to
> writing them to disk, so that we can load symbols from them without
> actually reading/parsing the file back. There might be more to it, Paul
> could tell.
It's at least required to also get to the bodies of the functions in those
other modules. If you don't want to parse the source again, then you will
have to have a different mean to store and read back general trees, at
which point you'll have solved the LTO problem. So I think before wasting
too much time in really supporting multi-file-whole-program mode it's
better to wait for LTO to move forward. That doesn't mean that we
couldn't already start working towards forming a nicer call graph by using
just one FUNCTION_DECL per entity.
Ciao,
Michael.
More information about the Fortran
mailing list