This is an archive of the discontinued LLVM Phabricator instance.

[SCEV] Extend trip count to avoid overflow by default
ClosedPublic

Authored by reames on Sep 27 2021, 1:59 PM.

Details

Summary

As a brief reminder, an "exit count" is the number of times the backedge executes before some event. It can be zero if we exit before the backedge is reached. A "trip count" is the number of times the loop header is entered if we branch into the loop. A trip count *can not* be zero, and in general, TC = BTC + 1.

There is a cornercases which we don't handle well. Let's assume i8 for our examples to keep things simple. If BTC = 255, then the correct trip count is 256. However, 256 is not representable in i8.

In theory, code which needs to reason about trip counts is responsible for checking for this cornercase, and either bailing out, or handling it correctly. Historically, we don't have a great track record about actually doing so.

When reviewing D109676, I found myself asking a basic question. Was there any good reason to preserve the current wrap-to-zero behavior when converting from backedge taken counts to trip counts? After reviewing existing code, I could not find a single case which appears to correctly and precisely handle the overflow case.

This patch changes the default behavior to extend instead of wrap. That is, if the result might be 256, we return a value of i9 type to ensure we interpret the count correctly. I did leave the legacy behavior as an option since a) loop-flatten stops triggering if I extend due to weirdly specific pattern matching I didn't understand and b) we could reasonably use the mode if we'd externally established a lock of overflow.

I want to emphasize that this change is *not* NFC. There are two call sites (one in ScalarEvolution.cpp, one in LoopCacheAnalysis.cpp) which are switched to the extend semantics. The former appears imprecise (but correct) for a constant 255 BTC. The later appears incorrect, though I don't have a test case.

Diff Detail

Event Timeline

reames created this revision.Sep 27 2021, 1:59 PM
reames requested review of this revision.Sep 27 2021, 1:59 PM
Herald added a project: Restricted Project. · View Herald TranscriptSep 27 2021, 1:59 PM
mkazantsev accepted this revision.Oct 7 2021, 10:26 PM

I'm fine with the change.

How do you think, can we add something to SCEV's verifier to catch this theoretical latent bug?

This revision is now accepted and ready to land.Oct 7 2021, 10:26 PM
This revision was landed with ongoing or failed builds.Oct 11 2021, 9:56 AM
This revision was automatically updated to reflect the committed changes.

I did leave the legacy behavior as an option since a) loop-flatten stops triggering if I extend due to weirdly specific pattern matching I didn't understand and b) we could reasonably use the mode if we'd externally established a lock of overflow.

I wasn't aware of this until I noticed the FIXME and have committed NFC patches rGf6ac8088b0e8 and rGada6d78a7802 to try and clarify this.