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