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]

Fix i386 wrong code issues introduced by the local flag fix


Hi,
this segfault in c-c++-common/torture/builtin-arith-overflow-12.c is caused
by fact that we split ltrans units separating call to alias of local function
and its target.  Because LTO partitioning turns aliases in boundaries into
normal symbols, we end up checking alias for can_change_signature_p that is
false.

This is just a manifestation of deeper problem that we do not represent aliases
between external symbols. Doing so is also needed to get address equality and
alias analysis right among other details. While I was aware of this issue, I
managed to delay proper fix until wrong code issues came.

This patch teaches middle-end about external aliases it
 1) makes symbol_table::remove_unreachable_nodes to not remove aliases from
    boundaries
 2) teach lto-cgraph to do right thing about streaming: insert alias
    targets to the boundary and stream the references

Same thing is also done for thunks as for good part of IPA optimizers these
are similar to aliases.

I also removed cgrpah_node::global_info that is unused and secured
cgraph_node::local_info and cgraph_node::rtl_info for aliases.

Bootstrapped/regtested x86_64-linux, will commit it after lto-bootstrapping.

Honza

	PR ipa/65005
	* ipa-visibility.c (cgraph_node::non_local_p): Turn into static
	function.
	* symtab.c (symtab_node::verify_base): Remove check that non-definitions
	have no comdat group.
	* lto-cgraph.c (lto_output_node): Always output thunk and alias info.
	(lto_output_varpool_node): Always output alias info.
	(output_refs): Output refs of boundary aliases, too.
	(compute_ltrans_boundary): Add alias and thunk target into boundaries.
	(output_symtab): Output call eges in thunks in boundary.
	(get_alias_symbol): Remove.
	(input_node, input_varpool_node): Do not special case weakrefs.
	* ipa.c (symbol_table::remove_unreachable_nodes): Do not remove
	alias and thunks targets in the boundary; do not take removed symbols
	from their comdat groups.
	* cgraph.c (cgraph_node::local_info): Look through aliases and thunks.
	(cgraph_node::global_info): Remove.
	(cgraph_node::rtl_info): Look through aliases and thunks.
	* cgrpah.h (global_info): Remove.
	(non_local_p): Remove.
Index: ipa-visibility.c
===================================================================
--- ipa-visibility.c	(revision 220606)
+++ ipa-visibility.c	(working copy)
@@ -101,8 +101,8 @@ along with GCC; see the file COPYING3.
 
 /* Return true when NODE can not be local. Worker for cgraph_local_node_p.  */
 
-bool
-cgraph_node::non_local_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
+static bool
+non_local_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
 {
   return !(node->only_called_directly_or_aliased_p ()
 	   /* i386 would need update to output thunk with locak calling
@@ -124,7 +124,7 @@ cgraph_node::local_p (void)
 
    if (n->thunk.thunk_p)
      return n->callees->callee->local_p ();
-   return !n->call_for_symbol_thunks_and_aliases (cgraph_node::non_local_p,
+   return !n->call_for_symbol_thunks_and_aliases (non_local_p,
 						  NULL, true);
 					
 }
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 220606)
+++ lto-cgraph.c	(working copy)
@@ -432,14 +432,13 @@ lto_output_node (struct lto_simple_outpu
   struct cgraph_node *clone_of, *ultimate_clone_of;
   ipa_opt_pass_d *pass;
   int i;
-  bool alias_p;
   const char *comdat;
   const char *section;
   tree group;
 
   boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node);
 
-  if (node->analyzed && !boundary_p)
+  if (node->analyzed && (!boundary_p || node->alias || node->thunk.thunk_p))
     tag = LTO_symtab_analyzed_node;
   else
     tag = LTO_symtab_unavail_node;
@@ -565,14 +564,7 @@ lto_output_node (struct lto_simple_outpu
 		     || referenced_from_other_partition_p (node, encoder)), 1);
   bp_pack_value (&bp, node->lowered, 1);
   bp_pack_value (&bp, in_other_partition, 1);
-  /* Real aliases in a boundary become non-aliases. However we still stream
-     alias info on weakrefs. 
-     TODO: We lose a bit of information here - when we know that variable is
-     defined in other unit, we may use the info on aliases to resolve 
-     symbol1 != symbol2 type tests that we can do only for locally defined objects
-     otherwise.  */
-  alias_p = node->alias && (!boundary_p || node->weakref);
-  bp_pack_value (&bp, alias_p, 1);
+  bp_pack_value (&bp, node->alias, 1);
   bp_pack_value (&bp, node->weakref, 1);
   bp_pack_value (&bp, node->frequency, 2);
   bp_pack_value (&bp, node->only_called_at_startup, 1);
@@ -581,14 +573,14 @@ lto_output_node (struct lto_simple_outpu
   bp_pack_value (&bp, node->calls_comdat_local, 1);
   bp_pack_value (&bp, node->icf_merged, 1);
   bp_pack_value (&bp, node->nonfreeing_fn, 1);
-  bp_pack_value (&bp, node->thunk.thunk_p && !boundary_p, 1);
+  bp_pack_value (&bp, node->thunk.thunk_p, 1);
   bp_pack_enum (&bp, ld_plugin_symbol_resolution,
 	        LDPR_NUM_KNOWN, node->resolution);
   bp_pack_value (&bp, node->instrumentation_clone, 1);
   streamer_write_bitpack (&bp);
   streamer_write_data_stream (ob->main_stream, section, strlen (section) + 1);
 
-  if (node->thunk.thunk_p && !boundary_p)
+  if (node->thunk.thunk_p)
     {
       streamer_write_uhwi_stream
 	 (ob->main_stream,
@@ -618,7 +610,6 @@ lto_output_varpool_node (struct lto_simp
   bool boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node);
   struct bitpack_d bp;
   int ref;
-  bool alias_p;
   const char *comdat;
   const char *section;
   tree group;
@@ -638,8 +629,7 @@ lto_output_varpool_node (struct lto_simp
   bp_pack_value (&bp, node->implicit_section, 1);
   bp_pack_value (&bp, node->writeonly, 1);
   bp_pack_value (&bp, node->definition, 1);
-  alias_p = node->alias && (!boundary_p || node->weakref);
-  bp_pack_value (&bp, alias_p, 1);
+  bp_pack_value (&bp, node->alias, 1);
   bp_pack_value (&bp, node->weakref, 1);
   bp_pack_value (&bp, node->analyzed && !boundary_p, 1);
   gcc_assert (node->definition || !node->analyzed);
@@ -794,18 +784,18 @@ output_outgoing_cgraph_edges (struct cgr
 static void
 output_refs (lto_symtab_encoder_t encoder)
 {
-  lto_symtab_encoder_iterator lsei;
   struct lto_simple_output_block *ob;
   int count;
   struct ipa_ref *ref;
-  int i;
 
   ob = lto_create_simple_output_block (LTO_section_refs);
 
-  for (lsei = lsei_start_in_partition (encoder); !lsei_end_p (lsei);
-       lsei_next_in_partition (&lsei))
+  for (int i = 0; i < lto_symtab_encoder_size (encoder); i++)
     {
-      symtab_node *node = lsei_node (lsei);
+      symtab_node *node = lto_symtab_encoder_deref (encoder, i);
+
+      if (!node->alias && !lto_symtab_encoder_in_partition_p (encoder, node))
+	continue;
 
       count = node->ref_list.nreferences ();
       if (count)
@@ -813,7 +803,7 @@ output_refs (lto_symtab_encoder_t encode
 	  streamer_write_gcov_count_stream (ob->main_stream, count);
 	  streamer_write_uhwi_stream (ob->main_stream,
 				     lto_symtab_encoder_lookup (encoder, node));
-	  for (i = 0; node->iterate_reference (i, ref); i++)
+	  for (int i = 0; node->iterate_reference (i, ref); i++)
 	    lto_output_ref (ob, ref, encoder);
 	}
     }
@@ -987,6 +977,19 @@ compute_ltrans_boundary (lto_symtab_enco
 		}
 	    }
     }
+  /* Be sure to also insert alias targert and thunk callees.  These needs
+     to stay to aid local calling conventions.  */
+  for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
+    {
+      symtab_node *node = lto_symtab_encoder_deref (encoder, i);
+      cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
+
+      if (node->alias && node->analyzed)
+	create_references (encoder, node);
+      if (cnode
+	  && cnode->thunk.thunk_p)
+	add_node_to (encoder, cnode->callees->callee, false);
+    }
   lto_symtab_encoder_delete (in_encoder);
   return encoder;
 }
@@ -998,7 +1001,6 @@ output_symtab (void)
 {
   struct cgraph_node *node;
   struct lto_simple_output_block *ob;
-  lto_symtab_encoder_iterator lsei;
   int i, n_nodes;
   lto_symtab_encoder_t encoder;
 
@@ -1028,12 +1030,16 @@ output_symtab (void)
     }
 
   /* Go over the nodes in SET again to write edges.  */
-  for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
-       lsei_next_function_in_partition (&lsei))
+  for (int i = 0; i < lto_symtab_encoder_size (encoder); i++)
     {
-      node = lsei_cgraph_node (lsei);
-      output_outgoing_cgraph_edges (node->callees, ob, encoder);
-      output_outgoing_cgraph_edges (node->indirect_calls, ob, encoder);
+      node = dyn_cast <cgraph_node *> (lto_symtab_encoder_deref (encoder, i));
+      if (node
+	  && (node->thunk.thunk_p
+	      || lto_symtab_encoder_in_partition_p (encoder, node)))
+	{
+	  output_outgoing_cgraph_edges (node->callees, ob, encoder);
+	  output_outgoing_cgraph_edges (node->indirect_calls, ob, encoder);
+	}
     }
 
   streamer_write_uhwi_stream (ob->main_stream, 0);
Index: symtab.c
===================================================================
--- symtab.c	(revision 220606)
+++ symtab.c	(working copy)
@@ -1070,11 +1070,6 @@ symtab_node::verify_base (void)
 	  error ("same_comdat_group list across different groups");
 	  error_found = true;
 	}
-      if (!n->definition)
-	{
-	  error ("Node has same_comdat_group but it is not a definition");
-	  error_found = true;
-	}
       if (n->type != type)
 	{
 	  error ("mixing different types of symbol in same comdat groups is not supported");
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 220606)
+++ cgraph.c	(working copy)
@@ -1846,20 +1846,7 @@ cgraph_node::local_info (tree decl)
   cgraph_node *node = get (decl);
   if (!node)
     return NULL;
-  return &node->local;
-}
-
-/* Return global info for the compiled function.  */
-
-cgraph_global_info *
-cgraph_node::global_info (tree decl)
-{
-  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
-    && symtab->global_info_ready);
-  cgraph_node *node = get (decl);
-  if (!node)
-    return NULL;
-  return &node->global;
+  return &node->ultimate_alias_target ()->local;
 }
 
 /* Return local info for the compiled function.  */
@@ -1869,11 +1856,13 @@ cgraph_node::rtl_info (tree decl)
 {
   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
   cgraph_node *node = get (decl);
-  if (!node
-      || (decl != current_function_decl
-	  && !TREE_ASM_WRITTEN (node->decl)))
+  if (!node)
+    return NULL;
+  node = node->ultimate_alias_target ();
+  if (node->decl != current_function_decl
+      && !TREE_ASM_WRITTEN (node->decl))
     return NULL;
-  return &node->rtl;
+  return &node->ultimate_alias_target ()->rtl;
 }
 
 /* Return a string describing the failure REASON.  */
Index: cgraph.h
===================================================================
--- cgraph.h	(revision 220606)
+++ cgraph.h	(working copy)
@@ -1164,9 +1164,6 @@ public:
   /* Return local info for the compiled function.  */
   static cgraph_local_info *local_info (tree decl);
 
-  /* Return global info for the compiled function.  */
-  static cgraph_global_info *global_info (tree);
-
   /* Return local info for the compiled function.  */
   static cgraph_rtl_info *rtl_info (tree);
 
@@ -1187,10 +1184,6 @@ public:
     return node->used_from_object_file_p ();
   }
 
-  /* Return true when cgraph_node can not be local.
-     Worker for cgraph_local_node_p.  */
-  static bool non_local_p (cgraph_node *node, void *);
-
   /* Verify whole cgraph structure.  */
   static void DEBUG_FUNCTION verify_cgraph_nodes (void);
 
Index: ipa.c
===================================================================
--- ipa.c	(revision 220606)
+++ ipa.c	(working copy)
@@ -383,7 +383,11 @@ symbol_table::remove_unreachable_nodes (
       /* If we are processing symbol in boundary, mark its AUX pointer for
 	 possible later re-processing in enqueue_node.  */
       if (in_boundary_p)
-	node->aux = (void *)2;
+	{
+	  node->aux = (void *)2;
+	  if (node->alias && node->analyzed)
+	    enqueue_node (node->get_alias_target (), &first, &reachable);
+	}
       else
 	{
 	  if (TREE_CODE (node->decl) == FUNCTION_DECL
@@ -486,6 +490,9 @@ symbol_table::remove_unreachable_nodes (
 		}
 
 	    }
+	  else if (cnode->thunk.thunk_p)
+	    enqueue_node (cnode->callees->callee, &first, &reachable);
+	      
 	  /* If any reachable function has simd clones, mark them as
 	     reachable as well.  */
 	  if (cnode->simd_clones)
@@ -534,7 +541,7 @@ symbol_table::remove_unreachable_nodes (
 	    node->release_body ();
 	  else if (!node->clone_of)
 	    gcc_assert (in_lto_p || DECL_RESULT (node->decl));
-	  if (node->definition)
+	  if (node->definition && !node->alias && !node->thunk.thunk_p)
 	    {
 	      if (file)
 		fprintf (file, " %s/%i", node->name (), node->order);
@@ -554,7 +561,6 @@ symbol_table::remove_unreachable_nodes (
 	      if (!node->in_other_partition)
 		node->local.local = false;
 	      node->remove_callees ();
-	      node->remove_from_same_comdat_group ();
 	      node->remove_all_references ();
 	      changed = true;
 	      if (node->thunk.thunk_p
@@ -614,7 +620,7 @@ symbol_table::remove_unreachable_nodes (
 	  vnode->remove ();
 	  changed = true;
 	}
-      else if (!reachable.contains (vnode))
+      else if (!reachable.contains (vnode) && !vnode->alias)
         {
 	  tree init;
 	  if (vnode->definition)


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