re PR debug/66691 (ICE on valid code at -O3 with -g enabled in simplify_subreg, at...
[gcc.git] / gcc / ipa-visibility.c
index d33c36bee9fd6d75a2640cac04a6a7babb5fb218..f6c1f4099e84fbee7704096af28b35ae048c37ec 100644 (file)
@@ -1,5 +1,5 @@
 /* IPA visibility pass
-   Copyright (C) 2003-2014 Free Software Foundation, Inc.
+   Copyright (C) 2003-2015 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -76,7 +76,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "alias.h"
+#include "symtab.h"
 #include "tree.h"
+#include "hard-reg-set.h"
+#include "function.h"
 #include "cgraph.h"
 #include "tree-pass.h"
 #include "calls.h"
@@ -85,17 +89,18 @@ along with GCC; see the file COPYING3.  If not see
 
 /* 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)
 {
-   /* FIXME: Aliases can be local, but i386 gets thunks wrong then.  */
-   return !(node->only_called_directly_or_aliased_p ()
-           && !node->has_aliases_p ()
-           && node->definition
-           && !DECL_EXTERNAL (node->decl)
-           && !node->externally_visible
-           && !node->used_from_other_partition
-           && !node->in_other_partition);
+  return !(node->only_called_directly_or_aliased_p ()
+          /* i386 would need update to output thunk with locak calling
+             ocnvetions.  */
+          && !node->thunk.thunk_p
+          && node->definition
+          && !DECL_EXTERNAL (node->decl)
+          && !node->externally_visible
+          && !node->used_from_other_partition
+          && !node->in_other_partition);
 }
 
 /* Return true when function can be marked local.  */
@@ -105,36 +110,13 @@ cgraph_node::local_p (void)
 {
    cgraph_node *n = ultimate_alias_target ();
 
-   /* FIXME: thunks can be considered local, but we need prevent i386
-      from attempting to change calling convention of them.  */
    if (n->thunk.thunk_p)
-     return false;
-   return !n->call_for_symbol_thunks_and_aliases (cgraph_node::non_local_p,
-                                               NULL, true);
+     return n->callees->callee->local_p ();
+   return !n->call_for_symbol_thunks_and_aliases (non_local_p,
+                                                 NULL, true);
                                        
 }
 
-/* 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
@@ -142,16 +124,14 @@ comdat_can_be_unshared_p_1 (symtab_node *node)
 {
   if (!node->externally_visible)
     return true;
-  /* When address is taken, we don't know if equality comparison won't
-     break eventually. Exception are virutal functions, C++
-     constructors/destructors and vtables, where this is not possible by
-     language standard.  */
-  if (!DECL_VIRTUAL_P (node->decl)
-      && (TREE_CODE (node->decl) != FUNCTION_DECL
-         || (!DECL_CXX_CONSTRUCTOR_P (node->decl)
-             && !DECL_CXX_DESTRUCTOR_P (node->decl)))
-      && node->address_taken_from_non_vtable_p ())
-    return false;
+  if (node->address_can_be_compared_p ())
+    {
+      struct ipa_ref *ref;
+
+      for (unsigned int i = 0; node->iterate_referring (i, ref); i++)
+       if (ref->address_matters_p ())
+         return false;
+    }
 
   /* If the symbol is used in some weird way, better to not touch it.  */
   if (node->force_output)
@@ -259,6 +239,10 @@ cgraph_externally_visible_p (struct cgraph_node *node,
   if (MAIN_NAME_P (DECL_NAME (node->decl)))
     return true;
 
+  if (node->instrumentation_clone
+      && MAIN_NAME_P (DECL_NAME (node->orig_decl)))
+    return true;
+
   return false;
 }
 
@@ -277,6 +261,13 @@ varpool_node::externally_visible_p (void)
   if (used_from_object_file_p ())
     return true;
 
+  /* Bringing TLS variables local may cause dynamic linker failures
+     on limits of static TLS vars.  */
+  if (DECL_THREAD_LOCAL_P (decl)
+      && (DECL_TLS_MODEL (decl) != TLS_MODEL_EMULATED
+         && DECL_TLS_MODEL (decl) != TLS_MODEL_INITIAL_EXEC))
+    return true;
+
   if (DECL_HARD_REGISTER (decl))
     return true;
   if (DECL_PRESERVE_P (decl))
@@ -361,7 +352,8 @@ can_replace_by_local_alias_in_vtable (symtab_node *node)
 /* 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)
@@ -398,11 +390,19 @@ update_visibility_by_resolution_info (symtab_node * node)
   if (node->same_comdat_group)
     for (symtab_node *next = node->same_comdat_group;
         next != node; next = next->same_comdat_group)
-      gcc_assert (!node->externally_visible
-                 || define == (next->resolution == LDPR_PREVAILING_DEF_IRONLY
-                               || next->resolution == LDPR_PREVAILING_DEF
-                               || next->resolution == LDPR_UNDEF
-                               || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP));
+      {
+       if (!next->externally_visible)
+         continue;
+
+       bool same_def
+         = define == (next->resolution == LDPR_PREVAILING_DEF_IRONLY
+                      || next->resolution == LDPR_PREVAILING_DEF
+                      || next->resolution == LDPR_UNDEF
+                      || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
+       gcc_assert (in_lto_p || same_def);
+       if (!same_def)
+         return;
+      }
 
   if (node->same_comdat_group)
     for (symtab_node *next = node->same_comdat_group;
@@ -536,6 +536,7 @@ function_and_variable_visibility (bool whole_program)
        }
 
       if (node->thunk.thunk_p
+         && !node->thunk.add_pointer_bounds_args
          && TREE_PUBLIC (node->decl))
        {
          struct cgraph_node *decl_node = node;
@@ -560,7 +561,8 @@ function_and_variable_visibility (bool whole_program)
     }
   FOR_EACH_DEFINED_FUNCTION (node)
     {
-      node->local.local |= node->local_p ();
+      if (!node->local.local)
+        node->local.local |= node->local_p ();
 
       /* If we know that function can not be overwritten by a different semantics
         and moreover its section can not be discarded, replace all direct calls
@@ -580,11 +582,11 @@ function_and_variable_visibility (bool whole_program)
                {
                  struct cgraph_edge *e = node->callers;
 
-                 cgraph_redirect_edge_callee (e, alias);
+                 e->redirect_callee (alias);
                  if (gimple_has_body_p (e->caller->decl))
                    {
                      push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
-                     cgraph_redirect_edge_call_stmt_to_callee (e);
+                     e->redirect_call_stmt_to_callee ();
                      pop_cfun ();
                    }
                }
@@ -633,6 +635,9 @@ function_and_variable_visibility (bool whole_program)
           vnode->externally_visible = false;
          vnode->forced_by_abi = false;
        }
+      if (lookup_attribute ("no_reorder",
+                           DECL_ATTRIBUTES (vnode->decl)))
+       vnode->no_reorder = 1;
       if (!vnode->externally_visible
          && !vnode->weakref)
        {
@@ -717,7 +722,7 @@ function_and_variable_visibility (bool whole_program)
          fprintf (dump_file, " %s", vnode->name ());
       fprintf (dump_file, "\n\n");
     }
-  cgraph_function_flags_ready = true;
+  symtab->function_flags_ready = true;
   return 0;
 }