Patchwork More weakref fixes

login
register
mail settings
Submitter Jan Hubicka
Date Aug. 30, 2013, 3:54 p.m.
Message ID <20130830155405.GB4601@kam.mff.cuni.cz>
Download mbox | patch
Permalink /patch/271346/
State New
Headers show

Comments

Jan Hubicka - Aug. 30, 2013, 3:54 p.m.
Hi,
this patch fixes gcc.dg/tree-ssa/attr-alias.c on x86-64 target.
The problem here is that we attempt to create local alias since we consider weakref
of test() to be overwritable and at the same time available.
The change in cgraph_function_body_availability makes weakref to properly inherit
availability of their target (that is weak in the testcase).
Fixing it uncovered more issues - with -flto-partition=none and -O0 we run into problem
that cgraph edge redirections are not applied. This is becuase inliner is not run in
this scenario when it ought to be (precisely because edge redirection is happened).
So the patch removes ipa_inline's gate logic, makes it to not do something useless at
-O0 and also removes fixup_cfg pass that is really part of inliner's transform.

While updating varpool part of availability I noticed that it is wrong for vtables
and constant pool. Fixed thus.

Finally I noticed that symbol renaming is broken on non-weakref targets.

Bootstrapped/regtested x86_64-linux, comitted.

Honza
	* cgraph.c (cgraph_function_body_availability): Handle weakref
	correctly.
	* gcc.dg/tree-ssa/attr-alias.c: Rename test3 to test1 to match template
	and comment.
	* passes.def: Remove pass_fixup_cfg.
	* ipa-inline.c (ipa_inline): When not optimizing, do not inline;
	track when we need to remove functions.
	(gate_ipa_inline): Execute inlining always; add comment why.
	(pass_data_ipa_inline): Remove TODO_remove_functions.
	* ipa-inline-analysis.c (inline_generate_summary): When not optimizing
	do not produce summaries.
	* symtab.c (change_decl_assembler_name): Handle renaming of weakrefs.
	(symtab_nonoverwritable_alias): Assert we are not called on weakref.
	* varpool.c (cgraph_variable_initializer_availability): Fix weakrefs,
	constant pool and vtable.

Patch

Index: cgraph.c
===================================================================
--- cgraph.c	(revision 202093)
+++ cgraph.c	(working copy)
@@ -2046,6 +2046,8 @@  cgraph_function_body_availability (struc
     avail = AVAIL_NOT_AVAILABLE;
   else if (node->local.local)
     avail = AVAIL_LOCAL;
+  else if (node->symbol.alias && node->symbol.weakref)
+    cgraph_function_or_thunk_node (node, &avail);
   else if (!node->symbol.externally_visible)
     avail = AVAIL_AVAILABLE;
   /* Inline functions are safe to be analyzed even if their symbol can
Index: testsuite/gcc.dg/tree-ssa/attr-alias.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/attr-alias.c	(revision 202092)
+++ testsuite/gcc.dg/tree-ssa/attr-alias.c	(working copy)
@@ -8,7 +8,7 @@  int test()
    return 0;
 }
 static int test2() __attribute__ ((alias("test")));
-static int test3() __attribute__ ((weakref)) __attribute__ ((alias("test2")));
+static int test1() __attribute__ ((weakref)) __attribute__ ((alias("test2")));
 static int test4() __attribute__ ((weakref)) __attribute__ ((alias("test")));
 main()
 {
Index: passes.def
===================================================================
--- passes.def	(revision 202092)
+++ passes.def	(working copy)
@@ -126,7 +126,6 @@  along with GCC; see the file COPYING3.
   /* These passes are run after IPA passes on every function that is being
      output to the assembler file.  */
   INSERT_PASSES_AFTER (all_passes)
-  NEXT_PASS (pass_fixup_cfg);
   NEXT_PASS (pass_lower_eh_dispatch);
   NEXT_PASS (pass_all_optimizations);
   PUSH_INSERT_PASSES_WITHIN (pass_all_optimizations)
Index: ipa-inline.c
===================================================================
--- ipa-inline.c	(revision 202092)
+++ ipa-inline.c	(working copy)
@@ -1904,6 +1904,10 @@  ipa_inline (void)
     XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
   int i;
   int cold;
+  bool remove_functions = false;
+
+  if (!optimize)
+    return 0;
 
   if (in_lto_p && optimize)
     ipa_update_after_lto_read ();
@@ -1984,6 +1988,7 @@  ipa_inline (void)
 		{
 		  cgraph_resolve_speculation (edge, NULL);
 		  update = true;
+		  remove_functions = true;
 		}
 	    }
 	  if (update)
@@ -2018,6 +2023,7 @@  ipa_inline (void)
 		    }
 
 		  inline_call (node->callers, true, NULL, NULL, true);
+		  remove_functions = true;
 		  if (dump_file)
 		    fprintf (dump_file,
 			     " Inlined into %s which now has %i size\n",
@@ -2048,7 +2054,7 @@  ipa_inline (void)
   /* In WPA we use inline summaries for partitioning process.  */
   if (!flag_wpa)
     inline_free_summary ();
-  return 0;
+  return remove_functions ? TODO_remove_functions : 0;
 }
 
 /* Inline always-inline function calls in NODE.  */
@@ -2292,13 +2298,13 @@  make_pass_early_inline (gcc::context *ct
 /* When to run IPA inlining.  Inlining of always-inline functions
    happens during early inlining.
 
-   Enable inlining unconditoinally at -flto.  We need size estimates to
-   drive partitioning.  */
+   Enable inlining unconditoinally, because callgraph redirection
+   happens here.   */
 
 static bool
 gate_ipa_inline (void)
 {
-  return optimize || flag_lto || flag_wpa;
+  return true;
 }
 
 namespace {
@@ -2315,7 +2321,7 @@  const pass_data pass_data_ipa_inline =
   0, /* properties_provided */
   0, /* properties_destroyed */
   TODO_remove_functions, /* todo_flags_start */
-  ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
+  ( TODO_dump_symtab ), /* todo_flags_finish */
 };
 
 class pass_ipa_inline : public ipa_opt_pass_d
Index: ipa-inline-analysis.c
===================================================================
--- ipa-inline-analysis.c	(revision 202092)
+++ ipa-inline-analysis.c	(working copy)
@@ -3698,6 +3698,11 @@  inline_generate_summary (void)
 {
   struct cgraph_node *node;
 
+  /* When not optimizing, do not bother to analyze.  Inlining is still done
+     because edge redirection needs to happen there.  */
+  if (!optimize && !flag_lto && !flag_wpa)
+    return;
+
   function_insertion_hook_holder =
     cgraph_add_function_insertion_hook (&add_new_function, NULL);
 
Index: symtab.c
===================================================================
--- symtab.c	(revision 202092)
+++ symtab.c	(working copy)
@@ -390,6 +390,9 @@  change_decl_assembler_name (tree decl, t
       if (name == DECL_ASSEMBLER_NAME (decl))
 	return;
 
+      tree alias = (IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (decl))
+		    ? TREE_CHAIN (DECL_ASSEMBLER_NAME (decl))
+		    : NULL);
       if (node)
 	unlink_from_assembler_name_hash (node, true);
       if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
@@ -397,6 +400,11 @@  change_decl_assembler_name (tree decl, t
 	warning (0, "%D renamed after being referenced in assembly", decl);
 
       SET_DECL_ASSEMBLER_NAME (decl, name);
+      if (alias)
+	{
+	  IDENTIFIER_TRANSPARENT_ALIAS (name) = 1;
+	  TREE_CHAIN (DECL_ASSEMBLER_NAME (name)) = alias;
+	}
       if (node)
 	insert_to_assembler_name_hash (node, true);
     }
@@ -1065,11 +1073,17 @@  symtab_nonoverwritable_alias (symtab_nod
 {
   tree new_decl;
   symtab_node new_node = NULL;
+
+  /* First try to look up existing alias or base object
+     (if that is already non-overwritable).  */
+  node = symtab_alias_ultimate_target (node, NULL);
+  gcc_assert (!node->symbol.alias && !node->symbol.weakref);
   symtab_for_node_and_aliases (node, symtab_nonoverwritable_alias_1,
 		               (void *)&new_node, true);
   if (new_node)
     return new_node;
 
+  /* Otherwise create a new one.  */
   new_decl = copy_node (node->symbol.decl);
   DECL_NAME (new_decl) = clone_function_name (node->symbol.decl, "localalias");
   if (TREE_CODE (new_decl) == FUNCTION_DECL)
Index: varpool.c
===================================================================
--- varpool.c	(revision 202092)
+++ varpool.c	(working copy)
@@ -260,10 +260,22 @@  cgraph_variable_initializer_availability
     return AVAIL_NOT_AVAILABLE;
   if (!TREE_PUBLIC (node->symbol.decl))
     return AVAIL_AVAILABLE;
+  if (DECL_IN_CONSTANT_POOL (node->symbol.decl)
+      || DECL_VIRTUAL_P (node->symbol.decl))
+    return AVAIL_AVAILABLE;
+  if (node->symbol.alias && node->symbol.weakref)
+    {
+      enum availability avail;
+
+      cgraph_variable_initializer_availability
+	      (varpool_variable_node (node, &avail));
+      return avail;
+    }
   /* If the variable can be overwritten, return OVERWRITABLE.  Takes
      care of at least one notable extension - the COMDAT variables
      used to share template instantiations in C++.  */
-  if (!decl_replaceable_p (node->symbol.decl))
+  if (decl_replaceable_p (node->symbol.decl)
+      || DECL_EXTERNAL (node->symbol.decl))
     return AVAIL_OVERWRITABLE;
   return AVAIL_AVAILABLE;
 }