-
Notifications
You must be signed in to change notification settings - Fork 12.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[NFC][Analysis] Add more SCEV tests for ptr inductions #108210
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For ptr_induction_eq_1, we prove that %b-%a is divisible by 8, so the trip count is (b-a)/8. (If difference isn't divisible by 8, we eventually branch on poison.) Here, we can't prove that: as long as there's another exit, the loop can go on indefinitely (at least, until we read past the end of the allocation). So we can't do any useful math.
If you tell the compiler the pointers are aligned (for example, using an "align" attribute), we do the computation.
Alternatively, we could compute a count assuming the loop exits via a particular branch; see #83052 (review) .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, this looks to be the same underlying issue as for #101372. Looking into why Clang doesn't generate
align
attributes and what would be needed to change that.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But in that example, unless I'm missing something, the early exit dominates the latch. I don't see how the early exit could make the symbolic max loop trip count greater than the backedge-taken count from the latch? I'm probably not explaining myself that well, but what I mean is surely the early exit can only reduce the trip count, not extend it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, consider the something like
%b = N * 8 * %a + 1
, so%exitcond
is never true, so we never exit the loop through it.The early exit then could exit at any later iteration (e.g. when ptr iv is
(N + 2) * 8 * %a
) , before%ptr.iv.next
wraps.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fair enough, but then surely the loop in
ptr_induction_eq_1
could also go on indefinitely and hence have an infinite symbolic max backedge-taken count? From what you're saying it sounds like there is a bug and ptr_induction_eq_1 should also return COULDNOTCOMPUTE?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ptr_induction_eq_1
is different as there's no early exit, so we must exit via the check ofptr.iv.next
.%b = N * 8 * %a + 1
would trigger UB inptr_induction_eq_1
, as %ptr.iv.next` is guaranteed to wrap if the single exit isn't taken.The early exit in
ptr_induction_early_exit_eq_1
allows for scenarios whereptr.iv > %b
while still not triggering UB because then we must exit via the early exit before wrap.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see. That's the bit I was missing. I think I understand this now. Thanks! So if the IR contained information about alignment that might help?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, the reason I'm asking about this is because I believe this to be a common pattern when you invoke the C++ routine
std::find(vec.begin(), vec.end(), needle)
where vec is of typestd::vector
. Theend()
value at least in libc++ is just a pointer, rather than being constructed in terms ofvec.begin() + vec.size()
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This helps us prove the loop is finite, but we can't produce a symbolic bound; at most, we could prove the max iteration count is 2^60 or something like that. Which is marginally helpful.
We could also generate a predicated backedge-taken count, which would be useful in contexts like vectorization. Granted, we don't usually vectorize loops with multiple exits anyway, but I guess that's changing a bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had a look at adding the predicate and it looks that also helps in some non-multi-exit cases: #108777
#101372 also contains some discussion about encoding alignment assumptions for certain libc++ data types/interfaces, as that would also help in other cases for which versioning is not applicable (e.g. removing bounds checks)