This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[lto][patch] Move the call to execute_all_ipa_transforms to cgraphunit.c
- From: Rafael Espindola <espindola at google dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Cc: Diego Novillo <dnovillo at google dot com>
- Date: Tue, 11 Nov 2008 17:21:09 +0000
- Subject: [lto][patch] Move the call to execute_all_ipa_transforms to cgraphunit.c
We have to move the call execute_all_ipa_transforms to cgraphunit.c,
since we want to run the transformations and then regenerate the
summaries.
Doing so shows a problem with pass_set_nothrow_function_flags. Setting
the NOTHROW bit of a function F invalidates the eh regions of any
function that call F. This is not currently visible since
execute_fixup_cfg gets called by other passes before the problem is
detected. Ian pointed out that the correct fix is to make
pass_set_nothrow_function_flag an IPA pass. The attached patches use 2
different approaches to avoid the problem.
Patch 1 adds a direct call to execute_fixup_cfg in
tree_rest_of_compilation. For reasons I still don't understand this
causes a regression on the following test
---------------------------------------------------------------
struct _Tune {
explicit _Tune() {
}
};
template<class _PoolTp>
static void _S_get_pool() {
static _Tune _M_options;
}
class __mt_alloc {
public:
~__mt_alloc() throw() {
}
};
void deallocate() {
_S_get_pool<int>();
delete (int *)0;
}
int main() {
__mt_alloc a;
deallocate();
deallocate();
}
---------------------------------------------------------------
cc1plus fails with "internal compiler error: in calc_dfs_tree, at
dominance.c:394". Converting _S_get_pool to a non-template function
solves the problem, so there is something really strange going on.
The second patch takes the simpler approach of just disabling the
pass. It is currently bootstrapping, but I have checked that it
doesn't show that regression.
So, which one is your favorite? :-) Assuming disabling the pass has no
regressions, should I commit that? And if it has? Should I debug the
above problem?
Cheers,
--
Rafael Avila de Espindola
Google | Gordon House | Barrow Street | Dublin 4 | Ireland
Registered in Dublin, Ireland | Registration Number: 368047
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 01cae4e..fe74fc1 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1078,7 +1078,46 @@ cgraph_inline_p (struct cgraph_edge *e, cgraph_inline_failed_t *reason)
return !e->inline_failed;
}
+/* Execute all ipa transforms in all functions. */
+static void
+cgraph_execute_all_ipa_transforms (void)
+{
+ struct cgraph_node *node;
+ struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
+ int order_pos, new_order_pos = 0;
+ int i;
+
+ order_pos = cgraph_postorder (order);
+ gcc_assert (order_pos == cgraph_n_nodes);
+
+ /* Garbage collector may remove inline clones we eliminate during
+ optimization. So we must be sure to not reference them. */
+ for (i = 0; i < order_pos; i++)
+ {
+ if (order[i]->output)
+ order[new_order_pos++] = order[i];
+ }
+
+ gimple_register_cfg_hooks ();
+
+ for (i = new_order_pos - 1; i >= 0; i--)
+ {
+ tree fndecl;
+ node = order[i];
+ fndecl = node->decl;
+
+ bitmap_obstack_initialize (NULL);
+ current_function_decl = fndecl;
+ set_cfun (DECL_STRUCT_FUNCTION (fndecl));
+
+ execute_all_ipa_transforms ();
+
+ set_cfun (NULL);
+ current_function_decl = NULL;
+ bitmap_obstack_release (NULL);
+ }
+}
/* Expand all functions that must be output.
@@ -1320,6 +1359,8 @@ cgraph_optimize (void)
cgraph_mark_functions_to_output ();
+ cgraph_execute_all_ipa_transforms ();
+
cgraph_state = CGRAPH_STATE_EXPANSION;
if (!flag_toplevel_reorder)
cgraph_output_in_order ();
diff --git a/gcc/passes.c b/gcc/passes.c
index ed433da..15603e1 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1244,20 +1244,26 @@ execute_one_ipa_transform_pass (struct cgraph_node *node,
void
execute_all_ipa_transforms (void)
{
- if (cfun && cfun->ipa_transforms_to_apply)
- {
- unsigned int i;
- struct cgraph_node *node = cgraph_node (current_function_decl);
-
- for (i = 0; i < VEC_length (ipa_opt_pass, cfun->ipa_transforms_to_apply);
- i++)
- execute_one_ipa_transform_pass (node,
- VEC_index (ipa_opt_pass,
- cfun->ipa_transforms_to_apply,
- i));
- VEC_free (ipa_opt_pass, heap, cfun->ipa_transforms_to_apply);
- cfun->ipa_transforms_to_apply = NULL;
- }
+ unsigned int i;
+ struct cgraph_node *node;
+
+ gcc_assert(cfun);
+ if (!cfun->ipa_transforms_to_apply)
+ return;
+
+ node = cgraph_node (current_function_decl);
+
+ gcc_assert (node->output);
+
+ for (i = 0; i < VEC_length (ipa_opt_pass, cfun->ipa_transforms_to_apply);
+ i++)
+ execute_one_ipa_transform_pass (node,
+ VEC_index (ipa_opt_pass,
+ cfun->ipa_transforms_to_apply,
+ i));
+
+ VEC_free (ipa_opt_pass, heap, cfun->ipa_transforms_to_apply);
+ cfun->ipa_transforms_to_apply = NULL;
}
/* Execute PASS. */
diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c
index 18ccf21..2732847 100644
--- a/gcc/tree-optimize.c
+++ b/gcc/tree-optimize.c
@@ -415,8 +415,9 @@ tree_rest_of_compilation (tree fndecl)
bitmap_obstack_initialize (®_obstack); /* FIXME, only at RTL generation*/
-
- execute_all_ipa_transforms ();
+ /* FIXME lto. pass_set_nothrow_function_flags might have corrupted our
+ eh regions. It should be rewritten as an IPA pass. */
+ execute_fixup_cfg ();
/* Perform all tree transforms and optimizations. */
execute_pass_list (all_passes);
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 01cae4e..fe74fc1 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1078,7 +1078,46 @@ cgraph_inline_p (struct cgraph_edge *e, cgraph_inline_failed_t *reason)
return !e->inline_failed;
}
+/* Execute all ipa transforms in all functions. */
+static void
+cgraph_execute_all_ipa_transforms (void)
+{
+ struct cgraph_node *node;
+ struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
+ int order_pos, new_order_pos = 0;
+ int i;
+
+ order_pos = cgraph_postorder (order);
+ gcc_assert (order_pos == cgraph_n_nodes);
+
+ /* Garbage collector may remove inline clones we eliminate during
+ optimization. So we must be sure to not reference them. */
+ for (i = 0; i < order_pos; i++)
+ {
+ if (order[i]->output)
+ order[new_order_pos++] = order[i];
+ }
+
+ gimple_register_cfg_hooks ();
+
+ for (i = new_order_pos - 1; i >= 0; i--)
+ {
+ tree fndecl;
+ node = order[i];
+ fndecl = node->decl;
+
+ bitmap_obstack_initialize (NULL);
+ current_function_decl = fndecl;
+ set_cfun (DECL_STRUCT_FUNCTION (fndecl));
+
+ execute_all_ipa_transforms ();
+
+ set_cfun (NULL);
+ current_function_decl = NULL;
+ bitmap_obstack_release (NULL);
+ }
+}
/* Expand all functions that must be output.
@@ -1320,6 +1359,8 @@ cgraph_optimize (void)
cgraph_mark_functions_to_output ();
+ cgraph_execute_all_ipa_transforms ();
+
cgraph_state = CGRAPH_STATE_EXPANSION;
if (!flag_toplevel_reorder)
cgraph_output_in_order ();
diff --git a/gcc/passes.c b/gcc/passes.c
index ed433da..50c47b6 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -823,7 +823,8 @@ init_optimization_passes (void)
NEXT_PASS (pass_split_for_shorten_branches);
NEXT_PASS (pass_convert_to_eh_region_ranges);
NEXT_PASS (pass_shorten_branches);
- NEXT_PASS (pass_set_nothrow_function_flags);
+ /* FIXME lto: should be an IPA pass. */
+ /* NEXT_PASS (pass_set_nothrow_function_flags);*/
NEXT_PASS (pass_final);
}
NEXT_PASS (pass_df_finish);
@@ -1244,20 +1245,26 @@ execute_one_ipa_transform_pass (struct cgraph_node *node,
void
execute_all_ipa_transforms (void)
{
- if (cfun && cfun->ipa_transforms_to_apply)
- {
- unsigned int i;
- struct cgraph_node *node = cgraph_node (current_function_decl);
-
- for (i = 0; i < VEC_length (ipa_opt_pass, cfun->ipa_transforms_to_apply);
- i++)
- execute_one_ipa_transform_pass (node,
- VEC_index (ipa_opt_pass,
- cfun->ipa_transforms_to_apply,
- i));
- VEC_free (ipa_opt_pass, heap, cfun->ipa_transforms_to_apply);
- cfun->ipa_transforms_to_apply = NULL;
- }
+ unsigned int i;
+ struct cgraph_node *node;
+
+ gcc_assert(cfun);
+ if (!cfun->ipa_transforms_to_apply)
+ return;
+
+ node = cgraph_node (current_function_decl);
+
+ gcc_assert (node->output);
+
+ for (i = 0; i < VEC_length (ipa_opt_pass, cfun->ipa_transforms_to_apply);
+ i++)
+ execute_one_ipa_transform_pass (node,
+ VEC_index (ipa_opt_pass,
+ cfun->ipa_transforms_to_apply,
+ i));
+
+ VEC_free (ipa_opt_pass, heap, cfun->ipa_transforms_to_apply);
+ cfun->ipa_transforms_to_apply = NULL;
}
/* Execute PASS. */
diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c
index 18ccf21..a5def35 100644
--- a/gcc/tree-optimize.c
+++ b/gcc/tree-optimize.c
@@ -415,9 +415,6 @@ tree_rest_of_compilation (tree fndecl)
bitmap_obstack_initialize (®_obstack); /* FIXME, only at RTL generation*/
-
- execute_all_ipa_transforms ();
-
/* Perform all tree transforms and optimizations. */
execute_pass_list (all_passes);