<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/85333>85333</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            GVNSink prodices incorrect codegen with respect to GEPs
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            bug,
            miscompilation,
            llvm:GVN
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          PiJoules
      </td>
    </tr>
</table>

<pre>
    ```
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "thumbv7em-none-unknown-eabi"

%"struct.std::pair" = type <{ i32, %struct.substruct, [2 x i8] }>
%struct.substruct = type { i8, i8 }
%"struct.std::random_access_iterator_tag" = type { i8 }

define linkonce_odr dso_local void @__advance(ptr noundef nonnull align 4 dereferenceable(4) %__i, i32 noundef %__n) local_unnamed_addr {
entry:
 %0 = call i1 @llvm.is.constant.i32(i32 %__n)
  %cmp = icmp eq i32 %__n, 1
  %or.cond = and i1 %0, %cmp
  br i1 %or.cond, label %if.then, label %if.else

if.then:                                          ; preds = %entry
  %1 = load ptr, ptr %__i, align 4
  %incdec.ptr = getelementptr inbounds i8, ptr %1, i32 8
  store ptr %incdec.ptr, ptr %__i, align 4
 br label %if.end6

if.else:                                          ; preds = %entry
  %2 = call i1 @llvm.is.constant.i32(i32 %__n)
  %cmp2 = icmp eq i32 %__n, -1
  %or.cond7 = and i1 %2, %cmp2
  br i1 %or.cond7, label %if.then3, label %if.else5

if.then3: ; preds = %if.else
  %3 = load ptr, ptr %__i, align 4
 %incdec.ptr4 = getelementptr inbounds i8, ptr %3, i32 -8
  store ptr %incdec.ptr4, ptr %__i, align 4
  br label %if.end6

if.else5: ; preds = %if.else
  %4 = load ptr, ptr %__i, align 4
  %add.ptr = getelementptr inbounds %"struct.std::pair", ptr %4, i32 %__n
  store ptr %add.ptr, ptr %__i, align 4
  br label %if.end6

if.end6:                                          ; preds = %if.then3, %if.else5, %if.then
  ret void
}
```

The above IR when piped through gvn-sink via `./bin/opt < /tmp/repro.ll -passes=gvn-sink -S` produces:

```
; ModuleID = '<stdin>'
source_filename = "<stdin>"
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "thumbv7em-none-unknown-eabi"

define linkonce_odr dso_local void @__advance(ptr noundef nonnull align 4 dereferenceable(4) %__i, i32 noundef %__n) local_unnamed_addr {
entry:
  %0 = call i1 @llvm.is.constant.i32(i32 %__n)
  %cmp = icmp eq i32 %__n, 1
  %or.cond = and i1 %0, %cmp
  br i1 %or.cond, label %if.then, label %if.else

if.then:                                          ; preds = %entry
  br label %if.end6

if.else: ; preds = %entry
  %1 = call i1 @llvm.is.constant.i32(i32 %__n)
  %cmp2 = icmp eq i32 %__n, -1
  %or.cond7 = and i1 %1, %cmp2
 br i1 %or.cond7, label %if.then3, label %if.else5

if.then3: ; preds = %if.else
  br label %if.end6

if.else5:                                         ; preds = %if.else
  br label %if.end6

if.end6: ; preds = %if.else5, %if.then3, %if.then
  %.sink1 = phi i32 [ 8, %if.then ], [ -8, %if.then3 ], [ %__n, %if.else5 ]
  %2 = load ptr, ptr %__i, align 4
  %incdec.ptr = getelementptr inbounds i8, ptr %2, i32 %.sink1
  store ptr %incdec.ptr, ptr %__i, align 4
  ret void
}

; Function Attrs: convergent nocallback nofree nosync nounwind willreturn memory(none)
declare i1 @llvm.is.constant.i32(i32) #0

attributes #0 = { convergent nocallback nofree nosync nounwind willreturn memory(none) }
```

The GEP in the result is incorrect. Prior, the GEPs were
```
  %incdec.ptr = getelementptr inbounds i8, ptr %1, i32 8
  %incdec.ptr4 = getelementptr inbounds i8, ptr %3, i32 -8
 %add.ptr = getelementptr inbounds %"struct.std::pair", ptr %4, i32 %__n
```
but now it's
```
%incdec.ptr = getelementptr inbounds i8, ptr %2, i32 %.sink1
```
This results in an incorrect offset for `%add.ptr = getelementptr inbounds %"struct.std::pair", ptr %4, i32 %__n` since we'd now just add `%.sink1` bytes (where `%.sink1 = %__n` which is the second argument), whereas before we'd add `%__n * 8` bytes (where 8 is the sizeof `%"struct.std::pair"`).

The before ASM is:
```
__advance:
        ldr     r2, [r0]
        add.w   r1, r2, r1, lsl #3
        str     r1, [r0]
        bx lr
```
but the after asm is:
```
__advance:
        ldr r2, [r0]
        add     r1, r2
        str     r1, [r0]
        bx lr
```

The GEP should not be a candidate for sinking.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWFtv4zYW_jX0y4ENmZRi-cEPTlwPukCLwU7RV4Mijy12KFJLUnazv35BSr7WmSQ76RYFVghkiTw81-9cFO692hnEBSkeSbEa8S7U1i0-q3_YTqMfVVY-L8hDNvxlK5ItA3c7DCB54Jo_2y4AYSsglOK4IWyJ45awJaPpNl6rcqwecsKWD_l4P6VleiJsOaXlmBO2zHo6w-j4y0NOKL0SEpxqNR4FhLprqv0Mm7GxBsed-WrswYyRV-p0cLjTglDqg-tEmPggCVsStmy5coTSxC48t5HvE5k9gmKU0CcgtDie6Kr-KS0XjxR-B1WSYgVktiLsh5OQW_oL1pFvGc-rMp36hl6OG2mbDRcCvd-ogI4H6zaB7661TSwvmKW7xK0yCFqZr9YI3FjpQHq70VZwDXurJJA822y43HMjkNCyDQ6M7YzELRhrTKc1cK12BnKQ6HCLDo1AXulInRM6j67ZbFSyhtHT4bRq4n4StumM4Q3KDZfSRW17BdEE9xwNTW_xUJZsElxrUNOondb7ZqL8RFjjAzdhkiJSRlknGcPxuCCaNnFQ8QH_BZd0TzC9oLQu8pSJmhuZxNEiG6ItmvZIW7lhbzgRKTSvUMc1tZ2EGs3tGmqPl5E4krElvPki7BFah9IPGC96b50tmKYNbbmENrioQgzfOR5D4C5OKCMkikkiYyvYYUCNDZoQV5SpYvD8gM2B1_QY2fLIxwfr8Lh95via_Mpde8jIhxsPJad9qIfo96OJfgNO4zt4mt0Aip4BRV9C1OwepNg9TBV3QMWiz_7giisQJgXZu-ByFdv8zXBhR7iMX8NL_ipg34aY4o3m5-_OFi7la6nyzWZyISM_umUAzz3XDOI-wi1x6bsS6RKDl-g7vaZqNijkMKRmMmhx6kHXs0F__6VG4JXdI_z4TzjUaKBVLUoItbPdrobd3oy9Ml9hrziQh2xC6LpShtC1bWMLjfLXoWkJXTtsnZ1oDeOWe4-esNXp9PgLecigdVZ2Iu4sryaAG8XYI_xkZafxx9Vg_4ywJx-kMrGh01lP523nBG62SmPsZcfJ44qU_n3moL_bcPD_6eAdve_tzfaNU8Zf2kOnf-yhf0ELfUc7-p66-06RQ6l_idNNyWb3KzihxSTWzT7Wba36IBWPUF4fAFKshg-f2OGveV9ungN8oUsiuJ3O_uT5lV503t7G75xjX2x3p2ay7owIyhpYhuBi8wFhzR7dDk0AEyuerrj4CsZuHSIY65-NSMXxoIyEg9LaYeicgQYb654JLWMxP6WVRKG5w1fTsS_A7Kr_8hCcqrqAPm31aJk9fpiG8Hr7__TDZ1AGQo3g0Hc6gPKgjLDOoQgT-OyUTVEIPbGHAzq8y_TjPmo-bNz9H8yNN06ouhizA6hA6Mzfd_6Hps4N819q5YdIxjgCN-dogt1uPQbYWhenuT_XOQ8ZeGUEwgEJncnklN86H4BLOUgfzHjIoHruc6A81OjwavtYQgeeh1qJOmI04tFjGgu423VR75iT9AkSD-6hwm2sKYP8s9jNxgChSyjvSC5PrNW_0W6HE99wQNyfT26zahC9_PITqIuB9zpU52nuPFb1l5Yu_To6VHCXXRTr_oqhO0SalD49Zf-sfWxRjF3T-zDwnL7Ms_odtHsR1tEtfBvQAffNf23XKzZd6OjoR1pwXfJ8bTsdQRmgQuAguJFK8oApOSLwlNlNRnLB5JzN-QgX09k0y4uymM9H9WKWVYIWeTavMkGRb-OcnRfTeSlkVk63s5Fa0IzmGZvmlFE2nU9YNRczMZMSt9OS8pzkGTZc6UnqGNbtRsr7DhdlwRgbpTnDp3_2Ulp1uz7VCKWN8sI2rdI89rTTcmRC2PLTrz_HpWI1cou4NK66nY9dSfngz5KCChoXn379-Uv8OovfZUrgRdUHYSXu0MBBhToWkzYuBpvq_6hzelGH0Kb40zWh650KdVdNhG0IXSdV-p9x6-xvKAKh62ScJ3Sd7PtPAAAA__-EAXSd">