-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[SimplifyCFG] Fold the contiguous wrapping cases into ICmp. #161000
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
Changes from 8 commits
dc8ea1e
4010221
c56155d
41c4da0
0ce3e6e
dd4fdf6
bfc9e92
9864e17
2288724
7c8dcd0
b89285e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -5718,15 +5718,49 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) { | |||||||
| return Changed; | ||||||||
| } | ||||||||
|
|
||||||||
| static bool casesAreContiguous(SmallVectorImpl<ConstantInt *> &Cases) { | ||||||||
| static bool casesAreContiguous(Value *Condition, | ||||||||
| SmallVectorImpl<ConstantInt *> &Cases, | ||||||||
| ConstantInt *&ContiguousCasesMin, | ||||||||
| ConstantInt *&ContiguousCasesMax, | ||||||||
| bool &IsWrapping) { | ||||||||
| assert(Cases.size() >= 1); | ||||||||
|
|
||||||||
| array_pod_sort(Cases.begin(), Cases.end(), constantIntSortPredicate); | ||||||||
| for (size_t I = 1, E = Cases.size(); I != E; ++I) { | ||||||||
| if (Cases[I - 1]->getValue() != Cases[I]->getValue() + 1) | ||||||||
| auto Min = Cases.back()->getValue(); | ||||||||
| auto Max = Cases.front()->getValue(); | ||||||||
| auto Offset = Max - Min; | ||||||||
| auto ContiguousOffset = Cases.size() - 1; | ||||||||
|
||||||||
| if (Offset == ContiguousOffset) { | ||||||||
| ContiguousCasesMin = Cases.back(); | ||||||||
| ContiguousCasesMax = Cases.front(); | ||||||||
| return true; | ||||||||
| } | ||||||||
| ConstantRange CR = computeConstantRange(Condition, /*ForSigned=*/false); | ||||||||
| // If this is a wrapping contiguous range, that is, [Min, OtherMin] + | ||||||||
| // [OtherMax, Max] (also [OtherMax, OtherMin]), [OtherMin+1, OtherMax-1] is a | ||||||||
| // contiguous range for the other destination. N.B. If CR is not a full range, | ||||||||
| // Max+1 is not equal to Min. It's not continuous in arithmetic. | ||||||||
| if (Max == CR.getUnsignedMax() && Min == CR.getUnsignedMin()) { | ||||||||
| assert(Cases.size() >= 2); | ||||||||
| auto *It = | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about something as follows before the logic here?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (I meant this before the std::adjacent_find, which is not appearing)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is what you want. |
||||||||
| std::adjacent_find(Cases.begin(), Cases.end(), [](auto L, auto R) { | ||||||||
| return L->getValue() != R->getValue() + 1; | ||||||||
| }); | ||||||||
| if (It == Cases.end()) | ||||||||
| return false; | ||||||||
| auto *OtherMax = *It; | ||||||||
| auto *OtherMin = *(It + 1); | ||||||||
|
||||||||
| auto *OtherMax = *It; | |
| auto *OtherMin = *(It + 1); | |
| auto [OtherMax, OtherMin] = std::make_pair(*It, *std::next(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.
I think the function name would deserve an update, e.g.,
findContiguousCases(and maybe return a std::optional struct instead of the three values as out parameters)?