This is an archive of the discontinued LLVM Phabricator instance.

[SCEV] Replace NumTripCountsComputed stat with NumExitCountsComputed
ClosedPublic

Authored by dmakogon on Apr 26 2023, 4:48 AM.

Details

Summary

This fixes assertion crash in https://github.com/llvm/llvm-project/issues/62380.

In the beginning of ScalarEvolution::getBackedgeTakenInfo we make sure that BackedgeTakenCounts contains an entry for the given loop.
Then we call computeBackedgeTakenCount which computes the result, and in the end we insert it in the map like so:

return BackedgeTakenCounts.find(L)->second = std::move(Result);

So we expect that the entry for L still exists in the cache.
However, it can get deleted. When it has computed the result, getBackedgeTakenInfo clears all the cached SCEVs that use the AddRecs in the loop.
In the crashing example, getBackedgeTakenInfo first gets called on an inner loop, and during this call it gets called again on its parent loop
. This recursion happens after the call to computeBackedgeTakenCount. And it happens so that some SCEV from the BTI of the child loop uses an AddRec of the parent loop. So when we successfully compute BTI for the parent loop, we erase already computed result for the child one.

The recursion happens in some debug only code that updates statistics. The algorithm itself is non-recursive.
Namely the recursive call happens in BackedgeTakenInfo::getExact function and its return value is only used to compare it against SCEVCouldNotCompute.

As suggested by @nikic I replaced the NumTripCountsComputed and NumTripCountsNotComputed with NumExitCountsComputed and NumExitCountsNotComputed respectively. They are updated during computations made for single exits. It relieves us of the need to compute exact exit count for the loop just to update the named statistic and thus the recursion cannot happen anymore.

Diff Detail

Event Timeline

dmakogon created this revision.Apr 26 2023, 4:48 AM
dmakogon requested review of this revision.Apr 26 2023, 4:48 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 26 2023, 4:48 AM
dmakogon updated this revision to Diff 517124.Apr 26 2023, 4:50 AM

Remove leftover debug print

mkazantsev added inline comments.Apr 28 2023, 4:33 AM
llvm/lib/Analysis/ScalarEvolution.cpp
8419

Please land this refactoring separately.

8444

I wonder, if the key can now be erased, what protects us from infinite recursion?

mkazantsev added inline comments.Apr 28 2023, 4:39 AM
llvm/lib/Analysis/ScalarEvolution.cpp
8452–8453

If the recursion only exists in this debug code to count statistics, and not used in normal algorithm execution, why do we need it at all? I'd rather throw this away than add extra checks/updates just because a non-recursive algorithm becomes recursive because of stat computation.

dmakogon updated this revision to Diff 517884.Apr 28 2023, 5:57 AM

Reworked the change as discussed offline with Max. The recursive call could happen in code that updates some stats. Namely in BackedgeTakenInfo::getExact. But the only usage of its result was to compare it against SCEVCouldNotCompute. So I added a new API to BackedgeTakenInfo which returns whether it can compute the exact exit count for loop and used it instead of its computation.

dmakogon retitled this revision from [SCEV] Don't expect BackedgeTakenCounts cache to contain an entry for loop in getBackedgeTakenInfo to [SCEV] Don't compute exact backedge taken count to update stats.Apr 28 2023, 6:00 AM
dmakogon edited the summary of this revision. (Show Details)
nikic added a comment.Apr 28 2023, 6:03 AM

I think it might make more sense to replace NumTripCountsComputed with NumExitCountsComputed etc (actually NumBruteForceTripCountsComputed already has this meaning, the name is a lie). I think this is the more interesting quantity to look at in terms of how good our calculations are, because whether we can determine an exit count is something we can influence, while whether a BECount can be determined from those exit counts is largely just a question of loop structure.

dmakogon updated this revision to Diff 518993.May 3 2023, 12:39 AM
dmakogon retitled this revision from [SCEV] Don't compute exact backedge taken count to update stats to [SCEV] Replace NumTripCountsComputed stat with NumExitCountsComputed.
dmakogon edited the summary of this revision. (Show Details)

As suggested by @nikic I replaced the NumTripCountsComputed and NumTripCountsNotComputed with NumExitCountsComputed and NumExitCountsNotComputed respectively. They are updated during computations made for single exits. It relieves us of the need to compute exact exit count for the loop just to update the named statistic and thus the recursion cannot happen anymore.

dmakogon marked 2 inline comments as done.May 3 2023, 12:39 AM
nikic added inline comments.May 3 2023, 12:45 AM
llvm/lib/Analysis/ScalarEvolution.cpp
8848

Should we count SymbolicMax or Exact as a "computed" exit count? The previous code was using the exact BECount.

dmakogon updated this revision to Diff 521242.May 11 2023, 3:26 AM

Don't count symbolic exit counts in statistics

llvm/lib/Analysis/ScalarEvolution.cpp
8848

Yeah, we shouldn't. Fixed

dmakogon updated this revision to Diff 521245.May 11 2023, 3:28 AM
nikic accepted this revision.May 14 2023, 10:10 AM

LGTM

This revision is now accepted and ready to land.May 14 2023, 10:10 AM
This revision was landed with ongoing or failed builds.May 22 2023, 6:12 AM
This revision was automatically updated to reflect the committed changes.