]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/tree-cfg.cc
Fix profile update after cancelled loop distribution
[thirdparty/gcc.git] / gcc / tree-cfg.cc
index c65af8cc8003d1930d4dbccc11669fde18d2cdd2..c158454946c623876213dd1a990330b5270d9e90 100644 (file)
@@ -7703,6 +7703,44 @@ fold_loop_internal_call (gimple *g, tree value)
       FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
        SET_USE (use_p, value);
       update_stmt (use_stmt);
+      /* If we turn conditional to constant, scale profile counts.
+        We know that the conditional was created by loop distribution
+        and all basic blocks dominated by the taken edge are part of
+        the loop distributed.  */
+      if (gimple_code (use_stmt) == GIMPLE_COND)
+       {
+         edge true_edge, false_edge;
+         extract_true_false_edges_from_block (gimple_bb (use_stmt),
+                                              &true_edge, &false_edge);
+         edge taken_edge = NULL, other_edge = NULL;
+         if (gimple_cond_true_p (as_a <gcond *>(use_stmt)))
+           {
+             taken_edge = true_edge;
+             other_edge = false_edge;
+           }
+         else if (gimple_cond_false_p (as_a <gcond *>(use_stmt)))
+           {
+             taken_edge = false_edge;
+             other_edge = true_edge;
+           }
+         if (taken_edge
+             && !(taken_edge->probability == profile_probability::always ()))
+           {
+             profile_count old_count = taken_edge->count ();
+             profile_count new_count = taken_edge->src->count;
+             taken_edge->probability = profile_probability::always ();
+             other_edge->probability = profile_probability::never ();
+             /* If we have multiple predecessors, we can't use the dominance
+                test.  This should not happen as the guarded code should
+                start with pre-header.  */
+             gcc_assert (single_pred_edge (taken_edge->dest));
+             taken_edge->dest->count
+               = taken_edge->dest->count.apply_scale (new_count,
+                                                      old_count);
+             scale_strictly_dominated_blocks (taken_edge->dest,
+                                              new_count, old_count);
+           }
+       }
     }
 }