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]

Re: Fix firefox compilation ICE


> Hi,
> this patch fixes ICE while building Firefox (and probably xalancbmk, too)
> with -O3 -flto.  I originally tested the whole patchset on several bigger apps
> including the inline heuristics change which teach it that thunks are very cheap.
> Mainline doesn't contain it that makes us to inline into thunks more heavilly
> and results in some suprises.  I hope it is last one.
> 
> Bootstrapped/regtested x86_64-linux, I am re-testing with last minute change
> and will commit afterwards.
> 
> Honza
> 

Hi,
this is variant of patch I comitted. It gets re-arranging of clone tree right
in function body saving and also fixes another ICE (probably unrelated) in
tree-inline.c when saving suddenly folds into direct call that is not in the
symbol table that can happen when we know we will redirect the call later.

Bootstrapped/regtested x86_64-linux.

Honza

	* ipa-inline-transform.c (preserve_function_body_p): Look for
	first non-thunk clone.
	(save_function_body): Save into first non-thunk.
	* lto-cgraph.c (lto_output_edge): When streaming thunk do not look
	up call stmt id.
	(lto_output_node): Inline thunks don't need body in every
	partition.
	* lto-streamer-in.c: Do not fixup thunk clones.
	* cgraphclones.c (cgraph_node::create_edge_including_clone): Skip
	thunks.
	* tree-inline.c (copy_bb): Be prepared for target node to be new after
	folding suceeds.
Index: cgraphclones.c
===================================================================
--- cgraphclones.c	(revision 236317)
+++ cgraphclones.c	(working copy)
@@ -771,33 +771,35 @@ cgraph_node::create_edge_including_clone
   node = clones;
   if (node)
     while (node != this)
-      {
-	cgraph_edge *edge = node->get_edge (old_stmt);
+      /* Thunk clones do not get updated while copying inline function body.  */
+      if (!node->thunk.thunk_p)
+	{
+	  cgraph_edge *edge = node->get_edge (old_stmt);
 
-        /* It is possible that clones already contain the edge while
-	   master didn't.  Either we promoted indirect call into direct
-	   call in the clone or we are processing clones of unreachable
-	   master where edges has been removed.  */
-	if (edge)
-	  edge->set_call_stmt (stmt);
-	else if (! node->get_edge (stmt))
-	  {
-	    edge = node->create_edge (callee, stmt, count, freq);
-	    edge->inline_failed = reason;
-	  }
+	  /* It is possible that clones already contain the edge while
+	     master didn't.  Either we promoted indirect call into direct
+	     call in the clone or we are processing clones of unreachable
+	     master where edges has been removed.  */
+	  if (edge)
+	    edge->set_call_stmt (stmt);
+	  else if (! node->get_edge (stmt))
+	    {
+	      edge = node->create_edge (callee, stmt, count, freq);
+	      edge->inline_failed = reason;
+	    }
 
-	if (node->clones)
-	  node = node->clones;
-	else if (node->next_sibling_clone)
-	  node = node->next_sibling_clone;
-	else
-	  {
-	    while (node != this && !node->next_sibling_clone)
-	      node = node->clone_of;
-	    if (node != this)
-	      node = node->next_sibling_clone;
-	  }
-      }
+	  if (node->clones)
+	    node = node->clones;
+	  else if (node->next_sibling_clone)
+	    node = node->next_sibling_clone;
+	  else
+	    {
+	      while (node != this && !node->next_sibling_clone)
+		node = node->clone_of;
+	      if (node != this)
+		node = node->next_sibling_clone;
+	    }
+	}
 }
 
 /* Remove the node from cgraph and all inline clones inlined into it.
Index: ipa-inline-transform.c
===================================================================
--- ipa-inline-transform.c	(revision 236317)
+++ ipa-inline-transform.c	(working copy)
@@ -506,6 +506,22 @@ save_inline_function_body (struct cgraph
 
   /* first_clone will be turned into real function.  */
   first_clone = node->clones;
+
+  /* Arrange first clone to not be thunk as those do not have bodies.  */
+  if (first_clone->thunk.thunk_p)
+    {
+      while (first_clone->thunk.thunk_p)
+        first_clone = first_clone->next_sibling_clone;
+      first_clone->prev_sibling_clone->next_sibling_clone
+	= first_clone->next_sibling_clone;
+      if (first_clone->next_sibling_clone)
+	first_clone->next_sibling_clone->prev_sibling_clone
+	   = first_clone->prev_sibling_clone;
+      first_clone->next_sibling_clone = node->clones;
+      first_clone->prev_sibling_clone = NULL;
+      node->clones->prev_sibling_clone = first_clone;
+      node->clones = first_clone;
+    }
   first_clone->decl = copy_node (node->decl);
   first_clone->decl->decl_with_vis.symtab_node = first_clone;
   gcc_assert (first_clone == cgraph_node::get (first_clone->decl));
@@ -514,7 +530,8 @@ save_inline_function_body (struct cgraph
      first_clone.  */
   if (first_clone->next_sibling_clone)
     {
-      for (n = first_clone->next_sibling_clone; n->next_sibling_clone; n = n->next_sibling_clone)
+      for (n = first_clone->next_sibling_clone; n->next_sibling_clone;
+	   n = n->next_sibling_clone)
         n->clone_of = first_clone;
       n->clone_of = first_clone;
       n->next_sibling_clone = first_clone->clones;
@@ -587,9 +604,10 @@ preserve_function_body_p (struct cgraph_
   gcc_assert (symtab->global_info_ready);
   gcc_assert (!node->alias && !node->thunk.thunk_p);
 
-  /* Look if there is any clone around.  */
-  if (node->clones && !node->clones->thunk.thunk_p)
-    return true;
+  /* Look if there is any non-thunk clone around.  */
+  for (node = node->clones; node; node = node->next_sibling_clone)
+    if (!node->thunk.thunk_p)
+      return true;
   return false;
 }
 
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 236317)
+++ lto-cgraph.c	(working copy)
@@ -259,7 +259,7 @@ lto_output_edge (struct lto_simple_outpu
   streamer_write_gcov_count_stream (ob->main_stream, edge->count);
 
   bp = bitpack_create (ob->main_stream);
-  uid = (!gimple_has_body_p (edge->caller->decl)
+  uid = (!gimple_has_body_p (edge->caller->decl) || edge->caller->thunk.thunk_p
 	 ? edge->lto_stmt_uid : gimple_uid (edge->call_stmt) + 1);
   bp_pack_enum (&bp, cgraph_inline_failed_t,
 	        CIF_N_REASONS, edge->inline_failed);
@@ -398,7 +398,8 @@ lto_output_node (struct lto_simple_outpu
 
   boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node);
 
-  if (node->analyzed && (!boundary_p || node->alias || node->thunk.thunk_p))
+  if (node->analyzed && (!boundary_p || node->alias
+			 || (node->thunk.thunk_p && !node->global.inlined_to)))
     tag = LTO_symtab_analyzed_node;
   else
     tag = LTO_symtab_unavail_node;
Index: lto-streamer-in.c
===================================================================
--- lto-streamer-in.c	(revision 236317)
+++ lto-streamer-in.c	(working copy)
@@ -953,7 +953,8 @@ fixup_call_stmt_edges (struct cgraph_nod
   if (orig->clones)
     for (node = orig->clones; node != orig;)
       {
-	fixup_call_stmt_edges_1 (node, stmts, fn);
+	if (!node->thunk.thunk_p)
+	  fixup_call_stmt_edges_1 (node, stmts, fn);
 	if (node->clones)
 	  node = node->clones;
 	else if (node->next_sibling_clone)
Index: tree-inline.c
===================================================================
--- tree-inline.c	(revision 236317)
+++ tree-inline.c	(working copy)
@@ -2063,7 +2063,7 @@ copy_bb (copy_body_data *id, basic_block
 		  && id->dst_node->definition
 		  && (fn = gimple_call_fndecl (stmt)) != NULL)
 		{
-		  struct cgraph_node *dest = cgraph_node::get (fn);
+		  struct cgraph_node *dest = cgraph_node::get_create (fn);
 
 		  /* We have missing edge in the callgraph.  This can happen
 		     when previous inlining turned an indirect call into a


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