Allow negative offset for UNSPEC_DTPOFF/UNSPEC_NTPOFF
[gcc.git] / gcc / ipa.c
index 766b26f03138b0f69e712731c1d711fb08374f2c..e270591807711f7cde661500867695c67cbc8d9d 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -24,7 +24,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "cgraph.h"
 #include "tree-pass.h"
-#include "timevar.h"
 #include "gimple.h"
 #include "ggc.h"
 #include "flags.h"
@@ -100,7 +99,10 @@ process_references (struct ipa_ref_list *list,
        {
          struct varpool_node *node = ipa_ref_varpool_node (ref);
 
-         if (node->analyzed)
+         if (node->analyzed
+             && (!DECL_EXTERNAL (node->symbol.decl)
+                 || node->alias
+                 || before_inlining_p))
            pointer_set_insert (reachable, node);
          enqueue_node ((symtab_node) node, first, reachable);
        }
@@ -187,6 +189,12 @@ has_addr_references_p (struct cgraph_node *node,
      reshape callgraph and preserve body when offline copy of function or
      inline clone is being removed.
 
+   - C++ virtual tables keyed to other unit are represented as DECL_EXTERNAL
+     variables with DECL_INITIAL set.  We finalize these and keep reachable
+     ones around for constant folding purposes.  After inlining we however
+     stop walking their references to let everything static referneced by them
+     to be removed when it is otherwise unreachable.
+
    We maintain queue of both reachable symbols (i.e. defined symbols that needs
    to stay) and symbols that are in boundary (i.e. external symbols referenced
    by reachable symbols or origins of clones).  The queue is represented
@@ -310,12 +318,12 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 
          /* For non-inline clones, force their origins to the boundary and ensure
             that body is not removed.  */
-         while (cnode->clone_of && !cnode->clone_of->symbol.aux
+         while (cnode->clone_of
                 && !gimple_has_body_p (cnode->symbol.decl))
            {
              bool noninline = cnode->clone_of->symbol.decl != cnode->symbol.decl;
              cnode = cnode->clone_of;
-             if (noninline && !cnode->symbol.aux)
+             if (noninline)
                {
                  pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
                  enqueue_node ((symtab_node)cnode, &first, reachable);
@@ -323,6 +331,19 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
                }
            }
        }
+      /* When we see constructor of external variable, keep referred nodes in the
+        boundary.  This will also hold initializers of the external vars NODE
+        reffers to.  */
+      if (symtab_variable_p (node)
+         && DECL_EXTERNAL (node->symbol.decl)
+         && !varpool (node)->alias
+         && in_boundary_p)
+        {
+         int i;
+         struct ipa_ref *ref;
+         for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
+           enqueue_node (ref->referred, &first, reachable);
+        }
     }
 
   /* Remove unreachable functions.   */
@@ -347,7 +368,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
              changed = true;
            }
          if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl)
-             && !DECL_ARTIFICIAL (node->symbol.decl))
+             && (node->local.finalized || !DECL_ARTIFICIAL (node->symbol.decl)))
            cgraph_release_function_body (node);
          node->analyzed = false;
        }
@@ -432,10 +453,6 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
     FOR_EACH_DEFINED_FUNCTION (node)
       cgraph_propagate_frequency (node);
 
-  /* Reclaim alias pairs for functions that have disappeared from the
-     call graph.  */
-  remove_unreachable_alias_pairs ();
-
   return changed;
 }
 
@@ -627,6 +644,9 @@ varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
   if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl))
     return true;
 
+  if (DECL_EXTERNAL (vnode->symbol.decl))
+    return true;
+
   if (!DECL_COMDAT (vnode->symbol.decl) && !TREE_PUBLIC (vnode->symbol.decl))
     return false;
 
@@ -662,7 +682,7 @@ varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
   if (vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
     return false;
 
-  /* As a special case, the COMDAT virutal tables can be unshared.
+  /* As a special case, the COMDAT virtual tables can be unshared.
      In LTO mode turn vtables into static variables.  The variable is readonly,
      so this does not enable more optimization, but referring static var
      is faster for dynamic linking.  Also this match logic hidding vtables
@@ -770,7 +790,7 @@ function_and_variable_visibility (bool whole_program)
 
       /* C++ FE on lack of COMDAT support create local COMDAT functions
         (that ought to be shared but can not due to object format
-        limitations).  It is neccesary to keep the flag to make rest of C++ FE
+        limitations).  It is necessary to keep the flag to make rest of C++ FE
         happy.  Clear the flag here to avoid confusion in middle-end.  */
       if (DECL_COMDAT (node->symbol.decl) && !TREE_PUBLIC (node->symbol.decl))
         DECL_COMDAT (node->symbol.decl) = 0;
@@ -890,7 +910,6 @@ function_and_variable_visibility (bool whole_program)
            symtab_dissolve_same_comdat_group_list ((symtab_node) vnode);
          vnode->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
        }
-     gcc_assert (TREE_STATIC (vnode->symbol.decl));
     }
   pointer_set_destroy (aliased_nodes);
   pointer_set_destroy (aliased_vnodes);
@@ -946,6 +965,34 @@ struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
  }
 };
 
+/* Free inline summary.  */
+
+static unsigned
+free_inline_summary (void)
+{
+  inline_free_summary ();
+  return 0;
+}
+
+struct simple_ipa_opt_pass pass_ipa_free_inline_summary =
+{
+ {
+  SIMPLE_IPA_PASS,
+  "*free_inline_summary",              /* name */
+  NULL,                                        /* gate */
+  free_inline_summary,                 /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_IPA_FREE_INLINE_SUMMARY,          /* tv_id */
+  0,                                   /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_ggc_collect                     /* todo_flags_finish */
+ }
+};
+
 /* Do not re-run on ltrans stage.  */
 
 static bool
@@ -954,7 +1001,7 @@ gate_whole_program_function_and_variable_visibility (void)
   return !flag_ltrans;
 }
 
-/* Bring functionss local at LTO time whith -fwhole-program.  */
+/* Bring functionss local at LTO time with -fwhole-program.  */
 
 static unsigned int
 whole_program_function_and_variable_visibility (void)
@@ -1330,7 +1377,7 @@ build_cdtor_fns (void)
 
 /* Look for constructors and destructors and produce function calling them.
    This is needed for targets not supporting ctors or dtors, but we perform the
-   transformation also at linktime to merge possibly numberous
+   transformation also at linktime to merge possibly numerous
    constructors/destructors into single function to improve code locality and
    reduce size.  */