public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Fix i386 wrong code issues introduced by the local flag fix
@ 2015-02-11  6:34 Jan Hubicka
       [not found] ` <20150211071042.GA338@x4>
  0 siblings, 1 reply; 2+ messages in thread
From: Jan Hubicka @ 2015-02-11  6:34 UTC (permalink / raw)
  To: gcc-patches

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)

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Fix i386 wrong code issues introduced by the local flag fix
       [not found]     ` <20150211100355.GB340@x4>
@ 2015-02-11 19:02       ` Jan Hubicka
  0 siblings, 0 replies; 2+ messages in thread
From: Jan Hubicka @ 2015-02-11 19:02 UTC (permalink / raw)
  To: Markus Trippelsdorf, gcc-patches; +Cc: Jan Hubicka

Hi,
this patch fixes ICE when building firefox reported by Markus:
> 
> lto1: internal compiler error: Segmentation fault
> 0x106e1feb crash_signal
>         ../../gcc/gcc/toplev.c:383
> 0x10589cd4 lto_get_decl_name_mapping(lto_file_decl_data*, char const*)
>         ../../gcc/gcc/lto-section-in.c:369
> 0x1057bb6b copy_function_or_variable
>         ../../gcc/gcc/lto-streamer-out.c:2194
> 0x1057df9b lto_output()
>         ../../gcc/gcc/lto-streamer-out.c:2289
> 0x105edd87 write_lto
>         ../../gcc/gcc/passes.c:2405
> 0x105f3073 ipa_write_optimization_summaries(lto_symtab_encoder_d*)
>         ../../gcc/gcc/passes.c:2607
> 0x1018f6ab do_stream_out
>         ../../gcc/gcc/lto/lto.c:2480
> 0x10190a33 stream_out
>         ../../gcc/gcc/lto/lto.c:2544
> 0x10190a33 lto_wpa_write_files
>         ../../gcc/gcc/lto/lto.c:2661
> 0x1019c0a7 do_whole_program_analysis
>         ../../gcc/gcc/lto/lto.c:3331
> 0x1019c0a7 lto_main()
>         ../../gcc/gcc/lto/lto.c:3451
> 

I tested it on Firefox, will commit after bootstrap&regtesting finishes (x86_64)

Honza

	* ipa.c (symbol_table::remove_unreachable_nodes): Avoid releasing
	bodies of thunks; comment on why.
	* symtab.c (symtab_node::get_partitioning_class): Aliases of extern
	symbols are extern.
Index: ipa.c
===================================================================
--- ipa.c	(revision 220608)
+++ ipa.c	(working copy)
@@ -537,7 +537,13 @@ symbol_table::remove_unreachable_nodes (
       /* If node is unreachable, remove its body.  */
       else if (!reachable.contains (node))
         {
-	  if (!body_needed_for_clonning.contains (node->decl))
+	  /* We keep definitions of thunks and aliases in the boundary so
+	     we can walk to the ultimate alias targets and function symbols
+	     reliably.  */
+	  if (node->alias || node->thunk.thunk_p)
+	    ;
+	  else if (!body_needed_for_clonning.contains (node->decl)
+	      && !node->alias && !node->thunk.thunk_p)
 	    node->release_body ();
 	  else if (!node->clone_of)
 	    gcc_assert (in_lto_p || DECL_RESULT (node->decl));
Index: symtab.c
===================================================================
--- symtab.c	(revision 220608)
+++ symtab.c	(working copy)
@@ -1779,6 +1779,8 @@ symtab_node::get_partitioning_class (voi
 
   if (varpool_node *vnode = dyn_cast <varpool_node *> (this))
     {
+      if (alias && definition && !ultimate_alias_target ()->definition)
+	return SYMBOL_EXTERNAL;
       /* Constant pool references use local symbol names that can not
          be promoted global.  We should never put into a constant pool
          objects that can not be duplicated across partitions.  */
@@ -1790,7 +1792,7 @@ symtab_node::get_partitioning_class (voi
      Handle them as external; compute_ltrans_boundary take care to make
      proper things to happen (i.e. to make them appear in the boundary but
      with body streamed, so clone can me materialized).  */
-  else if (!dyn_cast <cgraph_node *> (this)->definition)
+  else if (!dyn_cast <cgraph_node *> (this)->function_symbol ()->definition)
     return SYMBOL_EXTERNAL;
 
   /* Linker discardable symbols are duplicated to every use unless they are

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-02-11 19:02 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-11  6:34 Fix i386 wrong code issues introduced by the local flag fix Jan Hubicka
     [not found] ` <20150211071042.GA338@x4>
     [not found]   ` <20150211091523.GA24602@kam.mff.cuni.cz>
     [not found]     ` <20150211100355.GB340@x4>
2015-02-11 19:02       ` Jan Hubicka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).