> >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?
(in general I think -fipa-pta is kind of -fplease-explode-on-large-programs :))
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 ();
> >
>