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]

ipa-icf::merge TLC


Hi,
this patch reorganize sem_function::merge and sem_variable::merge.
I read the code in detail and found several issues that are fixed in the
following patch.

  1) The logic whether address matters was wrong and ignored symbol aliases.

     I separated it into symtab_node::address_matters predicate and also
     added special case for C++ cdtors that are already handled specially
     by ipa-visibility.

  2) Turning definition to alias will result in aliases of aliases.
     Because we normally do not output them, I think it is better to
     flatten the structure or we may run into interesting target issues
     with non-GNU assemblers.

     I fixed it in symtab_node::resolve_alias.

  3) check in cgraph_edge::verify_corresponds_to_fndecl used fndecl instead
     of callee's flag that is useless because fndecl may have its symbol
     removed.
     This was hacked around in sem_function::merge by applying change
     immediately that however breaks with WPA.

  4) Redirection of callers ignored existence of aliases
     Fixed by introduction of redirect_all_callers function. I did not reuse
     similar code in clone redirection because semantic is bit different WRT
     interposable aliases.

  5) binds_to_local_def_p introduced to fix PR64146 is wrong; it possible
     to merge interposable functions (by introducing thunk with local alias).
     What is wrong with the testcase is that sem equality think they are
     equivalent just because the interposable callees are equivalent.
     For everything interposable sem equality should resort to comparing
     functions by symtab_node::semantically_equivalent_p

     The testcase can be turned into wrong code again by making the wrapper
     functions non-interposable.

     Because Martin has similar patch on the way I decided to not fix this
     issue, so the patch currently breaks the testcase.

     I would like to stop snowballing here.  Either I will XFAIL the testcase
     momentarily or Martin will get his patch in tomorrow.

  6) logic about discarded symbols had weird code:
	-  if (original->resolution == LDPR_PREEMPTED_REG
	-      || original->resolution == LDPR_PREEMPTED_IR)
	-    original_discardable = true;
     It took me a while to remember why it is there.  Basically it is about
     the case where ORIGINAL definition is known to not appear in the final
     binary, because linker preemted it by something else.
     In this case introducing an alias is counter-effective and should be
     avoided.

     Martin: It would be nice if the ORIGINAL was always chosen in a way
     that it binds_to_local_def if possible.

  8) Thunks should not be produced for empty functions and such.

  9) Logic about COMDAT groups was quite wrong - basically it is possible
     to unify within groups but extra care needs to be taken to unify across
     groups

  10) There is no need to always give up when local alias of original can
      not be created

  11) ALIAS is interposable, it is still possible to turn it into a thunk
      and keep interpositions correct

  12) I merged diagnostics to be all "Not unifying;" or "Unified;"

  13) sem_variable::merge diverged somewhat from function version and
      had strange code preventing alias cycles that should not fire because
      we should not be merging aliases, only their targets.
      Code also disabled itself with -fvariable-sections for no reason.
     this simplifies grepping.

  14) As noticed by Jakub, it does not make that much sense to do
      just partial redirection when orignal function is going to stay
      for other reason.

I tested the patch on x86_64-linux and on LTO firefox.
I also tested LTO firefox with symbol aliases disabled (to immitate darwin)
and plan to regtest with this flag.

Finally I tried to reorganize the code so it is easier to follow.  First the
function decides whether alias is possible and if not it check conditions that
makes wrapper/redirection possible.  If everything fails it reports reason and
terminates.  After all checking it finally performs changes.

I plan to commit after some further testing tomorrow and having chance
Martin to look across the changes and discuss 5).

Honza

	PR ipa/65150
	* ipa-icf.c (redirect_all_callers): New function.
	(sem_function::merge): Reorganize and fix merging issues.
	(sem_variable::merge): Likewise.
	(sem_variable::compare_sections): Remove.
	* symtab.c (symtab_node::resolve_alias): When alias has aliases,
	redirect them.
	(address_matters_1): New function.
	(symtab_node::address_taken_from_non_vtable_p): Move here from
	ipa-visibility.
	(symtab_node::address_matters_p): New function.
	* cgraph.c (cgraph_edge::verify_corresponds_to_fndecl): Fix
	check for merged flag.
	* cgraph.h (address_matters_p): Declare.
	* ipa-visibility.c (symtab_node::address_taken_from_non_vtable_p):
	Remove.
	(update_vtable_references): Fix formating.
Index: symtab.c
===================================================================
--- symtab.c	(revision 220956)
+++ symtab.c	(working copy)
@@ -1512,6 +1512,19 @@ symtab_node::resolve_alias (symtab_node
   /* If alias has address taken, so does the target.  */
   if (address_taken)
     target->ultimate_alias_target ()->address_taken = true;
+
+  /* All non-weakref aliases of THIS are now in fact aliases of TARGET.  */
+  ipa_ref *ref;
+  for (unsigned i = 0; iterate_direct_aliases (i, ref);)
+    {
+      struct symtab_node *alias_alias = ref->referring;
+      if (!alias_alias->weakref)
+	{
+	  alias_alias->remove_all_references ();
+ 	  alias_alias->create_reference (target, IPA_REF_ALIAS, NULL);
+	}
+      else i++;
+    }
   return true;
 }
 
@@ -1862,3 +1875,51 @@ symtab_node::call_for_symbol_and_aliases
     }
   return false;
 }
+
+/* Return ture if address of N is possibly compared.  */
+
+static bool
+address_matters_1 (symtab_node *n, void *)
+{
+  if (DECL_VIRTUAL_P (n->decl))
+    return false;
+  if (is_a <cgraph_node *> (n)
+      && (DECL_CXX_CONSTRUCTOR_P (n->decl)
+	  || DECL_CXX_DESTRUCTOR_P (n->decl)))
+    return false;
+  if (n->externally_visible
+      || n->symtab_node::address_taken_from_non_vtable_p ())
+    return true;
+  return false;
+}
+
+/* Return true when there is a reference to node and it is not vtable.  */
+
+bool
+symtab_node::address_taken_from_non_vtable_p (void)
+{
+  int i;
+  struct ipa_ref *ref = NULL;
+
+  for (i = 0; iterate_referring (i, ref); i++)
+    if (ref->use == IPA_REF_ADDR)
+      {
+	varpool_node *node;
+	if (is_a <cgraph_node *> (ref->referring))
+	  return true;
+	node = dyn_cast <varpool_node *> (ref->referring);
+	if (!DECL_VIRTUAL_P (node->decl))
+	  return true;
+      }
+  return false;
+}
+
+/* Return true if symbol's address may possibly be compared to other
+   symbol's address.  */
+
+bool
+symtab_node::address_matters_p ()
+{
+  gcc_assert (!alias);
+  return call_for_symbol_and_aliases (address_matters_1, NULL, true);
+}
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 220956)
+++ cgraph.c	(working copy)
@@ -2630,7 +2630,7 @@ cgraph_edge::verify_corresponds_to_fndec
   if (!node
       || node->body_removed
       || node->in_other_partition
-      || node->icf_merged
+      || callee->icf_merged
       || callee->in_other_partition)
     return false;
 
Index: cgraph.h
===================================================================
--- cgraph.h	(revision 220956)
+++ cgraph.h	(working copy)
@@ -337,6 +337,10 @@ public:
      return 2 otherwise.   */
   int equal_address_to (symtab_node *s2);
 
+  /* Return true if symbol's address may possibly be compared to other
+     symbol's address.  */
+  bool address_matters_p ();
+
   /* Return symbol table node associated with DECL, if any,
      and NULL otherwise.  */
   static inline symtab_node *get (const_tree decl)
Index: ipa-icf.c
===================================================================
--- ipa-icf.c	(revision 220956)
+++ ipa-icf.c	(working copy)
@@ -594,8 +594,46 @@ set_local (cgraph_node *node, void *data
   return false;
 }
 
+/* Redirect all callers of N and its aliases to TO.  Remove aliases if
+   possible.  Return number of redirections made.  */
+
+static int
+redirect_all_callers (cgraph_node *n, cgraph_node *to)
+{
+  int nredirected = 0;
+  ipa_ref *ref;
+
+  while (n->callers)
+    {
+      cgraph_edge *e = n->callers;
+      e->redirect_callee (to);
+      nredirected++;
+    }
+  for (unsigned i = 0; n->iterate_direct_aliases (i, ref);)
+    {
+      bool removed = false;
+      cgraph_node *n_alias = dyn_cast <cgraph_node *> (ref->referring);
+
+      if ((DECL_COMDAT_GROUP (n->decl)
+	   && (DECL_COMDAT_GROUP (n->decl)
+	       == DECL_COMDAT_GROUP (n_alias->decl)))
+	  || (n_alias->get_availability () > AVAIL_INTERPOSABLE
+	      && n->get_availability () > AVAIL_INTERPOSABLE))
+	{
+	  nredirected += redirect_all_callers (n_alias, to);
+	  if (n_alias->can_remove_if_no_direct_calls_p ()
+	      && !n_alias->has_aliases_p ())
+	    n_alias->remove ();
+	}
+      if (!removed)
+	i++;
+    }
+  return nredirected;
+}
+
 /* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can
    be applied.  */
+
 bool
 sem_function::merge (sem_item *alias_item)
 {
@@ -604,16 +642,19 @@ sem_function::merge (sem_item *alias_ite
   sem_function *alias_func = static_cast<sem_function *> (alias_item);
 
   cgraph_node *original = get_node ();
-  cgraph_node *local_original = original;
+  cgraph_node *local_original = NULL;
   cgraph_node *alias = alias_func->get_node ();
-  bool original_address_matters;
-  bool alias_address_matters;
 
-  bool create_thunk = false;
+  bool create_wrapper = false;
   bool create_alias = false;
   bool redirect_callers = false;
+  bool remove = false;
+
   bool original_discardable = false;
 
+  bool original_address_matters = original->address_matters_p ();
+  bool alias_address_matters = original->address_matters_p ();
+
   /* Do not attempt to mix functions from different user sections;
      we do not know what user intends with those.  */
   if (((DECL_SECTION_NAME (original->decl) && !original->implicit_section)
@@ -622,123 +663,165 @@ sem_function::merge (sem_item *alias_ite
     {
       if (dump_file)
 	fprintf (dump_file,
-		 "Not unifying; original and alias are in different sections.\n\n");
+		 "Not unifying; "	
+		 "original and alias are in different sections.\n\n");
       return false;
     }
 
   /* See if original is in a section that can be discarded if the main
-     symbol is not used.  */
-  if (DECL_EXTERNAL (original->decl))
-    original_discardable = true;
-  if (original->resolution == LDPR_PREEMPTED_REG
-      || original->resolution == LDPR_PREEMPTED_IR)
-    original_discardable = true;
-  if (original->can_be_discarded_p ())
+     symbol is not used.
+
+     Also consider case where we have resolution info and we know that
+     original's definition is not going to be used.  In this case we can not
+     create alias to original.  */
+  if (original->can_be_discarded_p ()
+      || (node->resolution != LDPR_UNKNOWN 
+	  && !decl_binds_to_current_def_p (node->decl)))
     original_discardable = true;
 
-  /* See if original and/or alias address can be compared for equality.  */
-  original_address_matters
-    = (!DECL_VIRTUAL_P (original->decl)
-       && (original->externally_visible
-	   || original->address_taken_from_non_vtable_p ()));
-  alias_address_matters
-    = (!DECL_VIRTUAL_P (alias->decl)
-       && (alias->externally_visible
-	   || alias->address_taken_from_non_vtable_p ()));
-
-  /* If alias and original can be compared for address equality, we need
-     to create a thunk.  Also we can not create extra aliases into discardable
-     section (or we risk link failures when section is discarded).  */
-  if ((original_address_matters
-       && alias_address_matters)
+  /* Creating a symtab alias is the optimal way to merge.
+     It however can not be used in the following cases:
+
+     1) if ORIGINAL and ALIAS may be possibly compared for address equality.
+     2) if ORIGINAL is in a section that may be discarded by linker or if
+	it is an external functions where we can not create an alias
+	(ORIGINAL_DISCARDABLE)
+     3) if target do not support symbol aliases.
+
+     If we can not produce alias, we will turn ALIAS into WRAPPER of ORIGINAL
+     and/or redirect all callers from ALIAS to ORIGINAL.  */
+  if ((original_address_matters && alias_address_matters)
       || original_discardable
-      || DECL_COMDAT_GROUP (alias->decl)
       || !sem_item::target_supports_symbol_aliases_p ())
     {
-      create_thunk = !stdarg_p (TREE_TYPE (alias->decl));
-      create_alias = false;
-      /* When both alias and original are not overwritable, we can save
-         the extra thunk wrapper for direct calls.  */
+      /* First see if we can produce wrapper.  */
+
+      /* Do not turn function in one comdat group into wrapper to another
+	 comdat group; other compiler producing the body of the
+	 another comdat group may make opossite decision and with unfortunate
+	 linker choices this may close a loop.  */
+      if (DECL_COMDAT_GROUP (alias->decl)
+	  && (DECL_COMDAT_GROUP (alias->decl)
+	      != DECL_COMDAT_GROUP (original->decl)))
+	{
+	  if (dump_file)
+	    fprintf (dump_file,
+		     "Wrapper cannot be created because of COMDAT\n");
+	}
+      else if (DECL_STATIC_CHAIN (alias->decl))
+        {
+	  if (dump_file)
+	    fprintf (dump_file,
+		     "Can not create wrapper of nested functions.\n");
+        }
+      /* TODO: We can also deal with variadic functions never calling
+	 VA_START.  */
+      else if (stdarg_p (TREE_TYPE (alias->decl)))
+	{
+	  if (dump_file)
+	    fprintf (dump_file,
+		     "can not create wrapper of stdarg function.\n");
+	}
+      else if (inline_summaries
+	       && inline_summaries->get (alias)->self_size <= 2)
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "Wrapper creation is not "
+		     "profitable (function is too small).\n");
+	}
+      else
+        create_wrapper = true;
+
+      /* We can redirect local calls in the case both alias and orignal
+	 are not interposable.  */
       redirect_callers
-	= (!original_discardable
-	   && !DECL_COMDAT_GROUP (alias->decl)
-	   && alias->get_availability () > AVAIL_INTERPOSABLE
-	   && original->get_availability () > AVAIL_INTERPOSABLE
-	   && !alias->instrumented_version);
-    }
-  else
-    {
-      create_alias = true;
-      create_thunk = false;
-      redirect_callers = false;
-    }
+	= alias->get_availability () > AVAIL_INTERPOSABLE
+	  && original->get_availability () > AVAIL_INTERPOSABLE
+	  && !alias->instrumented_version;
 
-  /* We want thunk to always jump to the local function body
-     unless the body is comdat and may be optimized out.  */
-  if ((create_thunk || redirect_callers)
-      && (!original_discardable
+      if (!redirect_callers && !create_wrapper)
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "Not unifying; can not redirect callers nor "
+		     "produce wrapper\n\n");
+	  return false;
+	}
+
+      /* Work out the symbol the wrapper should call.
+	 If ORIGINAL is interposable, we need to call a local alias.
+	 Also produce local alias (if possible) as an optimization.  */
+      if (!original_discardable
 	  || (DECL_COMDAT_GROUP (original->decl)
 	      && (DECL_COMDAT_GROUP (original->decl)
-		  == DECL_COMDAT_GROUP (alias->decl)))))
-    local_original
-      = dyn_cast <cgraph_node *> (original->noninterposable_alias ());
-
-    if (!local_original)
-      {
-	if (dump_file)
-	  fprintf (dump_file, "Noninterposable alias cannot be created.\n\n");
-
-	return false;
-      }
+		  == DECL_COMDAT_GROUP (alias->decl))))
+	{
+	  local_original
+	    = dyn_cast <cgraph_node *> (original->noninterposable_alias ());
+	  if (!local_original
+	      && original->get_availability () > AVAIL_INTERPOSABLE)
+	    local_original = original;
+	  /* If original is COMDAT local, we can not really redirect external
+	     callers to it.  */
+	  if (original->comdat_local_p ())
+	    redirect_callers = false;
+	}
+      /* If we can not use local alias, fallback to the original
+	 when possible.  */
+      else if (original->get_availability () > AVAIL_INTERPOSABLE)
+	local_original = original;
+      if (!local_original)
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "Not unifying; "
+		     "can not produce local alias.\n\n");
+	  return false;
+	}
 
-  if (!decl_binds_to_current_def_p (alias->decl))
-    {
-      if (dump_file)
-	fprintf (dump_file, "Declaration does not bind to currect definition.\n\n");
-      return false;
+      if (!redirect_callers && !create_wrapper)
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "Not unifying; "
+		     "can not redirect callers nor produce a wrapper\n\n");
+	  return false;
+	}
+      if (!create_wrapper
+	  && !alias->can_remove_if_no_direct_calls_p ())
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "Not unifying; can not make wrapper and "
+		     "function has other uses than direct calls\n\n");
+	  return false;
+	}
     }
+  else
+    create_alias = true;
 
   if (redirect_callers)
     {
-      /* If alias is non-overwritable then
-         all direct calls are safe to be redirected to the original.  */
-      bool redirected = false;
-      while (alias->callers)
-	{
-	  cgraph_edge *e = alias->callers;
-	  e->redirect_callee (local_original);
-	  push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
+      int nredirected = redirect_all_callers (alias, local_original);
 
-	  if (e->call_stmt)
-	    e->redirect_call_stmt_to_callee ();
+      if (nredirected)
+	{
+	  alias->icf_merged = true;
+	  local_original->icf_merged = true;
 
-	  pop_cfun ();
-	  redirected = true;
+	  if (dump_file && nredirected)
+	    fprintf (dump_file, "%i local calls have been "
+		     "redirected.\n", nredirected);
 	}
 
-      alias->icf_merged = true;
-      if (local_original->lto_file_data
-	  && alias->lto_file_data
-	  && local_original->lto_file_data != alias->lto_file_data)
-      local_original->merged = true;
-
-      /* The alias function is removed if symbol address
-         does not matter.  */
-      if (!alias_address_matters)
-	alias->remove ();
-
-      if (dump_file && redirected)
-	fprintf (dump_file, "Callgraph local calls have been redirected.\n\n");
+      /* If all callers was redirected, do not produce wrapper.  */
+      if (alias->can_remove_if_no_direct_calls_p ()
+	  && !alias->has_aliases_p ())
+	{
+	  create_wrapper = false;
+	  remove = true;
+	}
+      gcc_assert (!create_alias);
     }
-  /* If the condtion above is not met, we are lucky and can turn the
-     function into real alias.  */
   else if (create_alias)
     {
       alias->icf_merged = true;
-      if (local_original->lto_file_data
-	  && alias->lto_file_data
-	  && local_original->lto_file_data != alias->lto_file_data)
-      local_original->merged = true;
 
       /* Remove the function's body.  */
       ipa_merge_profiles (original, alias);
@@ -753,39 +836,38 @@ sem_function::merge (sem_item *alias_ite
 	 (set_local, (void *)(size_t) original->local_p (), true);
 
       if (dump_file)
-	fprintf (dump_file, "Callgraph alias has been created.\n\n");
+	fprintf (dump_file, "Unified; Function alias has been created.\n\n");
     }
-  else if (create_thunk)
+  if (create_wrapper)
     {
-      if (DECL_COMDAT_GROUP (alias->decl))
-	{
-	  if (dump_file)
-	    fprintf (dump_file, "Callgraph thunk cannot be created because of COMDAT\n");
+      gcc_assert (!create_alias);
+      alias->icf_merged = true;
+      local_original->icf_merged = true;
 
-	  return 0;
-	}
+      ipa_merge_profiles (local_original, alias, true);
+      alias->create_wrapper (local_original);
 
-      if (DECL_STATIC_CHAIN (alias->decl))
-        {
-         if (dump_file)
-           fprintf (dump_file, "Thunk creation is risky for static-chain functions.\n\n");
+      if (dump_file)
+	fprintf (dump_file, "Unified; Wrapper has been created.\n\n");
+    }
+  gcc_assert (alias->icf_merged || remove);
+  original->icf_merged = true;
 
-         return 0;
-        }
+  /* Inform the inliner about cross-module merging.  */
+  if ((original->lto_file_data || alias->lto_file_data)
+      && original->lto_file_data != alias->lto_file_data)
+    local_original->merged = original->merged = true;
 
+  if (remove)
+    {
+      ipa_merge_profiles (original, alias);
+      alias->release_body ();
+      alias->reset ();
+      alias->body_removed = true;
       alias->icf_merged = true;
-      if (local_original->lto_file_data
-	  && alias->lto_file_data
-	  && local_original->lto_file_data != alias->lto_file_data)
-      local_original->merged = true;
-      ipa_merge_profiles (local_original, alias, true);
-      alias->create_wrapper (local_original);
-
       if (dump_file)
-	fprintf (dump_file, "Callgraph thunk has been created.\n\n");
+	fprintf (dump_file, "Unified; Function body was removed.\n");
     }
-  else if (dump_file)
-    fprintf (dump_file, "Callgraph merge operation cannot be performed.\n\n");
 
   return true;
 }
@@ -1281,7 +1363,8 @@ sem_variable::merge (sem_item *alias_ite
   if (!sem_item::target_supports_symbol_aliases_p ())
     {
       if (dump_file)
-	fprintf (dump_file, "Symbol aliases are not supported by target\n\n");
+	fprintf (dump_file, "Not unifying; "
+		 "Symbol aliases are not supported by target\n\n");
       return false;
     }
 
@@ -1291,42 +1374,60 @@ sem_variable::merge (sem_item *alias_ite
   varpool_node *alias = alias_var->get_node ();
   bool original_discardable = false;
 
+  bool original_address_matters = original->address_matters_p ();
+  bool alias_address_matters = original->address_matters_p ();
+
   /* See if original is in a section that can be discarded if the main
-     symbol is not used.  */
-  if (DECL_EXTERNAL (original->decl))
-    original_discardable = true;
-  if (original->resolution == LDPR_PREEMPTED_REG
-      || original->resolution == LDPR_PREEMPTED_IR)
-    original_discardable = true;
-  if (original->can_be_discarded_p ())
+     symbol is not used.
+     Also consider case where we have resolution info and we know that
+     original's definition is not going to be used.  In this case we can not
+     create alias to original.  */
+  if (original->can_be_discarded_p ()
+      || (node->resolution != LDPR_UNKNOWN 
+	  && !decl_binds_to_current_def_p (node->decl)))
     original_discardable = true;
 
   gcc_assert (!TREE_ASM_WRITTEN (alias->decl));
 
-  if (original_discardable || DECL_EXTERNAL (alias_var->decl) ||
-      !compare_sections (alias_var))
+  /* Do not attempt to mix functions from different user sections;
+     we do not know what user intends with those.  */
+  if (((DECL_SECTION_NAME (original->decl) && !original->implicit_section)
+       || (DECL_SECTION_NAME (alias->decl) && !alias->implicit_section))
+      && DECL_SECTION_NAME (original->decl) != DECL_SECTION_NAME (alias->decl))
+    {
+      if (dump_file)
+	fprintf (dump_file,
+		 "Not unifying; "	
+		 "original and alias are in different sections.\n\n");
+      return false;
+    }
+
+  /* We can not merge if address comparsion metters.  */
+  if (original_address_matters && alias_address_matters
+      && flag_merge_constants < 2)
+    {
+      if (dump_file)
+	fprintf (dump_file,
+		 "Not unifying; "	
+		 "adress of original and alias may be compared.\n\n");
+      return false;
+    }
+
+  if (original_discardable
+      && (!DECL_COMDAT_GROUP (original->decl)
+	  || (DECL_COMDAT_GROUP (original->decl)
+	      != DECL_COMDAT_GROUP (alias->decl))))
     {
       if (dump_file)
-	fprintf (dump_file, "Varpool alias cannot be created\n\n");
+	fprintf (dump_file, "Not unifying; alias cannot be created; "
+		 "target is discardable\n\n");
 
       return false;
     }
   else
     {
-      // alias cycle creation check
-      varpool_node *n = original;
-
-      while (n->alias)
-	{
-	  n = n->get_alias_target ();
-	  if (n == alias)
-	    {
-	      if (dump_file)
-		fprintf (dump_file, "Varpool alias cannot be created (alias cycle).\n\n");
-
-	      return false;
-	    }
-	}
+      gcc_assert (!original->alias);
+      gcc_assert (!alias->alias);
 
       alias->analyzed = false;
 
@@ -1338,26 +1439,12 @@ sem_variable::merge (sem_item *alias_ite
       alias->resolve_alias (original);
 
       if (dump_file)
-	fprintf (dump_file, "Varpool alias has been created.\n\n");
+	fprintf (dump_file, "Unified; Variable alias has been created.\n\n");
 
       return true;
     }
 }
 
-bool
-sem_variable::compare_sections (sem_variable *alias)
-{
-  const char *source = node->get_section ();
-  const char *target = alias->node->get_section();
-
-  if (source == NULL && target == NULL)
-    return true;
-  else if(!source || !target)
-    return false;
-  else
-    return strcmp (source, target) == 0;
-}
-
 /* Dump symbol to FILE.  */
 
 void
Index: ipa-visibility.c
===================================================================
--- ipa-visibility.c	(revision 220956)
+++ ipa-visibility.c	(working copy)
@@ -129,27 +129,6 @@ cgraph_node::local_p (void)
 					
 }
 
-/* Return true when there is a reference to node and it is not vtable.  */
-
-bool
-symtab_node::address_taken_from_non_vtable_p (void)
-{
-  int i;
-  struct ipa_ref *ref = NULL;
-
-  for (i = 0; iterate_referring (i, ref); i++)
-    if (ref->use == IPA_REF_ADDR)
-      {
-	varpool_node *node;
-	if (is_a <cgraph_node *> (ref->referring))
-	  return true;
-	node = dyn_cast <varpool_node *> (ref->referring);
-	if (!DECL_VIRTUAL_P (node->decl))
-	  return true;
-      }
-  return false;
-}
-
 /* A helper for comdat_can_be_unshared_p.  */
 
 static bool
@@ -387,7 +366,8 @@ can_replace_by_local_alias_in_vtable (sy
 /* walk_tree callback that rewrites initializer references.   */
 
 static tree
-update_vtable_references (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
+update_vtable_references (tree *tp, int *walk_subtrees,
+			  void *data ATTRIBUTE_UNUSED)
 {
   if (TREE_CODE (*tp) == VAR_DECL
       || TREE_CODE (*tp) == FUNCTION_DECL)


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