<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">