Issue |
154936
|
Summary |
[separate-const-offset-from-gep] miscompile for trunc
|
Labels |
miscompilation,
llvm:optimizations
|
Assignees |
|
Reporter |
ritter-x2a
|
llvm commit: 15a192cde5b89b6487cb95a7eeef7fa3b127f867
Reproduce with:
```
opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1200 -passes=separate-const-offset-from-gep -S separate-offset-from-gep-trunc-miscompile.ll
```
The attached code:
```
define ptr @src(ptr %p, i64 %a) {
%add = add i64 %a, 8
%trunc = trunc i64 %add to i32
%sext = sext i32 %trunc to i64
%arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %sext
ret ptr %arrayidx
}
```
is wrongly transformed into this code:
```
define ptr @src(ptr %p, i64 %a) #0 {
%1 = trunc i64 %a to i32
%2 = sext i32 %1 to i64
%3 = getelementptr i32, ptr %p, i64 %2
%arrayidx2 = getelementptr i8, ptr %3, i64 32
ret ptr %arrayidx2
}
```
Alive2 shows this transformation to be illegal: [alive2 link](https://alive2.llvm.org/ce/z/hLPfcw).
### Observations
This might be related to the (to me) unexpected handling of the `NonNegative` flag in `ConstantOffsetExtractor::find`:
[It isn't cleared for trunc](https://github.com/llvm/llvm-project/blob/f306e0aeb2c72e040c59e160e88af3bf76457693/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp#L606-L609), but [it is for zext](https://github.com/llvm/llvm-project/blob/f306e0aeb2c72e040c59e160e88af3bf76457693/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp#L617-L620) "because zext(a) >= 0 does not imply a >= 0" -- that doesn't hold for trunc either.
The meaning of `NonNegative` also seems odd: [the documentation](https://github.com/llvm/llvm-project/blob/f306e0aeb2c72e040c59e160e88af3bf76457693/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp#L235-L239), says
> NonNegative -- Whether V is guaranteed to be non-negative. For example, an index of an inbounds GEP is guaranteed to be non-negative. Levaraging this, we can better split inbounds GEPs.
I don't think that's right, inbounds GEP indices can be negative.
The unchanged passing of `SignExtended` and `ZeroExtended` for trunc might also be worth checking in this context.
Found while looking into #154116.
[separate-offset-from-gep-trunc-miscompile.ll.txt](https://github.com/user-attachments/files/21937707/separate-offset-from-gep-trunc-miscompile.ll.txt)
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs