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 partition WRT static variables taking address of labels


Hi,
this patch fixes problem with partitioning WRT named labels.  This problem
reproduces with linux kernel LTO and also on firefox with -fno-toplevel-reorder
at least.

Bootstrapped/regtested x86_64-linux and tested it fixes the problem on Firefx,
intend to commit it tomorrow after some more testing on chromium

The patch may need a bit more tweaking WRT nested functions contains nonlocal
adresses taken, but that is even more exotic than the problem I am trying
to solve so I think it can wait for next stage1. This patch should be backportable
to earlier releases after reversing the C++ APi changes.

Honza

	PR lto/50676
	* symtab.c (symtab_node::get_partitioning_class): Local static
	taking named label inherits partitioning property of the function
	it belong to.
	* lto-cgraph.c (lto_output_varpool_node, input_varpool_node): Stream
	contains_named_label.
	* tree.c (decl_address_ip_invariant_p): LABEL_DECL is not IP
	invariant.
	* cgraph.h (varpool_node): Add contains_named_label.
	* cgraphbuild.c (record_reference): Record contains_named_label.
	* lto-partition.c (add_references_to_partition,
	add_symbol_to_partition_1): Local static var should stay in
	same partition as its containing function when it reffer to
	named label.
	(add_sorted_nodes): Skip static var referring named label.
	(lto_balanced_map): Likewise.
	* varpool.c (varpool_node::dump): Dump contains_named_label.
	* ipa.c (symbol_table::remove_unreachable_nodes): Variable
	referring named label keeps its function alive.

	* gcc.dg/lto/named-label.c: New testcase.
Index: symtab.c
===================================================================
--- symtab.c	(revision 221757)
+++ symtab.c	(working copy)
@@ -1682,6 +1682,11 @@ symtab_node::get_partitioning_class (voi
 
   if (varpool_node *vnode = dyn_cast <varpool_node *> (this))
     {
+      /* Static variables referring named label are always handled the same way
+	 as the function they belong to.  */
+      if (vnode->contains_named_label)
+	return cgraph_node::get (decl_function_context (decl))
+		->get_partitioning_class ();
       if (alias && definition && !ultimate_alias_target ()->definition)
 	return SYMBOL_EXTERNAL;
       /* Constant pool references use local symbol names that can not
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 221757)
+++ lto-cgraph.c	(working copy)
@@ -662,6 +663,7 @@ lto_output_varpool_node (struct lto_simp
   bp_pack_value (&bp, node->tls_model, 3);
   bp_pack_value (&bp, node->used_by_single_function, 1);
   bp_pack_value (&bp, node->need_bounds_init, 1);
+  bp_pack_value (&bp, node->contains_named_label, 1);
   streamer_write_bitpack (&bp);
 
   group = node->get_comdat_group ();
@@ -1413,6 +1416,7 @@ input_varpool_node (struct lto_file_decl
   node->tls_model = (enum tls_model)bp_unpack_value (&bp, 3);
   node->used_by_single_function = (enum tls_model)bp_unpack_value (&bp, 1);
   node->need_bounds_init = bp_unpack_value (&bp, 1);
+  node->contains_named_label = bp_unpack_value (&bp, 1);
   group = read_identifier (ib);
   if (group)
     {
Index: tree.c
===================================================================
--- tree.c	(revision 221757)
+++ tree.c	(working copy)
@@ -3149,7 +3149,12 @@ decl_address_ip_invariant_p (const_tree
 
   switch (TREE_CODE (op))
     {
+    /* Theoretically label decls can be considered IP invariants, but until
+       we are able to handle them as regular symbols (i.e. output with
+       non-local visibility), we really want them to be contained in a function
+       they belong to.  */
     case LABEL_DECL:
+      return false;
     case FUNCTION_DECL:
     case STRING_CST:
       return true;
Index: cgraph.h
===================================================================
--- cgraph.h	(revision 221757)
+++ cgraph.h	(working copy)
@@ -1778,6 +1780,9 @@ public:
      if we did not do any inter-procedural code movement.  */
   unsigned used_by_single_function : 1;
 
+  /* Set if te variable is contains a named label.  */
+  unsigned contains_named_label : 1;
+
 private:
   /* Assemble thunks and aliases associated to varpool node.  */
   void assemble_aliases (void);
Index: cgraphbuild.c
===================================================================
--- cgraphbuild.c	(revision 221757)
+++ cgraphbuild.c	(working copy)
@@ -112,6 +112,8 @@ record_reference (tree *tp, int *walk_su
 	  varpool_node *vnode = varpool_node::get_create (decl);
 	  ctx->varpool_node->create_reference (vnode, IPA_REF_ADDR);
 	}
+      if (TREE_CODE (decl) == LABEL_DECL)
+	ctx->varpool_node->contains_named_label = true;
       *walk_subtrees = 0;
       break;
 
Index: lto/lto-partition.c
===================================================================
--- lto/lto-partition.c	(revision 221757)
+++ lto/lto-partition.c	(working copy)
@@ -113,6 +113,14 @@ add_references_to_partition (ltrans_part
   for (i = 0; node->iterate_reference (i, ref); i++)
     if (ref->referred->get_partitioning_class () == SYMBOL_DUPLICATE)
       add_symbol_to_partition (part, ref->referred);
+    /* A static variable referring to named labels must go to the same
+       partition as a function it belongs to.  */
+    else if (is_a <varpool_node *> (ref->referred)
+	     && (dyn_cast <varpool_node *> (ref->referred)
+		 ->contains_named_label)
+	     && node->decl == decl_function_context (ref->referred->decl)
+	     && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
+      add_symbol_to_partition (part, ref->referred);
     /* References to a readonly variable may be constant foled into its value.
        Recursively look into the initializers of the constant variable and add
        references, too.  */
@@ -193,6 +201,14 @@ add_symbol_to_partition_1 (ltrans_partit
 	add_symbol_to_partition_1 (part, cnode->instrumented_version);
     }
 
+  /* Variables referring named labels must always go to the same section
+     as the function they belong to.  */
+  if (is_a <varpool_node *> (node)
+      && dyn_cast <varpool_node *> (node)->contains_named_label)
+    add_symbol_to_partition_1 (part,
+			         cgraph_node::get
+				    (decl_function_context (node->decl)));
+
   add_references_to_partition (part, node);
 
   /* Add all aliases associated with the symbol.  */
@@ -409,7 +425,12 @@ add_sorted_nodes (vec<symtab_node *> &ne
 
   next_nodes.qsort (varpool_node_cmp);
   FOR_EACH_VEC_ELT (next_nodes, i, node)
-    if (!symbol_partitioned_p (node))
+    if (!symbol_partitioned_p (node)
+	/* Local statics containing named labels always go after their
+	   functions.  Do not partition on them and wait for them to be
+	   dragged in, so we do not force reordering of the functions.  */
+	&& (!is_a <varpool_node *> (node)
+	    || !dyn_cast <varpool_node *> (node)->contains_named_label))
       add_symbol_to_partition (partition, node);
 }
 
@@ -636,6 +657,7 @@ lto_balanced_map (int n_lto_partitions)
 		  continue;
 		if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder
 		    && !vnode->no_reorder
+		    && !vnode->contains_named_label
 		    && vnode->get_partitioning_class () == SYMBOL_PARTITION)
 		  add_symbol_to_partition (partition, vnode);
 		index = lto_symtab_encoder_lookup (partition->encoder,
@@ -674,6 +696,7 @@ lto_balanced_map (int n_lto_partitions)
 		if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder
 		    && !vnode->no_reorder
 		    && !vnode->can_remove_if_no_refs_p ()
+		    && !vnode->contains_named_label
 		    && vnode->get_partitioning_class () == SYMBOL_PARTITION)
 		  add_symbol_to_partition (partition, vnode);
 		index = lto_symtab_encoder_lookup (partition->encoder,
Index: varpool.c
===================================================================
--- varpool.c	(revision 221757)
+++ varpool.c	(working copy)
@@ -256,6 +256,8 @@ varpool_node::dump (FILE *f)
     fprintf (f, " const-value-known");
   if (writeonly)
     fprintf (f, " write-only");
+  if (contains_named_label)
+    fprintf (f, " contains-named-label");
   if (tls_model)
     fprintf (f, " tls-%s", tls_model_names [tls_model]);
   fprintf (f, "\n");
Index: ipa.c
===================================================================
--- ipa.c	(revision 221757)
+++ ipa.c	(working copy)
@@ -406,6 +406,18 @@ symbol_table::remove_unreachable_nodes (
 		      n->used_as_abstract_origin = true;
 		}
 	    }
+
+	  /* Static variables referring local label needs the containing
+	     function to be output.  */
+	  if (is_a <varpool_node *> (node)
+	      && dyn_cast <varpool_node *> (node)->contains_named_label)
+	    {
+	      cgraph_node *cn
+		 = cgraph_node::get (decl_function_context (node->decl));
+	      if (!reachable.add (cn))
+		enqueue_node (cn, &first, &reachable);
+	    }
+	      
 	  /* If any symbol in a comdat group is reachable, force
 	     all externally visible symbols in the same comdat
 	     group to be reachable as well.  Comdat-local symbols
Index: testsuite/gcc.dg/lto/named-label.c
===================================================================
--- testsuite/gcc.dg/lto/named-label.c	(revision 0)
+++ testsuite/gcc.dg/lto/named-label.c	(revision 0)
@@ -0,0 +1,29 @@
+/* { dg-lto-do link } */
+/* { dg-lto-options { { -fPIC -flto -flto-partition=max } } } */
+void *p0,*p1;
+void test (void **p)
+{
+  if (p[0]==p[1])
+    __builtin_abort ();
+  p0=p[0];
+  p1=p[1];
+}
+void test2 (void **p)
+{
+  if (p[0]!=p0|| p[1] !=p1)
+    __builtin_abort ();
+}
+void ** t()
+{
+  static void * labelptr[2]={&&label, &&label2};
+label:
+  test (labelptr);
+label2:
+  return labelptr;
+}
+int
+main()
+{
+  void **labelptr = t();
+  test2 (labelptr);
+}


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