re PR middle-end/65743 (LTO+FDO build of Firefox crashes at startup)
authorJan Hubicka <hubicka@ucw.cz>
Sun, 12 Apr 2015 05:44:52 +0000 (07:44 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 12 Apr 2015 05:44:52 +0000 (05:44 +0000)
PR ipa/65743
* ipa-inline-transform.c (speculation_removed): Remove static var.
(check_speculations): New function.
(clone_inlined_nodes): Do not check spculations.
(inline_call): Call check_speculations.
* ipa-prop.c (ipa_make_edge_direct_to_target): Do not
consider non-invariants.

From-SVN: r222017

gcc/ChangeLog
gcc/ipa-inline-transform.c
gcc/ipa-prop.c

index 19350f358944c7554a91357a750c99d17713b389..687770055df266d13c3c166f773bf55c180b864e 100644 (file)
@@ -1,3 +1,13 @@
+2015-04-11 Jan Hubicka  <hubicka@ucw.cz>
+
+       PR ipa/65743
+       * ipa-inline-transform.c (speculation_removed): Remove static var.
+       (check_speculations): New function.
+       (clone_inlined_nodes): Do not check spculations.
+       (inline_call): Call check_speculations.
+       * ipa-prop.c (ipa_make_edge_direct_to_target): Do not
+       consider non-invariants.
+
 2015-04-11 Jan Hubicka  <hubicka@ucw.cz>
           Martin Liska  <mliska@suse.cz>
 
index 99ed512ea96ff4d188c2386c103265437053f172..5a628f39dd68b6c314e6ea19a25de0286497d54c 100644 (file)
@@ -64,7 +64,6 @@ along with GCC; see the file COPYING3.  If not see
 
 int ncalls_inlined;
 int nfunctions_inlined;
-bool speculation_removed;
 
 /* Scale frequency of NODE edges by FREQ_SCALE.  */
 
@@ -256,12 +255,29 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
       next = e->next_callee;
       if (!e->inline_failed)
         clone_inlined_nodes (e, duplicate, update_original, overall_size, freq_scale);
+    }
+}
+
+/* Check all speculations in N and resolve them if they seems useless. */
+
+static bool
+check_speculations (cgraph_node *n)
+{
+  bool speculation_removed = false;
+  cgraph_edge *next;
+
+  for (cgraph_edge *e = n->callees; e; e = next)
+    {
+      next = e->next_callee;
       if (e->speculative && !speculation_useful_p (e, true))
        {
          e->resolve_speculation (NULL);
          speculation_removed = true;
        }
+      else if (!e->inline_failed)
+       speculation_removed |= check_speculations (e->callee);
     }
+  return speculation_removed;
 }
 
 /* Mark all call graph edges coming out of NODE and all nodes that have been
@@ -310,7 +326,6 @@ inline_call (struct cgraph_edge *e, bool update_original,
   bool predicated = inline_edge_summary (e)->predicate != NULL;
 #endif
 
-  speculation_removed = false;
   /* Don't inline inlined edges.  */
   gcc_assert (e->inline_failed);
   /* Don't even think of inlining inline clone.  */
@@ -360,6 +375,7 @@ inline_call (struct cgraph_edge *e, bool update_original,
     mark_all_inlined_calls_cdtor (e->callee);
   if (opt_for_fn (e->caller->decl, optimize))
     new_edges_found = ipa_propagate_indirect_call_infos (curr, new_edges);
+  check_speculations (e->callee);
   if (update_overall_summary)
    inline_update_overall_summary (to);
   new_size = inline_summaries->get (to)->size;
index 89a4623e0c2884e10eccf08a447efc2147717df7..dc8f3606b1e295bdf8371296b8269965d8e714d7 100644 (file)
@@ -2626,9 +2626,29 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target,
       target = canonicalize_constructor_val (target, NULL);
       if (!target || TREE_CODE (target) != FUNCTION_DECL)
        {
-         if (ie->indirect_info->member_ptr)
-           /* Member pointer call that goes through a VMT lookup.  */
-           return NULL;
+         /* Member pointer call that goes through a VMT lookup.  */
+         if (ie->indirect_info->member_ptr
+             /* Or if target is not an invariant expression and we do not
+                know if it will evaulate to function at runtime.
+                This can happen when folding through &VAR, where &VAR
+                is IP invariant, but VAR itself is not.
+
+                TODO: Revisit this when GCC 5 is branched.  It seems that
+                member_ptr check is not needed and that we may try to fold
+                the expression and see if VAR is readonly.  */
+             || !is_gimple_ip_invariant (target))
+           {
+             if (dump_enabled_p ())
+               {
+                 location_t loc = gimple_location_safe (ie->call_stmt);
+                 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+                                  "discovered direct call non-invariant "
+                                  "%s/%i\n",
+                                  ie->caller->name (), ie->caller->order);
+               }
+             return NULL;
+           }
+
 
           if (dump_enabled_p ())
            {