This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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 (&reg_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 (&reg_obstack); /* FIXME, only at RTL generation*/
 
-
-  execute_all_ipa_transforms ();
-
   /* Perform all tree transforms and optimizations.  */
   execute_pass_list (all_passes);
   

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]