On Sun, Nov 16, 2014 at 7:00 PM, Jan Hubicka <[email protected]> wrote:
>> >The patch also hits a bug in i386's ix86_set_current_function. It is
>> >responsible
>> >for initializing backend and it does so lazily remembering the previous
>> >options
>> >backend was initialized for. Pragma parsing however clears the cache
>> >that leads
>> >to wrong settings being used for subsetquent functions.
>> >
>> >Bootstrapped/regtested x86_64-linux, will commit it tomorrow after bit
>> >of more testing.
>>
>> But for example for IPA pta this means we apply all IPA transforms without
>> any garbage collection run?
>
> The original loop also did not contain ggc_collect calls. Can we call
> ggc_collect from ipa-pta's
> data collection loop?
I suppose we could. We can also "unload" bodies if that is possible?
How much garbage do we accumulate during the IPA transform apply
phase?
> (in general I think -fipa-pta is kind of -fplease-explode-on-large-programs
> :))
True...
Richard.
> Honza
>>
>> Richard.
>>
>> >Index: gcc/cgraphclones.c
>> >===================================================================
>> >--- gcc/cgraphclones.c (revision 217612)
>> >+++ gcc/cgraphclones.c (working copy)
>> >@@ -307,7 +307,7 @@ duplicate_thunk_for_node (cgraph_node *t
>> > node = duplicate_thunk_for_node (thunk_of, node);
>> >
>> > if (!DECL_ARGUMENTS (thunk->decl))
>> >- thunk->get_body ();
>> >+ thunk->get_untransformed_body ();
>> >
>> > cgraph_edge *cs;
>> > for (cs = node->callers; cs; cs = cs->next_caller)
>> >@@ -1067,7 +1067,7 @@ symbol_table::materialize_all_clones (vo
>> > && !gimple_has_body_p (node->decl))
>> > {
>> > if (!node->clone_of->clone_of)
>> >- node->clone_of->get_body ();
>> >+ node->clone_of->get_untransformed_body ();
>> > if (gimple_has_body_p (node->clone_of->decl))
>> > {
>> > if (symtab->dump_file)
>> >Index: gcc/ipa-icf.c
>> >===================================================================
>> >--- gcc/ipa-icf.c (revision 217612)
>> >+++ gcc/ipa-icf.c (working copy)
>> >@@ -706,7 +706,7 @@ void
>> > sem_function::init (void)
>> > {
>> > if (in_lto_p)
>> >- get_node ()->get_body ();
>> >+ get_node ()->get_untransformed_body ();
>> >
>> > tree fndecl = node->decl;
>> > function *func = DECL_STRUCT_FUNCTION (fndecl);
>> >Index: gcc/passes.c
>> >===================================================================
>> >--- gcc/passes.c (revision 217612)
>> >+++ gcc/passes.c (working copy)
>> >@@ -2214,36 +2214,6 @@ execute_one_pass (opt_pass *pass)
>> > executed. */
>> > invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass);
>> >
>> >- /* SIPLE IPA passes do not handle callgraphs with IPA transforms in
>> >it.
>> >- Apply all trnasforms first. */
>> >- if (pass->type == SIMPLE_IPA_PASS)
>> >- {
>> >- struct cgraph_node *node;
>> >- bool applied = false;
>> >- FOR_EACH_DEFINED_FUNCTION (node)
>> >- if (node->analyzed
>> >- && node->has_gimple_body_p ()
>> >- && (!node->clone_of || node->decl != node->clone_of->decl))
>> >- {
>> >- if (!node->global.inlined_to
>> >- && node->ipa_transforms_to_apply.exists ())
>> >- {
>> >- node->get_body ();
>> >- push_cfun (DECL_STRUCT_FUNCTION (node->decl));
>> >- execute_all_ipa_transforms ();
>> >- cgraph_edge::rebuild_edges ();
>> >- free_dominance_info (CDI_DOMINATORS);
>> >- free_dominance_info (CDI_POST_DOMINATORS);
>> >- pop_cfun ();
>> >- applied = true;
>> >- }
>> >- }
>> >- if (applied)
>> >- symtab->remove_unreachable_nodes (false, dump_file);
>> >- /* Restore current_pass. */
>> >- current_pass = pass;
>> >- }
>> >-
>> > if (!quiet_flag && !cfun)
>> > fprintf (stderr, " <%s>", pass->name ? pass->name : "");
>> >
>> >Index: gcc/cgraphunit.c
>> >===================================================================
>> >--- gcc/cgraphunit.c (revision 217612)
>> >+++ gcc/cgraphunit.c (working copy)
>> >@@ -197,7 +197,6 @@ along with GCC; see the file COPYING3.
>> > #include "target.h"
>> > #include "diagnostic.h"
>> > #include "params.h"
>> >-#include "fibheap.h"
>> > #include "intl.h"
>> > #include "hash-map.h"
>> > #include "plugin-api.h"
>> >@@ -1469,7 +1468,7 @@ cgraph_node::expand_thunk (bool output_a
>> > }
>> >
>> > if (in_lto_p)
>> >- get_body ();
>> >+ get_untransformed_body ();
>> > a = DECL_ARGUMENTS (thunk_fndecl);
>> >
>> > current_function_decl = thunk_fndecl;
>> >@@ -1522,7 +1521,7 @@ cgraph_node::expand_thunk (bool output_a
>> > gimple ret;
>> >
>> > if (in_lto_p)
>> >- get_body ();
>> >+ get_untransformed_body ();
>> > a = DECL_ARGUMENTS (thunk_fndecl);
>> >
>> > current_function_decl = thunk_fndecl;
>> >@@ -1744,7 +1743,7 @@ cgraph_node::expand (void)
>> > announce_function (decl);
>> > process = 0;
>> > gcc_assert (lowered);
>> >- get_body ();
>> >+ get_untransformed_body ();
>> >
>> > /* Generate RTL for the body of DECL. */
>> >
>> >Index: gcc/cgraph.c
>> >===================================================================
>> >--- gcc/cgraph.c (revision 217612)
>> >+++ gcc/cgraph.c (working copy)
>> >@@ -1664,29 +1664,33 @@ release_function_body (tree decl)
>> > {
>> > if (DECL_STRUCT_FUNCTION (decl))
>> > {
>> >- push_cfun (DECL_STRUCT_FUNCTION (decl));
>> >- if (cfun->cfg
>> >- && current_loops)
>> >- {
>> >- cfun->curr_properties &= ~PROP_loops;
>> >- loop_optimizer_finalize ();
>> >- }
>> >- if (cfun->gimple_df)
>> >+ if (DECL_STRUCT_FUNCTION (decl)->cfg
>> >+ || DECL_STRUCT_FUNCTION (decl)->gimple_df)
>> > {
>> >- delete_tree_ssa ();
>> >- delete_tree_cfg_annotations ();
>> >- cfun->eh = NULL;
>> >- }
>> >- if (cfun->cfg)
>> >- {
>> >- gcc_assert (!dom_info_available_p (CDI_DOMINATORS));
>> >- gcc_assert (!dom_info_available_p (CDI_POST_DOMINATORS));
>> >- clear_edges ();
>> >- cfun->cfg = NULL;
>> >+ push_cfun (DECL_STRUCT_FUNCTION (decl));
>> >+ if (cfun->cfg
>> >+ && current_loops)
>> >+ {
>> >+ cfun->curr_properties &= ~PROP_loops;
>> >+ loop_optimizer_finalize ();
>> >+ }
>> >+ if (cfun->gimple_df)
>> >+ {
>> >+ delete_tree_ssa ();
>> >+ delete_tree_cfg_annotations ();
>> >+ cfun->eh = NULL;
>> >+ }
>> >+ if (cfun->cfg)
>> >+ {
>> >+ gcc_assert (!dom_info_available_p (CDI_DOMINATORS));
>> >+ gcc_assert (!dom_info_available_p (CDI_POST_DOMINATORS));
>> >+ clear_edges ();
>> >+ cfun->cfg = NULL;
>> >+ }
>> >+ if (cfun->value_histograms)
>> >+ free_histograms ();
>> >+ pop_cfun ();
>> > }
>> >- if (cfun->value_histograms)
>> >- free_histograms ();
>> >- pop_cfun ();
>> > gimple_set_body (decl, NULL);
>> > /* Struct function hangs a lot of data that would leak if we didn't
>> > removed all pointers to it. */
>> >@@ -3138,7 +3142,7 @@ cgraph_node::function_symbol (enum avail
>> > present. */
>> >
>> > bool
>> >-cgraph_node::get_body (void)
>> >+cgraph_node::get_untransformed_body (void)
>> > {
>> > lto_file_decl_data *file_data;
>> > const char *data, *name;
>> >@@ -3178,6 +3182,44 @@ cgraph_node::get_body (void)
>> > return true;
>> > }
>> >
>> >+/* Prepare function body. When doing LTO, read cgraph_node's body
>> >from disk
>> >+ if it is not already present. When some IPA transformations are
>> >scheduled,
>> >+ apply them. */
>> >+
>> >+bool
>> >+cgraph_node::get_body (void)
>> >+{
>> >+ bool updated;
>> >+
>> >+ updated = get_untransformed_body ();
>> >+
>> >+ /* Getting transformed body makes no sense for inline clones;
>> >+ we should never use this on real clones becuase they are
>> >materialized
>> >+ early.
>> >+ TODO: Materializing clones here will likely lead to smaller
>> >LTRANS
>> >+ footprint. */
>> >+ gcc_assert (!global.inlined_to && !clone_of);
>> >+ if (ipa_transforms_to_apply.exists ())
>> >+ {
>> >+ opt_pass *saved_current_pass = current_pass;
>> >+ FILE *saved_dump_file = dump_file;
>> >+ int saved_dump_flags = dump_flags;
>> >+
>> >+ push_cfun (DECL_STRUCT_FUNCTION (decl));
>> >+ execute_all_ipa_transforms ();
>> >+ cgraph_edge::rebuild_edges ();
>> >+ free_dominance_info (CDI_DOMINATORS);
>> >+ free_dominance_info (CDI_POST_DOMINATORS);
>> >+ pop_cfun ();
>> >+ updated = true;
>> >+
>> >+ current_pass = saved_current_pass;
>> >+ dump_file = saved_dump_file;
>> >+ dump_flags = saved_dump_flags;
>> >+ }
>> >+ return updated;
>> >+}
>> >+
>> > /* Return the DECL_STRUCT_FUNCTION of the function. */
>> >
>> > struct function *
>> >Index: gcc/cgraph.h
>> >===================================================================
>> >--- gcc/cgraph.h (revision 217612)
>> >+++ gcc/cgraph.h (working copy)
>> >@@ -933,6 +933,11 @@ public:
>> >
>> >/* When doing LTO, read cgraph_node's body from disk if it is not
>> >already
>> > present. */
>> >+ bool get_untransformed_body (void);
>> >+
>> >+ /* Prepare function body. When doing LTO, read cgraph_node's body
>> >from disk
>> >+ if it is not already present. When some IPA transformations are
>> >scheduled,
>> >+ apply them. */
>> > bool get_body (void);
>> >
>> > /* Release memory used to represent body of function.
>> >Index: gcc/config/i386/i386.c
>> >===================================================================
>> >--- gcc/config/i386/i386.c (revision 217612)
>> >+++ gcc/config/i386/i386.c (working copy)
>> >@@ -5029,10 +5029,35 @@ ix86_can_inline_p (tree caller, tree cal
>> > /* Remember the last target of ix86_set_current_function. */
>> > static GTY(()) tree ix86_previous_fndecl;
>> >
>> >+/* Set target globals to default. */
>> >+
>> >+static void
>> >+ix86_reset_to_default_globals (void)
>> >+{
>> >+ tree old_tree = (ix86_previous_fndecl
>> >+ ? DECL_FUNCTION_SPECIFIC_TARGET (ix86_previous_fndecl)
>> >+ : NULL_TREE);
>> >+
>> >+ if (old_tree)
>> >+ {
>> >+ tree new_tree = target_option_current_node;
>> >+ cl_target_option_restore (&global_options,
>> >+ TREE_TARGET_OPTION (new_tree));
>> >+ if (TREE_TARGET_GLOBALS (new_tree))
>> >+ restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
>> >+ else if (new_tree == target_option_default_node)
>> >+ restore_target_globals (&default_target_globals);
>> >+ else
>> >+ TREE_TARGET_GLOBALS (new_tree)
>> >+ = save_target_globals_default_opts ();
>> >+ }
>> >+}
>> >+
>> > /* Invalidate ix86_previous_fndecl cache. */
>> > void
>> > ix86_reset_previous_fndecl (void)
>> > {
>> >+ ix86_reset_to_default_globals ();
>> > ix86_previous_fndecl = NULL_TREE;
>> > }
>> >
>> >@@ -5071,18 +5096,7 @@ ix86_set_current_function (tree fndecl)
>> > }
>> >
>> > else if (old_tree)
>> >- {
>> >- new_tree = target_option_current_node;
>> >- cl_target_option_restore (&global_options,
>> >- TREE_TARGET_OPTION (new_tree));
>> >- if (TREE_TARGET_GLOBALS (new_tree))
>> >- restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
>> >- else if (new_tree == target_option_default_node)
>> >- restore_target_globals (&default_target_globals);
>> >- else
>> >- TREE_TARGET_GLOBALS (new_tree)
>> >- = save_target_globals_default_opts ();
>> >- }
>> >+ ix86_reset_to_default_globals ();
>> > }
>> > }
>> >
>> >@@ -50972,7 +50986,7 @@ ix86_simd_clone_adjust (struct cgraph_no
>> > bool ok = ix86_valid_target_attribute_p (node->decl, NULL, args, 0);
>> > gcc_assert (ok);
>> > pop_cfun ();
>> >- ix86_previous_fndecl = NULL_TREE;
>> >+ ix86_reset_previous_fndecl ();
>> > ix86_set_current_function (node->decl);
>> > }
>> >
>> >Index: gcc/tree-inline.c
>> >===================================================================
>> >--- gcc/tree-inline.c (revision 217612)
>> >+++ gcc/tree-inline.c (working copy)
>> >@@ -4338,7 +4338,7 @@ expand_call_inline (basic_block bb, gimp
>> > goto egress;
>> > }
>> > fn = cg_edge->callee->decl;
>> >- cg_edge->callee->get_body ();
>> >+ cg_edge->callee->get_untransformed_body ();
>> >
>> > #ifdef ENABLE_CHECKING
>> > if (cg_edge->callee->decl != id->dst_node->decl)
>> >Index: gcc/tree-ssa-structalias.c
>> >===================================================================
>> >--- gcc/tree-ssa-structalias.c (revision 217612)
>> >+++ gcc/tree-ssa-structalias.c (working copy)
>> >@@ -7086,7 +7086,7 @@ ipa_pta_execute (void)
>> > /* Nodes without a body are not interesting. Especially do not
>> > visit clones at this point for now - we get duplicate decls
>> > there for inline clones at least. */
>> >- if (!node->has_gimple_body_p () || node->clone_of)
>> >+ if (!node->has_gimple_body_p () || node->global.inlined_to)
>> > continue;
>> > node->get_body ();
>> >
>>