diff mbox

Fix ICE building Mozilla with LTO

Message ID 20130317154218.GA18948@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka March 17, 2013, 3:42 p.m. UTC
Hi,
current mainline (as well as release branch) dies by ICE in cgraph_mark_address_taken
because we attempt to create reference to inline clone.  This happens becuase of ltrans
propagation for pretty special case from devirtualization missed by WPA but taken by
constant propagation happening as part of clone creating.

In this case we need to re-create symbol node for the virtual call that we fail t do so.
It is the same case as in ipa_make_edge_direct_to_target where I added the necessary code.

This patch is not aesthetically pleasing because I plan to solve the problem for 4.9
by moving cgraph clones out of symbol table hash, but it is not trivial to do so and
I hope this form of patch is fine for release branch.

Bootstrapped/regtested x86_64-linux, I will commit it to mainline. Does it seem OK for
release branch? (it is technically a regression even if I do not have better testcase
than Mozilla version that does not build with 4.7.  It depends heavily on partitioning
decisions making it hard to reduce).

Honza

	* cgraph.h (cgraph_get_create_real_symbol_node): Declare.
	* cgraph.c (cgraph_get_create_real_symbol_node): New function.
	* cgrpahbuild.c: Use cgraph_get_create_real_symbol_node instead
	of cgraph_get_create_node.
	* ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
diff mbox

Patch

Index: cgraph.h
===================================================================
--- cgraph.h	(revision 196601)
+++ cgraph.h	(working copy)
@@ -575,6 +575,7 @@ 
 struct cgraph_node * cgraph_create_node (tree);
 struct cgraph_node * cgraph_create_empty_node (void);
 struct cgraph_node * cgraph_get_create_node (tree);
+struct cgraph_node * cgraph_get_create_real_symbol_node (tree);
 struct cgraph_node * cgraph_same_body_alias (struct cgraph_node *, tree, tree);
 struct cgraph_node * cgraph_add_thunk (struct cgraph_node *, tree, tree, bool, HOST_WIDE_INT,
 				       HOST_WIDE_INT, tree, tree);
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 196601)
+++ cgraph.c	(working copy)
@@ -2595,4 +2597,47 @@ 
   FOR_EACH_FUNCTION (node)
     verify_cgraph_node (node);
 }
+
+/* Create external decl node for DECL.
+   The difference i nbetween cgraph_get_create_node and
+   cgraph_get_create_real_symbol_node is that cgraph_get_create_node
+   may return inline clone, while cgraph_get_create_real_symbol_node
+   will create a new node in this case.
+   FIXME: This function should be removed once clones are put out of decl
+   hash.  */
+
+struct cgraph_node *
+cgraph_get_create_real_symbol_node (tree decl)
+{
+  struct cgraph_node *first_clone = cgraph_get_node (decl);
+  struct cgraph_node *node;
+  /* create symbol table node.  even if inline clone exists, we can not take
+     it as a target of non-inlined call.  */
+  node = cgraph_get_node (decl);
+  if (node && !node->global.inlined_to)
+    return node;
+
+  node = cgraph_create_node (decl);
+
+  /* ok, we previously inlined the function, then removed the offline copy and
+     now we want it back for external call.  this can happen when devirtualizing
+     while inlining function called once that happens after extern inlined and
+     virtuals are already removed.  in this case introduce the external node
+     and make it available for call.  */
+  if (first_clone)
+    {
+      first_clone->clone_of = node;
+      node->clones = first_clone;
+      symtab_prevail_in_asm_name_hash ((symtab_node) node);
+      symtab_insert_node_to_hashtable ((symtab_node) node);
+      if (dump_file)
+	fprintf (dump_file, "Introduced new external node "
+		 "(%s/%i) and turned into root of the clone tree.\n",
+		 xstrdup (cgraph_node_name (node)), node->uid);
+    }
+  else if (dump_file)
+    fprintf (dump_file, "Introduced new external node "
+	     "(%s/%i).\n", xstrdup (cgraph_node_name (node)), node->uid);
+  return node;
+}
 #include "gt-cgraph.h"
Index: cgraphbuild.c
===================================================================
--- cgraphbuild.c	(revision 196601)
+++ cgraphbuild.c	(working copy)
@@ -73,7 +73,7 @@ 
       decl = get_base_var (*tp);
       if (TREE_CODE (decl) == FUNCTION_DECL)
 	{
-	  struct cgraph_node *node = cgraph_get_create_node (decl);
+	  struct cgraph_node *node = cgraph_get_create_real_symbol_node (decl);
 	  if (!ctx->only_vars)
 	    cgraph_mark_address_taken_node (node);
 	  ipa_record_reference ((symtab_node)ctx->varpool_node,
@@ -143,7 +143,7 @@ 
     {
       struct cgraph_node *per_node;
 
-      per_node = cgraph_get_create_node (DECL_FUNCTION_PERSONALITY (node->symbol.decl));
+      per_node = cgraph_get_create_real_symbol_node (DECL_FUNCTION_PERSONALITY (node->symbol.decl));
       ipa_record_reference ((symtab_node)node, (symtab_node)per_node, IPA_REF_ADDR, NULL);
       cgraph_mark_address_taken_node (per_node);
     }
@@ -223,7 +223,7 @@ 
   addr = get_base_address (addr);
   if (TREE_CODE (addr) == FUNCTION_DECL)
     {
-      struct cgraph_node *node = cgraph_get_create_node (addr);
+      struct cgraph_node *node = cgraph_get_create_real_symbol_node (addr);
       cgraph_mark_address_taken_node (node);
       ipa_record_reference ((symtab_node)data,
 			    (symtab_node)node,
@@ -252,7 +252,7 @@ 
     {
       /* ??? This can happen on platforms with descriptors when these are
 	 directly manipulated in the code.  Pretend that it's an address.  */
-      struct cgraph_node *node = cgraph_get_create_node (t);
+      struct cgraph_node *node = cgraph_get_create_real_symbol_node (t);
       cgraph_mark_address_taken_node (node);
       ipa_record_reference ((symtab_node)data,
 			    (symtab_node)node,
@@ -330,7 +330,7 @@ 
 	    {
 	      tree fn = gimple_omp_parallel_child_fn (stmt);
 	      ipa_record_reference ((symtab_node)node,
-				    (symtab_node)cgraph_get_create_node (fn),
+				    (symtab_node)cgraph_get_create_real_symbol_node (fn),
 				    IPA_REF_ADDR, stmt);
 	    }
 	  if (gimple_code (stmt) == GIMPLE_OMP_TASK)
@@ -338,12 +338,12 @@ 
 	      tree fn = gimple_omp_task_child_fn (stmt);
 	      if (fn)
 		ipa_record_reference ((symtab_node)node,
-				      (symtab_node) cgraph_get_create_node (fn),
+				      (symtab_node) cgraph_get_create_real_symbol_node (fn),
 				      IPA_REF_ADDR, stmt);
 	      fn = gimple_omp_task_copy_fn (stmt);
 	      if (fn)
 		ipa_record_reference ((symtab_node)node,
-				      (symtab_node)cgraph_get_create_node (fn),
+				      (symtab_node)cgraph_get_create_real_symbol_node (fn),
 				      IPA_REF_ADDR, stmt);
 	    }
 	}
Index: ipa-prop.c
===================================================================
--- ipa-prop.c	(revision 196601)
+++ ipa-prop.c	(working copy)
@@ -2117,7 +2117,6 @@ 
      we may create the first reference to the object in the unit.  */
   if (!callee || callee->global.inlined_to)
     {
-      struct cgraph_node *first_clone = callee;
 
       /* We are better to ensure we can refer to it.
 	 In the case of static functions we are out of luck, since we already	
@@ -2133,31 +2132,7 @@ 
 		     xstrdup (cgraph_node_name (ie->callee)), ie->callee->uid);
 	  return NULL;
 	}
-
-      /* Create symbol table node.  Even if inline clone exists, we can not take
-	 it as a target of non-inlined call.  */
-      callee = cgraph_create_node (target);
-
-      /* OK, we previously inlined the function, then removed the offline copy and
-	 now we want it back for external call.  This can happen when devirtualizing
-	 while inlining function called once that happens after extern inlined and
-	 virtuals are already removed.  In this case introduce the external node
-	 and make it available for call.  */
-      if (first_clone)
-	{
-	  first_clone->clone_of = callee;
-	  callee->clones = first_clone;
-	  symtab_prevail_in_asm_name_hash ((symtab_node)callee);
-	  symtab_insert_node_to_hashtable ((symtab_node)callee);
-	  if (dump_file)
-	    fprintf (dump_file, "ipa-prop: Introduced new external node "
-		     "(%s/%i) and turned into root of the clone tree.\n",
-		     xstrdup (cgraph_node_name (callee)), callee->uid);
-	}
-      else if (dump_file)
-	fprintf (dump_file, "ipa-prop: Introduced new external node "
-		 "(%s/%i).\n",
-		 xstrdup (cgraph_node_name (callee)), callee->uid);
+      callee = cgraph_get_create_real_symbol_node (target);
     }
   ipa_check_create_node_params ();