ipa-inline-analysis.c (redirect_to_unreachable): Be prepared for edge to change by...
authorJan Hubicka <hubicka@ucw.cz>
Fri, 27 Mar 2015 04:01:04 +0000 (05:01 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Fri, 27 Mar 2015 04:01:04 +0000 (04:01 +0000)
* ipa-inline-analysis.c (redirect_to_unreachable): Be prepared for
edge to change by speculation resolution or redirection.
(edge_set_predicate): Likewise.
(inline_summary_t::duplicate): Likewise.
(remap_edge_summaries): Likewise.
* gcc.c-torture/compile/20150327.c: New testcase.

From-SVN: r221718

gcc/ChangeLog
gcc/ipa-inline-analysis.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/20150327.c [new file with mode: 0644]

index 14cfadca4095e0d41cd81736a3313154c127fec5..992cd5360b9a5bedcdddd72a2da3b5957b94d05c 100644 (file)
@@ -1,3 +1,11 @@
+2015-03-26  Jan Hubicka  <hubicka@ucw.cz>
+
+       * ipa-inline-analysis.c (redirect_to_unreachable): Be prepared for
+       edge to change by speculation resolution or redirection.
+       (edge_set_predicate): Likewise.
+       (inline_summary_t::duplicate): Likewise.
+       (remap_edge_summaries): Likewise.
+
 2015-03-26  Jan Hubicka  <hubicka@ucw.cz>
 
        * ipa-inline.c (check_maybe_up, check_maybe_down, check_match):
index 6f34c47449b60c72ceda712b6e6dfa27ff11f4a9..a9d885fe34dd383513e2fbad722a39e37cd71013 100644 (file)
@@ -762,20 +762,20 @@ account_size_time (struct inline_summary *summary, int size, int time,
 
 /* We proved E to be unreachable, redirect it to __bultin_unreachable.  */
 
-static void
+static struct cgraph_edge *
 redirect_to_unreachable (struct cgraph_edge *e)
 {
   struct cgraph_node *callee = !e->inline_failed ? e->callee : NULL;
-  struct inline_edge_summary *es = inline_edge_summary (e);
 
   if (e->speculative)
-    e->resolve_speculation (builtin_decl_implicit (BUILT_IN_UNREACHABLE));
-  if (!e->callee)
+    e = e->resolve_speculation (builtin_decl_implicit (BUILT_IN_UNREACHABLE));
+  else if (!e->callee)
     e->make_direct (cgraph_node::get_create
                      (builtin_decl_implicit (BUILT_IN_UNREACHABLE)));
   else
     e->redirect_callee (cgraph_node::get_create
                        (builtin_decl_implicit (BUILT_IN_UNREACHABLE)));
+  struct inline_edge_summary *es = inline_edge_summary (e);
   e->inline_failed = CIF_UNREACHABLE;
   e->frequency = 0;
   e->count = 0;
@@ -783,6 +783,7 @@ redirect_to_unreachable (struct cgraph_edge *e)
   es->call_stmt_time = 0;
   if (callee)
     callee->remove_symbol_and_inline_clones ();
+  return e;
 }
 
 /* Set predicate for edge E.  */
@@ -790,12 +791,12 @@ redirect_to_unreachable (struct cgraph_edge *e)
 static void
 edge_set_predicate (struct cgraph_edge *e, struct predicate *predicate)
 {
-  struct inline_edge_summary *es = inline_edge_summary (e);
-
   /* If the edge is determined to be never executed, redirect it
      to BUILTIN_UNREACHABLE to save inliner from inlining into it.  */
   if (predicate && false_predicate_p (predicate))
-    redirect_to_unreachable (e);
+    e = redirect_to_unreachable (e);
+
+  struct inline_edge_summary *es = inline_edge_summary (e);
   if (predicate && !true_predicate_p (predicate))
     {
       if (!es->predicate)
@@ -1184,7 +1185,7 @@ inline_summary_t::duplicate (cgraph_node *src,
       size_time_entry *e;
       int optimized_out_size = 0;
       bool inlined_to_p = false;
-      struct cgraph_edge *edge;
+      struct cgraph_edge *edge, *next;
 
       info->entry = 0;
       known_vals.safe_grow_cleared (count);
@@ -1229,10 +1230,11 @@ inline_summary_t::duplicate (cgraph_node *src,
 
       /* Remap edge predicates with the same simplification as above.
          Also copy constantness arrays.   */
-      for (edge = dst->callees; edge; edge = edge->next_callee)
+      for (edge = dst->callees; edge; edge = next)
        {
          struct predicate new_predicate;
          struct inline_edge_summary *es = inline_edge_summary (edge);
+         next = edge->next_callee;
 
          if (!edge->inline_failed)
            inlined_to_p = true;
@@ -1249,10 +1251,11 @@ inline_summary_t::duplicate (cgraph_node *src,
 
       /* Remap indirect edge predicates with the same simplificaiton as above. 
          Also copy constantness arrays.   */
-      for (edge = dst->indirect_calls; edge; edge = edge->next_callee)
+      for (edge = dst->indirect_calls; edge; edge = next)
        {
          struct predicate new_predicate;
          struct inline_edge_summary *es = inline_edge_summary (edge);
+         next = edge->next_callee;
 
          gcc_checking_assert (edge->inline_failed);
          if (!es->predicate)
@@ -3484,11 +3487,12 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
                      clause_t possible_truths,
                      struct predicate *toplev_predicate)
 {
-  struct cgraph_edge *e;
-  for (e = node->callees; e; e = e->next_callee)
+  struct cgraph_edge *e, *next;
+  for (e = node->callees; e; e = next)
     {
       struct inline_edge_summary *es = inline_edge_summary (e);
       struct predicate p;
+      next = e->next_callee;
 
       if (e->inline_failed)
        {
@@ -3509,10 +3513,11 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
                              operand_map, offset_map, possible_truths,
                              toplev_predicate);
     }
-  for (e = node->indirect_calls; e; e = e->next_callee)
+  for (e = node->indirect_calls; e; e = next)
     {
       struct inline_edge_summary *es = inline_edge_summary (e);
       struct predicate p;
+      next = e->next_callee;
 
       remap_edge_change_prob (inlined_edge, e);
       if (es->predicate)
index 226ac2ac18ca137bfaf773ce090873e76a7d0b40..135dfc03e9e05062b9adf256a836ccd6f17abf68 100644 (file)
@@ -1,3 +1,7 @@
+2015-03-26  Jan Hubicka  <hubicka@ucw.cz>
+
+       * gcc.c-torture/compile/20150327.c: New testcase.
+
 2015-03-26  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/65555
diff --git a/gcc/testsuite/gcc.c-torture/compile/20150327.c b/gcc/testsuite/gcc.c-torture/compile/20150327.c
new file mode 100644 (file)
index 0000000..373ea61
--- /dev/null
@@ -0,0 +1,11 @@
+int a;
+int (*b)(), (*c)();
+int fn1(int p1) {
+  if (a)
+    return 0;
+  if (p1) {
+    c();
+    b();
+  }
+}
+void fn2() { fn1(0); }