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

Reply via email to