Fix merging of common traget info.
authorJan Hubicka <hubicka@ucw.cz>
Fri, 13 Dec 2019 15:41:55 +0000 (16:41 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Fri, 13 Dec 2019 15:41:55 +0000 (15:41 +0000)
* ipa-utils.c (ipa_merge_profiles): Improve dumping; merge common
targets.

From-SVN: r279373

gcc/ChangeLog
gcc/ipa-utils.c

index 864d954f8e3b43213361b98d833261e0c2f71672..c40d936e6cbb14e9d16f06e42362ac7782dee36c 100644 (file)
@@ -1,3 +1,8 @@
+2019-12-13  Jan Hubicka  <hubicka@ucw.cz>
+
+       * ipa-utils.c (ipa_merge_profiles): Improve dumping; merge common
+       targets.
+
 2019-12-13  Andrew Stubbs  <ams@codesourcery.com>
 
        * config/gcn/gcn-valu.md (sdwa): New mode attribute.
index fdbecdb7b35ae8aa2f6ca494d239b315329099eb..cc65e2a7a00becfa3d2b599ea20403903d5debad 100644 (file)
@@ -423,11 +423,6 @@ ipa_merge_profiles (struct cgraph_node *dst,
   if (!src->count.initialized_p ()
       || !(src->count.ipa () == src->count))
     return;
-  if (symtab->dump_file)
-    {
-      fprintf (symtab->dump_file, "Merging profiles of %s to %s\n",
-              src->dump_name (), dst->dump_name ());
-    }
   profile_count orig_count = dst->count;
 
   /* Either sum the profiles if both are IPA and not global0, or
@@ -451,6 +446,19 @@ ipa_merge_profiles (struct cgraph_node *dst,
   if (dst->count == orig_count)
     return;
 
+  if (symtab->dump_file)
+    {
+      fprintf (symtab->dump_file, "Merging profiles of %s count:",
+              src->dump_name ());
+      src->count.dump (symtab->dump_file);
+      fprintf (symtab->dump_file, " to %s count:",
+              dst->dump_name ());
+      orig_count.dump (symtab->dump_file);
+      fprintf (symtab->dump_file, " resulting count:");
+      dst->count.dump (symtab->dump_file);
+      fprintf (symtab->dump_file, "\n");
+    }
+
   /* First handle functions with no gimple body.  */
   if (dst->thunk.thunk_p || dst->alias
       || src->thunk.thunk_p || src->alias)
@@ -516,45 +524,86 @@ ipa_merge_profiles (struct cgraph_node *dst,
   else 
     {
       basic_block srcbb, dstbb;
+      struct cgraph_edge *e, *e2;
 
-      FOR_ALL_BB_FN (srcbb, srccfun)
+      for (e = dst->callees, e2 = src->callees; e && e2 && match;
+          e2 = e2->next_callee, e = e->next_callee)
        {
-         unsigned int i;
-
-         dstbb = BASIC_BLOCK_FOR_FN (dstcfun, srcbb->index);
-         if (dstbb == NULL)
+         if (gimple_bb (e->call_stmt)->index
+             != gimple_bb (e2->call_stmt)->index)
            {
              if (symtab->dump_file)
                fprintf (symtab->dump_file,
-                        "No matching block for bb %i.\n",
-                        srcbb->index);
+                        "Giving up; call stmt mismatch.\n");
              match = false;
-             break;
            }
-         if (EDGE_COUNT (srcbb->succs) != EDGE_COUNT (dstbb->succs))
+       }
+      if (e || e2)
+       {
+         if (symtab->dump_file)
+           fprintf (symtab->dump_file,
+                    "Giving up; number of calls differs.\n");
+         match = false;
+       }
+      for (e = dst->indirect_calls, e2 = src->indirect_calls; e && e2 && match;
+          e2 = e2->next_callee, e = e->next_callee)
+       {
+         if (gimple_bb (e->call_stmt)->index
+             != gimple_bb (e2->call_stmt)->index)
            {
              if (symtab->dump_file)
                fprintf (symtab->dump_file,
-                        "Edge count mismatch for bb %i.\n",
-                        srcbb->index);
+                        "Giving up; indirect call stmt mismatch.\n");
              match = false;
-             break;
-           }
-         for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
-           {
-             edge srce = EDGE_SUCC (srcbb, i);
-             edge dste = EDGE_SUCC (dstbb, i);
-             if (srce->dest->index != dste->dest->index)
-               {
-                 if (symtab->dump_file)
-                   fprintf (symtab->dump_file,
-                            "Succ edge mismatch for bb %i.\n",
-                            srce->dest->index);
-                 match = false;
-                 break;
-               }
            }
        }
+      if (e || e2)
+       {
+         if (symtab->dump_file)
+           fprintf (symtab->dump_file,
+                    "Giving up; number of indirect calls differs.\n");
+         match=false;
+       }
+
+      if (match)
+       FOR_ALL_BB_FN (srcbb, srccfun)
+         {
+           unsigned int i;
+
+           dstbb = BASIC_BLOCK_FOR_FN (dstcfun, srcbb->index);
+           if (dstbb == NULL)
+             {
+               if (symtab->dump_file)
+                 fprintf (symtab->dump_file,
+                          "No matching block for bb %i.\n",
+                          srcbb->index);
+               match = false;
+               break;
+             }
+           if (EDGE_COUNT (srcbb->succs) != EDGE_COUNT (dstbb->succs))
+             {
+               if (symtab->dump_file)
+                 fprintf (symtab->dump_file,
+                          "Edge count mismatch for bb %i.\n",
+                          srcbb->index);
+               match = false;
+               break;
+             }
+           for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
+             {
+               edge srce = EDGE_SUCC (srcbb, i);
+               edge dste = EDGE_SUCC (dstbb, i);
+               if (srce->dest->index != dste->dest->index)
+                 {
+                   if (symtab->dump_file)
+                     fprintf (symtab->dump_file,
+                              "Succ edge mismatch for bb %i.\n",
+                              srce->dest->index);
+                   match = false;
+                   break;
+                 }
+             }
+         }
     }
   if (match)
     {
@@ -626,6 +675,70 @@ ipa_merge_profiles (struct cgraph_node *dst,
           e2 = (e2 ? e2->next_callee : NULL), e = e->next_callee)
        {
          profile_count count = gimple_bb (e->call_stmt)->count;
+         if (copy_counts)
+           {
+             e->indirect_info->common_target_id
+                     = e2->indirect_info->common_target_id;
+             e->indirect_info->common_target_probability
+                     = e2->indirect_info->common_target_probability;
+           }
+         else if (e->indirect_info->common_target_id
+                  || e2->indirect_info->common_target_id)
+           {
+             sreal scale1
+                = e->count.ipa().to_sreal_scale (count);
+             sreal scale2
+                = e2->count.ipa().to_sreal_scale (count);
+
+             if (scale1 == 0 && scale2 == 0)
+               scale1 = scale2 = 1;
+             sreal sum = scale1 + scale2;
+             int scaled_probability1
+                     = ((sreal)e->indirect_info->common_target_probability
+                       * scale1 / sum).to_int ();
+             int scaled_probability2
+                     = ((sreal)e2->indirect_info->common_target_probability
+                        * scale2 / sum).to_int ();
+             if (symtab->dump_file)
+               {
+                 fprintf (symtab->dump_file,
+                          "Merging common targets %i prob %i"
+                          " and %i prob %i with scales %f %f\n",
+                          e->indirect_info->common_target_id,
+                          e->indirect_info->common_target_probability,
+                          e2->indirect_info->common_target_id,
+                          e2->indirect_info->common_target_probability,
+                          scale1.to_double (),
+                          scale2.to_double ());
+                 fprintf (symtab->dump_file, "Combined BB count ");
+                 count.dump (symtab->dump_file);
+                 fprintf (symtab->dump_file, " dst edge count ");
+                 e->count.dump (symtab->dump_file);
+                 fprintf (symtab->dump_file, " src edge count ");
+                 e2->count.dump (symtab->dump_file);
+                 fprintf (symtab->dump_file, "\n");
+               }
+             if (e->indirect_info->common_target_id
+                 == e2->indirect_info->common_target_id)
+               e->indirect_info->common_target_probability
+                       = scaled_probability1 + scaled_probability2;
+             else if (!e2->indirect_info->common_target_id
+                      || scaled_probability1 > scaled_probability2)
+               e->indirect_info->common_target_probability
+                       = scaled_probability1;
+             else 
+               {
+                 e->indirect_info->common_target_id
+                         = e2->indirect_info->common_target_id;
+                 e->indirect_info->common_target_probability
+                         = scaled_probability2;
+               }
+             if (symtab->dump_file)
+               fprintf (symtab->dump_file, "Merged as %i prob %i\n",
+                        e->indirect_info->common_target_id,
+                        e->indirect_info->common_target_probability);
+           }
+
          /* 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
@@ -647,8 +760,8 @@ ipa_merge_profiles (struct cgraph_node *dst,
                     indirect edge.  */
                  if (!e2)
                    {
-                     if (dump_file)
-                       fprintf (dump_file,
+                     if (symtab->dump_file)
+                       fprintf (symtab->dump_file,
                                 "Mismatch in merging indirect edges\n");
                    }
                  else if (!e2->speculative)