re PR ipa/63576 (ICE : in ipa_merge_profiles, at ipa-utils.c:540 during Firefox LTO...
authorJan Hubicka <hubicka@ucw.cz>
Tue, 20 Jan 2015 20:03:23 +0000 (21:03 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Tue, 20 Jan 2015 20:03:23 +0000 (20:03 +0000)
PR ipa/63576
* ipa-utils.c (ipa_merge_profiles): Merge speculative edges.

From-SVN: r219910

gcc/ChangeLog
gcc/ipa-utils.c

index 7b063f3cce2e10a71e2796e017f49dba05e0a273..f9755b8200cc7ceb98b85f530332d126b3315af4 100644 (file)
@@ -1,3 +1,8 @@
+2015-01-19  Jan Hubicka  <hubicka@ucw.cz>
+
+       PR ipa/63576
+       * ipa-utils.c (ipa_merge_profiles): Merge speculative edges.
+
 2015-01-19  Jan Hubicka  <hubicka@ucw.cz>
 
        PR lto/45375
index bc538c58c25c48248b83483a92c6b7a7ebaae351..76125481cd9f9062e121bfc14823902522335f55 100644 (file)
@@ -539,7 +539,7 @@ ipa_merge_profiles (struct cgraph_node *dst,
     }
   if (match)
     {
-      struct cgraph_edge *e;
+      struct cgraph_edge *e, *e2;
       basic_block srcbb, dstbb;
 
       /* TODO: merge also statement histograms.  */
@@ -562,19 +562,95 @@ ipa_merge_profiles (struct cgraph_node *dst,
       pop_cfun ();
       for (e = dst->callees; e; e = e->next_callee)
        {
-         gcc_assert (!e->speculative);
+         if (e->speculative)
+           continue;
          e->count = gimple_bb (e->call_stmt)->count;
          e->frequency = compute_call_stmt_bb_frequency
                             (dst->decl,
                              gimple_bb (e->call_stmt));
        }
-      for (e = dst->indirect_calls; e; e = e->next_callee)
+      for (e = dst->indirect_calls, e2 = src->indirect_calls; e;
+          e2 = (e2 ? e2->next_callee : NULL), e = e->next_callee)
        {
-         gcc_assert (!e->speculative);
-         e->count = gimple_bb (e->call_stmt)->count;
-         e->frequency = compute_call_stmt_bb_frequency
-                            (dst->decl,
-                             gimple_bb (e->call_stmt));
+         gcov_type count = gimple_bb (e->call_stmt)->count;
+         int freq = compute_call_stmt_bb_frequency
+                       (dst->decl,
+                        gimple_bb (e->call_stmt));
+         /* When call is speculative, we need to re-distribute probabilities
+            the same way as they was.  This is not really correct because
+            in the other copy the speculation may differ; but probably it
+            is not really worth the effort.  */
+         if (e->speculative)
+           {
+             cgraph_edge *direct, *indirect;
+             cgraph_edge *direct2 = NULL, *indirect2 = NULL;
+             ipa_ref *ref;
+
+             e->speculative_call_info (direct, indirect, ref);
+             gcc_assert (e == indirect);
+             if (e2 && e2->speculative)
+               e2->speculative_call_info (direct2, indirect2, ref);
+             if (indirect->count || direct->count)
+               {
+                 /* We should mismatch earlier if there is no matching
+                    indirect edge.  */
+                 if (!e2)
+                   {
+                     if (dump_file)
+                       fprintf (dump_file,
+                                "Mismatch in merging indirect edges\n");
+                   }
+                 else if (!e2->speculative)
+                   indirect->count += e2->count;
+                 else if (e2->speculative)
+                   {
+                     if (DECL_ASSEMBLER_NAME (direct2->callee->decl)
+                         != DECL_ASSEMBLER_NAME (direct->callee->decl))
+                       {
+                         if (direct2->count >= direct->count)
+                           {
+                             direct->redirect_callee (direct2->callee);
+                             indirect->count += indirect2->count
+                                                + direct->count;
+                             direct->count = direct2->count;
+                           }
+                         else
+                           indirect->count += indirect2->count + direct2->count;
+                       }
+                     else
+                       {
+                          direct->count += direct2->count;
+                          indirect->count += indirect2->count;
+                       }
+                   }
+                 int  prob = RDIV (direct->count * REG_BR_PROB_BASE ,
+                                   direct->count + indirect->count);
+                 direct->frequency = RDIV (freq * prob, REG_BR_PROB_BASE);
+                 indirect->frequency = RDIV (freq * (REG_BR_PROB_BASE - prob),
+                                             REG_BR_PROB_BASE);
+               }
+             else
+               /* At the moment we should have only profile feedback based
+                  speculations when merging.  */
+               gcc_unreachable ();
+           }
+         else if (e2->speculative)
+           {
+             cgraph_edge *direct, *indirect;
+             ipa_ref *ref;
+
+             e2->speculative_call_info (direct, indirect, ref);
+             e->count = count;
+             e->frequency = freq;
+             int prob = RDIV (direct->count * REG_BR_PROB_BASE, e->count);
+             e->make_speculative (direct->callee, direct->count,
+                                  RDIV (freq * prob, REG_BR_PROB_BASE));
+           }
+         else
+           {
+             e->count = count;
+             e->frequency = freq;
+           }
        }
       src->release_body ();
       inline_update_overall_summary (dst);