On Sun, Apr 22, 2012 at 2:16 PM, Jan Hubicka <hubi...@ucw.cz> wrote:
> Hi,
> this is second part of cleanup of the callgraph/varpool reachability code.
>
> As I wrote in previous email, the callgraph was originally written with
> reachability code built in. This code was used by non-unit-at-a-time (to drop
> unnecesary inline functoins), the unit-a-a-time cgraph builder and by pass
> removing unreachable functions.
>
> It was implemented as a queue of functions known to be needed that was
> processed by those consumers, plus by the needed flag (removed in previous
> patch) for functions that are trivially needed and reachable flag for
> functions that are needed by reachablity analysis.
>
> Similarly varpool code had reachability built in, but the variables was not
> removed (it broke drwarf2out), just they was not output when unreachable.
> This was done after functions was output and later this reachability code
> was re-used for removal of unreferenced variables, too.
>
> This all was interlacing with cgraph construction code because we did not 
> track
> all references via ipa-ref like we do now.
>
> This patch removes the shared reachability code and replaces it by 3
> independent implementations. The motivation is that the 3 cases are different
> enough to not motivate code reuse for something as simple as an queue +
> walk of ipa-references, callees and same comdat group lists.
>
> 1) at cgraph/varpool construction time in cgraphbuild.c.  This code is bit
>   complicated by fact that new nodes are being discovered and finalized on the
>   process (such as local statics of functions that are not visible before
>   function containing them is lowered, or by openMP expansion).
>
>   The code is now also mre contained (see all the varpool_mark_needed_node
>   calls that has been removed).  Because of non-unit-at-a-time we
>   used to decide that variables are needed at many different places, in
>   order to bring them into output file as early as possible.
>
>   Now we discover most of the stuff by walking the IL as we build cgraph
>   and reference lists.  There is still feedback from cgraph_finalize,
>   varpool_finalize and cgraph_add_new_function for functions/vars appearing
>   during the process.  Not as interwinded as before though.
>   It is made simple by fact that we have only those references and
>   calls that are needed and thus function is reachable if it has some
>   referneces to it.
>
>   Newly we now remove unreferenced varpool nodes that should save some memory.
>   We should also destroy their DECL_INITIAL pointer, but I am still affraid
>   of dwarf2out breaking, so I will try that inrementally.
> 2) unreachable nodes removal in ipa.c. This is just usual rechability walk,
>   but it has some extra complication to deal with extern inlines (that stay
>   in code for a while but past inlining their bodies are removed even if
>   they are reachable), virtual functions (that also stay for a while to
>   allow devirtualization via type based mechanizm or external constructors)
>   and it also has to deal with virtual clones (i.e. we can not remove
>   original function of the clone prior materialization) and inline clones
>   (when offline version of function is no longer needed, the clone
>   tree needs to be reshaped).
> 3) final pass in varpool that looks what vars are still needed after
>   all functions was expanded.  This is done by DECL_RLT_SET_P test that
>   is bit kludgy, but works well.
>   For example, in combine.c we still remove some of __FUNCTION__ vars because
>   some of aborts are proven to be unnecesary.
>
> There are a lot of subsequent cleanups left on the table, I tried to separate
> this into a lot smaller patch than this one, but it has significant 
> snowballing
> effect.  Most irritating part is the wrapup_global_declarations logic that 
> once
> was there to avoid unreferences static vars to be output but it completely
> pointless now.  Probably should be moved into cgraph construction stage.
>
> Other problem is that we are creaing new symbols from realy random places, 
> like
> DECL_ASSEMBLER_NAME langhook callback from C++ FE that creates extra name 
> aliases...
>
> The code is now also more picky on variable being finalized in order to be 
> output.
> This uncovers latent bug in C++ FE where explicit instantiations are sometimes
> not finalized at all.
>
> Regtested/bootstrapped x86_64-linux and also tested with LTO Mozilla.
> Will commit it tonight.
>
> Honza
>
>
>        * lto-symtab.c (lto_varpool_replace_node): Do not merge needed flags.
>        * cgraphbuild.c (record_reference, record_type_list, mark_address,
>        mark_load, mark_store): Do not mark varpool nodes as needed.
>        * cgraph.c (cgraph_new_nodes): Remove.
>        (cgraph_create_function_alias): Do not mark nodes as reachable.
>        (cgraph_add_thunk): Likewise.
>        (cgraph_mark_reachable_node): Do not manage the queue.
>        * cgraph.h (cgraph_node): Remove next_needed.
>        (varpool_nodes_queue): Remove next_needed and prev_needed.
>        (x_cgraph_nodes_queue, x_cgraph_nodes_queue, cgraph_new_nodes): Remove.
>        (cgraph_new_nodes): Declare.
>        (x_varpool_nodes_queue, varpool_nodes_queue); Remove.
>        (varpool_analyze_pending_decls): Remove.
>        (varpool_analyze_node): New.
>        (varpool_mark_needed_node): Remove.
>        (varpool_first_variable, varpool_next_variable): New inlines.
>        (varpool_first_static_initializer, varpool_next_static_initializer): 
> Update.
>        (FOR_EACH_STATIC_VARIABLE): Remove unused walker.
>        (varpool_first_defined_variable): New inline.
>        (varpool_next_defined_variable): New inline
>        (FOR_EACH_VARIABLE): Reimplement.
>        (FOR_EACH_DEFINED_VARIABLE): Reimplement.
>        * toplev.c (wrapup_global_declaration_2): Use analyzed instead of
>        needed flag.
>        * cgraphunit.c (cgraph_new_nodes): Declare here.
>        (enqueue_node): New function.
>        (cgraph_process_new_functions): update for new
>        node set; when constructing cgraph enqueue node for processing.
>        (cgraph_add_new_function): Use new node set.
>        (process_function_and_variable_attributes): Do not set varpool needed
>        flags.
>        (referred_to_p): New function.
>        (varpool_finalize_decl): Move here from varpool.c; enqueue needed node
>        when varpool is in construction.
>        (cgraph_analyze_functions): Rewrite.
>        (cgraph_expand_all_functions): Update.
>        (cgraph_output_in_order): Do not analyze pending decls; do not set 
> needed flags.
>        (cgraph_optimize): Do not analyze pending decls.
>        * lto-cgraph.c (input_varpool_node): Clear analyzed flag for objects 
> in other
>        partition; do not mark node as needed.
>        * dwarf2out.c (reference_to_unused): Use analyzed flag.
>        (premark_types_used_by_global_vars_helper): Likewise.
>        * ipa.c (process_references): Do not call varpool_mark_needed_node.
>        (cgraph_remove_unreachable_nodes): Do not rely on varpool and
>        cgrpah queues.
>        (function_and_variable_visibility): Do not mark node as needed.
>        (whole_program_function_and_variable_visibility): Likewise.
>        * Makefile.in (gt-varpool.h): No longer needed.
>        * passes.c (execute_one_pass, execute_ipa_pass_list): Update.
>        (ipa_write_summaries): Do not use needed flag.
>        * varpool.c: Do not include gt-varpool.h
>        (x_varpool_nodes_queue, x_varpool_last_needed_node,
>        x_varpool_last_needed_node, x_varpool_first_unanalyzed_node,
>        x_varpool_first_unanalyzed_node, varpool_assembled_nodes_queue):
>        Remove.
>        (varpool_remove_node): Do not update the lists.
>        (dump_varpool_node): Do not dump needed flag.
>        (varpool_enqueue_needed_node): Remove.
>        (varpool_mark_needed_node): Remove.
>        (varpool_reset_queue): Remove.
>        (varpool_finalize_decl): Move to cgraphunit.c
>        (varpool_analyze_node): New functions based on former
>        varpool_analyze_pending_decls.
>        (varpool_analyze_pending_decls): Remove.
>        (varpool_assemble_decl): Do not update the lists.
>        (enqueue_node): New function.
>        (varpool_remove_unreferenced_decls): Rewrite.
>        (varpool_empty_needed_queue): Remove.
>        (add_new_static_var): Do not mark node as needed.
>        (varpool_create_variable_alias): Handle expansion state
>        creation.
>        * except.c (output_ttype): Do not mark node as needed.
>        * varasm.c (mark_decl_referenced): Do not use mark_needed_node.
>        * tree-profile.c (init_ic_make_global_vars, init_ic_make_global_vars):
>        Likewise.
>        * tree-switch-conversion.c (build_one_array): Likewise.
>
>        * class.c (build_utf8_ref): Do not mark varpool node as needed.
>
>        * gcc-interface/utils.c (gnat_write_global_declarations): Do not mark
>        needed node.
>
>        * lto-partition.c (partition_varpool_node_p): Do not use needed flag.
>
>        * decl2.c (maybe_make_one_only): Mark keyed COMDATs as USED so they
>        gets finalized.

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53088
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53089

-- 
H.J.

Reply via email to