When folding and/or of icmps, look through add of a constant and adjust the icmp range instead. Effectively, this decomposes X + C1 < C2 style range checks back into a normal range. This allows us to fold comparisons involving two range checks or one range check and some other condition. We had a fold for a really specific case of this (or of range check and eq, and only one one side!) while this handles it in fully generality.
Details
Diff Detail
Event Timeline
I expect this will subsume a few more folds strewn about, such as https://github.com/llvm/llvm-project/blob/24e07e1cf58841601287dca3df55078041dde00d/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp#L777-L789. However, this fold needs to be expanded to support splats first (which is trivial, but affects a number of folds under the same branch, so I'll do that separately).
Nice!
I don't see any test diffs with 2 signed preds. Is there any value in adding a test like that to further exercise the range logic?
define i1 @src(i64 %x) { %t1 = add i64 %x, 127 %t2 = icmp slt i64 %t1, 1024 %t3 = add i64 %x, 128 %t4 = icmp slt i64 %t3, 256 %t5 = and i1 %t2, %t4 ret i1 %t5 }
llvm/test/Transforms/InstCombine/signed-truncation-check.ll | ||
---|---|---|
957–958 | It's not a single instruction, but don't need this comment now. |
Rebase over test with signed preds (https://alive2.llvm.org/ce/z/qv9MZr), drop outdated comment.
I actually thought that we were already canonicalizing signed range checks to unsigned ones, but apparently we aren't.
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | ||
---|---|---|
1209–1221 | Can this happen though? In canonical IR this will get folded to (x + (C1 + C0) < C2) | (x + C0 < C3), at which point we have the expected pattern. (In non-canonical IR this is not the case, but that shouldn't be a problem as this is not a question of correctness -- the fold will apply only once it has become canonical.) | |
2467 | It doesn't require both comparisons to have an add. We can have an add on neither, both or one of them (this pattern). |
LGTM
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | ||
---|---|---|
1209–1210 | On first look, I also didn't catch that this block will match either 1 or 2 offsets, so we should make that clear in the code comment. // Look through add of a constant offset on V1, V2, or both operands... |
On first look, I also didn't catch that this block will match either 1 or 2 offsets, so we should make that clear in the code comment.
Something like: