Unit at a time C++ again

Jan Hubicka hubicka@ucw.cz
Wed Jun 18 13:53:00 GMT 2003


Mark,
after some frustration I got back to the unit-at-a-time and it appears
difficult to get there without doing quite a lot of intrusive modifications at
once, so I would like to discuss with you a plan whether it is possible to get
unit-at-a-time working with gcc-3.4 timeframe (it would be nice to do as it
would be easier to modify inlining heuristics to avoid some dead ends we are
seeing now).

As discussed last time, we both agree that we are shooting for scheme where
frontend expands all functions/datastructures into generic tree form (gimple in
post-3.5) and unit-at-a-time code cares to build callgraph and graph of
references and remove unreachable nodes.

My current code, as implemented for C/objC does not touch the data structures
and does just the callgraph part.  My original plan was to first convert all
frontends to the callgraph and continue by datastructures next.  The API is
done as follows:

  once frontend is finished with function, it calls:
    cgraph_finalize_function (decl, body)
  once frontend is finished with the compilation unit it calls:
    cgraph_finalize_compilation_unit ()
  and once we want to output functions it calls:
    cgraph_expand_functions ()

At the moment the data structures are output directly via varasm and it calls
   cgraph_mark_needed_node (node, needed)
for each function whose reference is output.  As incremental step I would like
to implement the data-structure part, but the way data structures are output
seems to be very frontend dependent so it appears to be dificult.  I would like
to do it later in case it is not essential to get callgraph part used by C++.

cgraph expand functions then examines entry points to the program (externally
visible functions, functions marked by varasm) and lowers representation of all
such reachable bodies.  I expect gimplification to sit there, but at the moment
I simply call back the frontend via
    lang_hooks.callgraph.lower_function
this function is supposed to make all calls and references to function in the
body explicit and it may futher do cgraph_mark_needed_node for functions needed
by this function.  Callgraph is constructed for the examined functions and
reachable functions are marked as needed and lowered by same process.

Finally once needed functions are lowered, unit-at-a-time optimizations are
performed and
    lang_hooks.callgraph.expand_function
is called.  On tree-SSA I expect this to be middle end gimple
optimizer/expander but at the moment this is slightly frontend specific.

Now the question is how to map C++ frontend to it.  My original plan has been as follows:
  - map expand_body to cgraph_finalize_function
  - use lang_hooks.callgraph.lower_function to output virtual tables/produce
    static initializers for given function

First dificulty I run into that expand_body often deffers function and later we
change DECL_PUBLIC and similar attributes.  My cgraph code expects that once
function is finalized, it's declaration does not change so it gets confused.

Why is this done?  Is this really needed?
To avoid problems with this I decided to keep the function deffering mechanizm
and finalize_functions at the end of compilation.

The patch I sent does not exactly that - instead it preserves the current loop
to determine functions needed and finalize only those that are needed.  This is
because to get the proper flags I needed to call import_export_decl that
appeared to be unsafe to call for functions I won't output at the end.
Perhaps I can avoid this and simply walk whole queue and finalize all functions.

Another problem is the code to output static initializers/virtual tables.  At
the moment I kept the code to iterate over functions needed and I simply inject
TREE_SYMBOL_REFERENCED flag from lower_function.

This is ugly as we discussed earlier.  We concluded that it will be better to
just examine what functions are further needed by this and expand it later.  I
did run into problem here with static initializers - I apparently can not
expand the function to statically initialize something until I output the data
itself, but I don't want to do that.

What do you think about incremental step here were we simply output the static
initializers and virtual tables needed by the function.  Is this possible to do
so with simple recursive walk of function body noticing what tables/data are
referenced?  (so we won't need to have the loop going trought all the vtables
checking TREE_SYMBOL_REFERENCED.

What do you think about sollution that will keep the array for deffering
functions, but actually cgraph_finalize_function them all at the end of
compilation unit.  Then output vtables/static initializers referenced by static
data (using loop similar to current one, but this won't need to iterate,
right?) and finally in lang_hooks.callgraph.lower_function walk function
body and output vtables/static initializers needed by function that are not
already output.  Will this introduce new function bodies?

Honza



More information about the Gcc mailing list