diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2021-10-04 23:55:43 +0100 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2021-10-08 13:17:47 +0100 |
commit | 0ee3dc6052361290c92bba492cc0a9e556b31055 (patch) | |
tree | b191e3bb94fe67445ee327752388ceef80c7197e /gcc/tree-predcom.c | |
parent | 816da497dfba541aabdbe08a03e6e9988a7d9573 (diff) | |
download | gcc-0ee3dc6052361290c92bba492cc0a9e556b31055.zip gcc-0ee3dc6052361290c92bba492cc0a9e556b31055.tar.gz gcc-0ee3dc6052361290c92bba492cc0a9e556b31055.tar.bz2 |
loop: Fix profile updates after unrolling [PR102385]
In g:62acc72a957b5614 I'd stopped the unroller from using
an epilogue loop in cases where the iteration count was
known to be a multiple of the unroll factor. The epilogue
and non-epilogue cases still shared this (preexisting) code
to update the edge frequencies:
basic_block exit_bb = single_pred (loop->latch);
new_exit = find_edge (exit_bb, rest);
new_exit->probability = profile_probability::always ()
.apply_scale (1, new_est_niter + 1);
[etc]
But of course (in hindsight) that only makes sense for the
epilogue case, where we've already moved the main loop's exit edge
to be a sibling of the latch edge. For the non-epilogue case,
the exit edge stays (and needs to stay) in its original position.
I don't really understand what the code is trying to do for
the epilogue case. It has:
/* Ensure that the frequencies in the loop match the new estimated
number of iterations, and change the probability of the new
exit edge. */
profile_count freq_h = loop->header->count;
profile_count freq_e = (loop_preheader_edge (loop))->count ();
if (freq_h.nonzero_p ())
{
...
scale_loop_frequencies (loop, freq_e.probability_in (freq_h));
}
Here, freq_e.probability_in (freq_h) is freq_e / freq_h, so for the
header block, this has the effect of:
new header count = freq_h * (freq_e / freq_h)
i.e. we say that the header executes exactly as often as the
preheader edge, which would only make sense if the loop never
iterates. Also, after setting the probability of the nonexit edge
(correctly) to new_est_niter / (new_est_niter + 1), the code does:
scale_bbs_frequencies (&loop->latch, 1, prob);
for this new probability. I think that only makes sense if the
nonexit edge was previously unconditional (100%). But the code
carefully preserved the probability of the original exit edge
when creating the new one.
All I'm trying to do here though is fix the mess I created
and get the probabilities right for the non-epilogue case.
Things are simpler there since we don't have to worry about
loop versioning. Hopefully the comments explain the approach.
The function's current interface implies that it can cope with
multiple exit edges and that the function only needs the iteration
count relative to one of those edges in order to work correctly.
In practice that's not the case: it assumes there is exactly one
exit edge and all current callers also ensure that the exit test
dominates the latch. I think the function is easier to follow
if we remove the implied generality.
gcc/
PR tree-optimization/102385
* predict.h (change_edge_frequency): Declare.
* predict.c (change_edge_frequency): New function.
* tree-ssa-loop-manip.h (tree_transform_and_unroll_loop): Remove
edge argument.
(tree_unroll_loop): Likewise.
* gimple-loop-jam.c (tree_loop_unroll_and_jam): Update accordingly.
* tree-predcom.c (pcom_worker::tree_predictive_commoning_loop):
Likewise.
* tree-ssa-loop-prefetch.c (loop_prefetch_arrays): Likewise.
* tree-ssa-loop-manip.c (tree_unroll_loop): Likewise.
(tree_transform_and_unroll_loop): Likewise. Use single_dom_exit
to retrieve the exit edges. Make all the old profile update code
conditional on !single_loop_p -- the case it was written for --
and use a different approach for the single-loop case.
gcc/testsuite/
* gcc.dg/pr102385.c: New test.
Diffstat (limited to 'gcc/tree-predcom.c')
-rw-r--r-- | gcc/tree-predcom.c | 3 |
1 files changed, 1 insertions, 2 deletions
diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c index ce1f08f..208e755 100644 --- a/gcc/tree-predcom.c +++ b/gcc/tree-predcom.c @@ -3398,8 +3398,7 @@ pcom_worker::tree_predictive_commoning_loop (bool allow_unroll_p) the phi nodes in execute_pred_commoning_cbck. A bit hacky. */ replace_phis_by_defined_names (m_chains); - edge exit = single_dom_exit (m_loop); - tree_transform_and_unroll_loop (m_loop, unroll_factor, exit, &desc, + tree_transform_and_unroll_loop (m_loop, unroll_factor, &desc, execute_pred_commoning_cbck, &dta); eliminate_temp_copies (m_loop, tmp_vars); } |