<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/154936>154936</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[separate-const-offset-from-gep] miscompile for trunc
</td>
</tr>
<tr>
<th>Labels</th>
<td>
miscompilation,
llvm:optimizations
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
ritter-x2a
</td>
</tr>
</table>
<pre>
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)
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzUVk1v2zwS_jX0ZSBDGllfBx-cOC4KBG2xLXaBvVHUSOKWIgWSip3--gUlOc6m2Rct8F4KyBAtDoczzzzzwZ2TnSbas-yOZccNn3xv7N5K78lGF-Sb2jTPe6WeBhBmGKRn6QGSjCcVioayuqzqfFcWoq4yXhBRW7Q8rRMs2jIvWHxg8eEfNFrTTILgLH3P0vCN5fH6xAczeogGb-WoiKVHPjSd0BEfmvDrHYdoEOPE0mPXXhKMY4hG7hw5lh4djdxyT5Ew2vnItK0jH7XWDFFHI0Rf4UXizV7k7aRFNEgnzDBKRVul3tjF4sO3noB7z0VPDQjT0M_WN9RKTTB6C2wXOysYlvMfzEaG9yDzXVhzhhWw4o7FB5j_Nw2w9AjhfRO5hzIIMMxm82aJZXWVaRrwBmSKV0WOLn6WmxcyxdvpIJjvXm60lj_L5jILd-RJ0UDaB1ulrs2kGwd6Os-68R7e8SHcMGuz5K_7V60BleL4Bhvp4GyN7tQzeMu1a40dqAGpvQHfS_d3QIpp_BrX5B3M3iCGP8GVvIEqfQ-j_wsLvkUY3ztevjqdXk-vRr2DJ74LKIsPByWfCMH15uwWEF-g5V4aHVypCaRS1HEVspVld3w5pKT-zrIjw7L3fnQBeTwxPC3b25DlW2M7hidBDE8_GJ76xy-tODOstsv14cF0eeBz7cg-zde6a8JIB4Pseh-MsKS4p5mxvidgWHoDA4W4TZouI4mw23PdKKk7MO0ilsefjP5EHffyiVgeQ6t4B1KHnfuQ6Fz7z3M6P1y85cIbG1xJD63UTQBqYVR299GDdJph4UEo4pYaaI1d2PEeDp30_VRvhRkYngIa6ysarfkPCc_wVCtTMzy1aZxTzKlGUSDFu1hkFSV5TGXJ27Rui3yXFXmVvtIjw7lv11g5hqevgituw2ItUrNzi2cna4YPD1-2YhwZpo95nEePeVwxrAJ36smHsMrg3-zSj5Caf5ZHSRE95hgvSYw1CT45WhzBcsnt9CEkUgyNIQfaeJDDqJ6Bv-wwRIgi8D33s9AS696oV4EGkr4nu13L-UBcr2T7mWhcOQOOaHBgmmZNnsDJxogppPLM9T8LaEyz6BHTK3Ucf15zlaUP8Mr_AOS_egpYwT8Dr7qJW649LQlcE2ijI71Kb-FkLNCFD6Fr4z1wDVI3dAnAzuu1pXx4-PILyh7piVvehcCEmhYUngkE11BTGEXAjSqw_ZVWt1akj9CYJe6-l_r7TAaGhQMbytBcaf_HFt1IQW7VDS8m3Br-pEXPdUcNhDnjxpWvstMPF0-6oWYmi27C53-TNa8_34i31MGZUzXB2Vjfg-hJfA86pb62QO3p4tf7T8FQOPdSEShjVklvQp9Lsl2S5Nc6nN39zmiz9b9QHyZHNlrGncD1wLNWKgpvTKq0KOKC4em3r8Vq0-zTpkorvqF9UmRZmWdlkW_6fdzWFeZUJ9SWZYlV0RYJr3dJ3tZpnrdiI_cYYxaXiAmmwftCpAXtdjllnAuRtGwX08ClemleG-ncRPsk21VpvlG8JuXm6RbxxbQlizE0dIY4Z1kaxlA5yB9rN0MM47CdJ9-onjrHdrGSzrvbRV56NQ_Ofz2FsuwIN1Bu9NhMVu1_u4jM3oWIrA4-7fG_AQAA__8CIbYE">