omp-builtins.def (BUILT_IN_GOMP_LOOP_NONMONOTONIC_RUNTIME_START, [...]): Fix up funct...
[gcc.git] / gcc / ipa.c
index 879d9c249cd6ade298bfe39773bf1dec2c6b9fef..89fb1da50fd42fd0e3e926c530ec699822efbaa1 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -1,5 +1,5 @@
 /* Basic IPA optimizations and utilities.
-   Copyright (C) 2003-2016 Free Software Foundation, Inc.
+   Copyright (C) 2003-2018 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -34,10 +34,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "symbol-summary.h"
 #include "tree-vrp.h"
 #include "ipa-prop.h"
-#include "ipa-inline.h"
+#include "ipa-fnsummary.h"
 #include "dbgcnt.h"
 #include "debug.h"
-
+#include "stringpool.h"
+#include "attribs.h"
 
 /* Return true when NODE has ADDR reference.  */
 
@@ -100,12 +101,32 @@ enqueue_node (symtab_node *node, symtab_node **first,
   *first = node;
 }
 
+/* Return true if NODE may get inlined later.
+   This is used to keep DECL_EXTERNAL function bodies around long enough
+   so inliner can proces them.  */
+
+static bool
+possible_inline_candidate_p (symtab_node *node)
+{
+  if (symtab->state >= IPA_SSA_AFTER_INLINING)
+    return false;
+  cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
+  if (!cnode)
+    return false;
+  if (DECL_UNINLINABLE (cnode->decl))
+    return false;
+  if (opt_for_fn (cnode->decl, optimize))
+    return true;
+  if (symtab->state >= IPA_SSA)
+    return false;
+  return lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl));
+}
+
 /* Process references.  */
 
 static void
 process_references (symtab_node *snode,
                    symtab_node **first,
-                   bool before_inlining_p,
                    hash_set<symtab_node *> *reachable)
 {
   int i;
@@ -117,28 +138,22 @@ process_references (symtab_node *snode,
 
       if (node->definition && !node->in_other_partition
          && ((!DECL_EXTERNAL (node->decl) || node->alias)
-             || (((before_inlining_p
-                   && ((TREE_CODE (node->decl) != FUNCTION_DECL
-                        && optimize)
-                       || (TREE_CODE (node->decl) == FUNCTION_DECL
-                           && opt_for_fn (body->decl, optimize))
-                       || (symtab->state < IPA_SSA
-                           && lookup_attribute
-                                ("always_inline",
-                                 DECL_ATTRIBUTES (body->decl))))))
+             || (possible_inline_candidate_p (node)
                  /* We use variable constructors during late compilation for
                     constant folding.  Keep references alive so partitioning
                     knows about potential references.  */
                  || (VAR_P (node->decl)
-                     && flag_wpa
-                     && ctor_for_folding (node->decl)
-                        != error_mark_node))))
+                     && (flag_wpa
+                         || flag_incremental_link
+                                == INCREMENTAL_LINK_LTO)
+                     && dyn_cast <varpool_node *> (node)
+                          ->ctor_useable_for_folding_p ()))))
        {
          /* Be sure that we will not optimize out alias target
             body.  */
          if (DECL_EXTERNAL (node->decl)
              && node->alias
-             && before_inlining_p)
+             && symtab->state < IPA_SSA_AFTER_INLINING)
            reachable->add (body);
          reachable->add (node);
        }
@@ -158,8 +173,7 @@ static void
 walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
                               struct cgraph_edge *edge,
                               symtab_node **first,
-                              hash_set<symtab_node *> *reachable,
-                              bool before_inlining_p)
+                              hash_set<symtab_node *> *reachable)
 {
   unsigned int i;
   void *cache_token;
@@ -188,15 +202,14 @@ walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
          /* Prior inlining, keep alive bodies of possible targets for
             devirtualization.  */
          if (n->definition
-             && (before_inlining_p
-                 && opt_for_fn (body->decl, optimize)
+             && (possible_inline_candidate_p (body)
                  && opt_for_fn (body->decl, flag_devirtualize)))
             {
                /* Be sure that we will not optimize out alias target
                   body.  */
                if (DECL_EXTERNAL (n->decl)
                    && n->alias
-                   && before_inlining_p)
+                   && symtab->state < IPA_SSA_AFTER_INLINING)
                  reachable->add (body);
               reachable->add (n);
             }
@@ -223,29 +236,17 @@ walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
                       (builtin_decl_implicit (BUILT_IN_UNREACHABLE));
 
          if (dump_enabled_p ())
-            {
-             location_t locus;
-             if (edge->call_stmt)
-               locus = gimple_location (edge->call_stmt);
-             else
-               locus = UNKNOWN_LOCATION;
-             dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, locus,
-                               "devirtualizing call in %s/%i to %s/%i\n",
-                               edge->caller->name (), edge->caller->order,
-                               target->name (),
-                               target->order);
+           {
+             dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, edge->call_stmt,
+                              "devirtualizing call in %s to %s\n",
+                              edge->caller->dump_name (),
+                              target->dump_name ());
            }
          edge = edge->make_direct (target);
-         if (inline_summaries)
-           inline_update_overall_summary (node);
+         if (ipa_fn_summaries)
+           ipa_update_overall_fn_summary (node);
          else if (edge->call_stmt)
-           {
-             edge->redirect_call_stmt_to_callee ();
-
-             /* Call to __builtin_unreachable shouldn't be instrumented.  */
-             if (!targets.length ())
-               gimple_call_set_with_bounds (edge->call_stmt, false);
-           }
+           edge->redirect_call_stmt_to_callee ();
        }
     }
 }
@@ -313,8 +314,6 @@ symbol_table::remove_unreachable_nodes (FILE *file)
   hash_set<symtab_node *> reachable;
   hash_set<tree> body_needed_for_clonning;
   hash_set<void *> reachable_call_targets;
-  bool before_inlining_p = symtab->state < (!optimize ? IPA_SSA
-                                           : IPA_SSA_AFTER_INLINING);
 
   timevar_push (TV_IPA_UNREACHABLE);
   build_type_inheritance_graph ();
@@ -406,7 +405,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
                  enqueue_node (next, &first, &reachable);
            }
          /* Mark references as reachable.  */
-         process_references (node, &first, before_inlining_p, &reachable);
+         process_references (node, &first, &reachable);
        }
 
       if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
@@ -426,8 +425,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
                      next = e->next_callee;
                      if (e->indirect_info->polymorphic)
                        walk_polymorphic_call_targets (&reachable_call_targets,
-                                                      e, &first, &reachable,
-                                                      before_inlining_p);
+                                                      e, &first, &reachable);
                    }
                }
              for (e = cnode->callees; e; e = e->next_callee)
@@ -438,18 +436,13 @@ symbol_table::remove_unreachable_nodes (FILE *file)
                      && (!e->inline_failed
                          || !DECL_EXTERNAL (e->callee->decl)
                          || e->callee->alias
-                         || (before_inlining_p
-                             && (opt_for_fn (body->decl, optimize)
-                                 || (symtab->state < IPA_SSA
-                                     && lookup_attribute
-                                         ("always_inline",
-                                          DECL_ATTRIBUTES (body->decl)))))))
+                         || possible_inline_candidate_p (e->callee)))
                    {
                      /* Be sure that we will not optimize out alias target
                         body.  */
                      if (DECL_EXTERNAL (e->callee->decl)
                          && e->callee->alias
-                         && before_inlining_p)
+                         && symtab->state < IPA_SSA_AFTER_INLINING)
                        reachable.add (body);
                      reachable.add (e->callee);
                    }
@@ -461,20 +454,6 @@ symbol_table::remove_unreachable_nodes (FILE *file)
              if (cnode->global.inlined_to)
                body_needed_for_clonning.add (cnode->decl);
 
-             /* For instrumentation clones we always need original
-                function node for proper LTO privatization.  */
-             if (cnode->instrumentation_clone
-                 && cnode->definition)
-               {
-                 gcc_assert (cnode->instrumented_version || in_lto_p);
-                 if (cnode->instrumented_version)
-                   {
-                     enqueue_node (cnode->instrumented_version, &first,
-                                   &reachable);
-                     reachable.add (cnode->instrumented_version);
-                   }
-               }
-
              /* For non-inline clones, force their origins to the boundary and ensure
                 that body is not removed.  */
              while (cnode->clone_of)
@@ -529,7 +508,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
       if (!node->aux)
        {
          if (file)
-           fprintf (file, " %s/%i", node->name (), node->order);
+           fprintf (file, " %s", node->dump_name ());
          node->remove ();
          changed = true;
        }
@@ -549,7 +528,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
          if (node->definition && !node->alias && !node->thunk.thunk_p)
            {
              if (file)
-               fprintf (file, " %s/%i", node->name (), node->order);
+               fprintf (file, " %s", node->dump_name ());
              node->body_removed = true;
              node->analyzed = false;
              node->definition = false;
@@ -616,15 +595,14 @@ symbol_table::remove_unreachable_nodes (FILE *file)
          while (vnode->iterate_direct_aliases (0, ref))
            {
              if (file)
-               fprintf (file, " %s/%i", ref->referred->name (),
-                        ref->referred->order);
+               fprintf (file, " %s", ref->referred->dump_name ());
              ref->referring->remove ();
            }
          if (file)
-           fprintf (file, " %s/%i", vnode->name (), vnode->order);
+           fprintf (file, " %s", vnode->dump_name ());
           vnext = next_variable (vnode);
          /* Signal removal to the debug machinery.  */
-         if (! flag_wpa)
+         if (! flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO)
            {
              vnode->definition = false;
              (*debug_hooks->late_global_decl) (vnode->decl);
@@ -642,8 +620,8 @@ symbol_table::remove_unreachable_nodes (FILE *file)
              changed = true;
            }
          /* Keep body if it may be useful for constant folding.  */
-         if ((init = ctor_for_folding (vnode->decl)) == error_mark_node
-             && !POINTER_BOUNDS_P (vnode->decl))
+         if ((flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO)
+             || ((init = ctor_for_folding (vnode->decl)) == error_mark_node))
            vnode->remove_initializer ();
          else
            DECL_INITIAL (vnode->decl) = init;
@@ -668,10 +646,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
        && !node->used_from_other_partition)
       {
        if (!node->call_for_symbol_and_aliases
-           (has_addr_references_p, NULL, true)
-           && (!node->instrumentation_clone
-               || !node->instrumented_version
-               || !node->instrumented_version->address_taken))
+           (has_addr_references_p, NULL, true))
          {
            if (file)
              fprintf (file, " %s", node->name ());
@@ -682,7 +657,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
                   of possible later devirtualization.  Do not mark them as
                   local too early so we won't optimize them out before
                   we are done with polymorphic call analysis.  */
-               && (!before_inlining_p
+               && (symtab->state >= IPA_SSA_AFTER_INLINING
                    || !node->call_for_symbol_and_aliases
                       (is_indirect_call_target_p, NULL, true)))
              {
@@ -698,7 +673,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
   symtab_node::checking_verify_symtab_nodes ();
 
   /* If we removed something, perhaps profile could be improved.  */
-  if (changed && optimize && inline_edge_summary_vec.exists ())
+  if (changed && (optimize || in_lto_p) && ipa_call_summaries)
     FOR_EACH_DEFINED_FUNCTION (node)
       ipa_propagate_frequency (node);
 
@@ -739,8 +714,6 @@ process_references (varpool_node *vnode,
        process_references (dyn_cast<varpool_node *> (ref->referring), written,
                            address_taken, read, explicit_refs);
        break;
-      case IPA_REF_CHKP:
-       gcc_unreachable ();
       }
 }
 
@@ -759,7 +732,7 @@ bool
 set_writeonly_bit (varpool_node *vnode, void *data)
 {
   vnode->writeonly = true;
-  if (optimize)
+  if (optimize || in_lto_p)
     {
       DECL_INITIAL (vnode->decl) = NULL;
       if (!vnode->alias)
@@ -782,10 +755,10 @@ clear_addressable_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED)
   return false;
 }
 
-/* Discover variables that have no longer address taken or that are read only
-   and update their flags.
+/* Discover variables that have no longer address taken, are read-only or
+   write-only and update their flags.
 
-   Return true when unreachable symbol removan should be done.
+   Return true when unreachable symbol removal should be done.
 
    FIXME: This can not be done in between gimplify and omp_expand since
    readonly flag plays role on what is shared and what is not.  Currently we do
@@ -794,8 +767,11 @@ clear_addressable_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED)
    make sense to do it before early optimizations.  */
 
 bool
-ipa_discover_readonly_nonaddressable_vars (void)
+ipa_discover_variable_flags (void)
 {
+  if (!flag_ipa_reference_addressable)
+    return false;
+
   bool remove_p = false;
   varpool_node *vnode;
   if (dump_file)
@@ -845,54 +821,9 @@ ipa_discover_readonly_nonaddressable_vars (void)
   return remove_p;
 }
 
-/* Free inline summary.  */
-
-namespace {
-
-const pass_data pass_data_ipa_free_inline_summary =
-{
-  SIMPLE_IPA_PASS, /* type */
-  "free-inline-summary", /* name */
-  OPTGROUP_NONE, /* optinfo_flags */
-  TV_IPA_FREE_INLINE_SUMMARY, /* tv_id */
-  0, /* properties_required */
-  0, /* properties_provided */
-  0, /* properties_destroyed */
-  0, /* todo_flags_start */
-  /* Early optimizations may make function unreachable.  We can not
-     remove unreachable functions as part of the ealry opts pass because
-     TODOs are run before subpasses.  Do it here.  */
-  ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
-};
-
-class pass_ipa_free_inline_summary : public simple_ipa_opt_pass
-{
-public:
-  pass_ipa_free_inline_summary (gcc::context *ctxt)
-    : simple_ipa_opt_pass (pass_data_ipa_free_inline_summary, ctxt)
-  {}
-
-  /* opt_pass methods: */
-  virtual unsigned int execute (function *)
-    {
-      inline_free_summary ();
-      return 0;
-    }
-
-}; // class pass_ipa_free_inline_summary
-
-} // anon namespace
-
-simple_ipa_opt_pass *
-make_pass_ipa_free_inline_summary (gcc::context *ctxt)
-{
-  return new pass_ipa_free_inline_summary (ctxt);
-}
-
 /* Generate and emit a static constructor or destructor.  WHICH must
-   be one of 'I' (for a constructor), 'D' (for a destructor), 'P'
-   (for chp static vars constructor) or 'B' (for chkp static bounds
-   constructor).  BODY is a STATEMENT_LIST containing GENERIC
+   be one of 'I' (for a constructor), 'D' (for a destructor).
+   BODY is a STATEMENT_LIST containing GENERIC
    statements.  PRIORITY is the initialization priority for this
    constructor or destructor.
 
@@ -955,20 +886,6 @@ cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final)
       DECL_STATIC_CONSTRUCTOR (decl) = 1;
       decl_init_priority_insert (decl, priority);
       break;
-    case 'P':
-      DECL_STATIC_CONSTRUCTOR (decl) = 1;
-      DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("chkp ctor"),
-                                         NULL,
-                                         NULL_TREE);
-      decl_init_priority_insert (decl, priority);
-      break;
-    case 'B':
-      DECL_STATIC_CONSTRUCTOR (decl) = 1;
-      DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("bnd_legacy"),
-                                         NULL,
-                                         NULL_TREE);
-      decl_init_priority_insert (decl, priority);
-      break;
     case 'D':
       DECL_STATIC_DESTRUCTOR (decl) = 1;
       decl_fini_priority_insert (decl, priority);
@@ -986,9 +903,8 @@ cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final)
 }
 
 /* Generate and emit a static constructor or destructor.  WHICH must
-   be one of 'I' (for a constructor), 'D' (for a destructor), 'P'
-   (for chkp static vars constructor) or 'B' (for chkp static bounds
-   constructor).  BODY is a STATEMENT_LIST containing GENERIC
+   be one of 'I' (for a constructor) or 'D' (for a destructor).
+   BODY is a STATEMENT_LIST containing GENERIC
    statements.  PRIORITY is the initialization priority for this
    constructor or destructor.  */
 
@@ -1221,7 +1137,7 @@ pass_ipa_cdtor_merge::gate (function *)
   /* Perform the pass when we have no ctors/dtors support
      or at LTO time to merge multiple constructors into single
      function.  */
-  return !targetm.have_ctors_dtors || (optimize && in_lto_p);
+  return !targetm.have_ctors_dtors || in_lto_p;
 }
 
 } // anon namespace
@@ -1391,8 +1307,8 @@ ipa_single_use (void)
 
          if (dump_file)
            {
-             fprintf (dump_file, "Variable %s/%i is used by single function\n",
-                      var->name (), var->order);
+             fprintf (dump_file, "Variable %s is used by single function\n",
+                      var->dump_name ());
            }
          var->used_by_single_function = true;
        }
@@ -1433,17 +1349,10 @@ public:
   {}
 
   /* opt_pass methods: */
-  virtual bool gate (function *);
   virtual unsigned int execute (function *) { return ipa_single_use (); }
 
 }; // class pass_ipa_single_use
 
-bool
-pass_ipa_single_use::gate (function *)
-{
-  return optimize;
-}
-
 } // anon namespace
 
 ipa_opt_pass_d *