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
Incorrect optimization of gep without inbounds + load -> icmp eq #44555
Comments
Not sure if I'm using it correctly, but the online instance of Alive2 does not show this as invalid? |
The quick fix: diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
But that causes 5 other test changes (no more optimization) in that same regression test file. I think the tests were meant to exercise various possibilities for that index variable such as "what if its size is too small to cause an overflow?" That is, do we need to use the datalayout in addition to 'inbounds' to decide how to limit this transform? |
You're doing it right; I just think the online version is a bit old. |
I just updated both LLVM and Alive2. The example is still reading as correct, and I have made sure I'm not seeing cached results. |
For the given testcase, we only produce the wrong result for precisely x == 0x80000009. We could mask off the high bit to produce the correct result, I think. The general form of the transform is something like "(x & (-1 >> TrailingBits(sizeof(IndexedType)))) == n". |
I could reproduce this with 64 bits offset: Alive2 says the offset can be truncated and compared as well: |
Right, both the target data & sizeof(type) are important because the bug is triggered as Eli say when sext(idx) * sizeof(type) overflows. It seems there's a bug in Alive2 and/or the online tool ATM, sorry. We are looking into it. The example I posted is valid though. |
Alive2 + CE problem was my fault. Should be fixed now, sorry about that. |
Alive2 link: https://alive2.llvm.org/ce/z/bGG9Vy |
Extended Description
The following unit test in "Transforms/InstCombine/load-cmp.ll" exposes an incorrect optimization:
define i1 @test1_noinbounds(i32 %X) {
; CHECK-LABEL: @test1_noinbounds(
; CHECK-NEXT: [[R:%.]] = icmp eq i32 [[X:%.]], 9
; CHECK-NEXT: ret i1 [[R]]
;
%P = getelementptr [10 x i16], [10 x i16]* @G16, i32 0, i32 %X
%Q = load i16, i16* %P
%R = icmp eq i16 %Q, 0
ret i1 %R
}
Output of Alive2. TL;DR: the optimization is only correct with gep inbounds, otherwise the transformation to "icmp eq" misses the overflow case.
@G16 = constant 20 bytes, align 16
define i1 @test1_noinbounds(i32 %X) {
#init:
store [10 x i16] { 35, 82, 69, 81, 85, 73, 82, 69, 68, 0 }, * @G16, align 16
br label %0
%0:
%P = gep * @G16, 20 x i32 0, 2 x i32 %X
%Q = load i16, * %P, align 2
%R = icmp eq i16 %Q, 0
ret i1 %R
}
=>
@G16 = constant 20 bytes, align 16
define i1 @test1_noinbounds(i32 %X) {
#init:
store [10 x i16] { 35, 82, 69, 81, 85, 73, 82, 69, 68, 0 }, * @G16, align 16
br label %0
%0:
%R = icmp eq i32 %X, 9
ret i1 %R
}
Transformation doesn't verify!
ERROR: Value mismatch
Example:
i32 %X = #x80000009 (2147483657, -2147483639)
Source:
i16 %Q = #x0000 (0)
i1 %R = #x1 (1)
Target:
i1 %R = #x0 (0)
Source value: #x1 (1)
Target value: #x0 (0)
The text was updated successfully, but these errors were encountered: