On Sun, Nov 16, 2014 at 7:00 PM, Jan Hubicka <hubi...@ucw.cz> 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 (); >> > >>