aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-prefetch.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2021-10-04 23:55:43 +0100
committerRichard Sandiford <richard.sandiford@arm.com>2021-10-08 13:17:47 +0100
commit0ee3dc6052361290c92bba492cc0a9e556b31055 (patch)
treeb191e3bb94fe67445ee327752388ceef80c7197e /gcc/tree-ssa-loop-prefetch.c
parent816da497dfba541aabdbe08a03e6e9988a7d9573 (diff)
downloadgcc-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-ssa-loop-prefetch.c')
-rw-r--r--gcc/tree-ssa-loop-prefetch.c3
1 files changed, 1 insertions, 2 deletions
diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c
index 85977e2..04b2b33 100644
--- a/gcc/tree-ssa-loop-prefetch.c
+++ b/gcc/tree-ssa-loop-prefetch.c
@@ -1962,8 +1962,7 @@ loop_prefetch_arrays (class loop *loop)
iterations so that we do not issue superfluous prefetches. */
if (unroll_factor != 1)
{
- tree_unroll_loop (loop, unroll_factor,
- single_dom_exit (loop), &desc);
+ tree_unroll_loop (loop, unroll_factor, &desc);
unrolled = true;
}