<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/61362>61362</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
GVN incorrectly converts load to a constant with the `allockind(alloc,zeroed)` attribute
</td>
</tr>
<tr>
<th>Labels</th>
<td>
miscompilation,
llvm:GVN
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
aykevl
</td>
</tr>
</table>
<pre>
I have the following IR, which is a simplified version of a real bug I'm hitting over at https://github.com/tinygo-org/tinygo/pull/3540:
```llvm
define i16 @readValue(ptr %addr, ptr %wait) optsize {
entry:
; allocate memory for %value
%value = call ptr @alloc(i32 2)
; store this pointer into a hardware register
%value_int = ptrtoint ptr %value to i32
store volatile i32 %value_int, ptr %addr
; wait until the hardware has written to %value
br label %loop
loop:
%ready = load volatile i1, ptr %wait
br i1 %ready, label %loop, label %done
done:
; condition is satisfied, read the result from %value
%result = load i16, ptr %value
ret i16 %result
}
```
The code works as follows:
1. An object is allocated on the heap.
2. A pointer to this object is stored in a hardware register.
3. The code waits for the hardware to change the value.
4. The value is loaded, and returned.
After `opt -passes=gvn`, the IR looks like this ([Godbolt link](https://llvm.godbolt.org/z/axoqPx19z)):
```llvm
define i16 @readValue(ptr %addr, ptr %wait) #1 {
%value = call ptr @alloc(i32 2)
%value_int = ptrtoint ptr %value to i32
store volatile i32 %value_int, ptr %addr, align 4
br label %loop
loop: ; preds = %loop, %entry
%ready = load volatile i1, ptr %wait, align 1
br i1 %ready, label %loop, label %done
done: ; preds = %loop
ret i16 0
}
```
Unfortunately, GVN converts the load and return at the end to a simple constant `ret i16 0`. This is unexpected, and I believe this is a bug in GVN.
The logic in GVN appears to be that the call to `@alloc` returns zeroed memory, it doesn't see any store to the memory, and therefore it believes the load at the end can be replaced with a zero value. However, in this case, the pointer actually escapes before it is loaded at the end so as I see it, GVN should not have assumed the value didn't change.
Some notes:
- It is still reproducible when I use `store volatile ptr %value, ptr %addr` (storing the pointer as a pointer type, instead of as a ptrtoint).
- It also reproduces without the loop, but I put the loop in there to make the code a bit more realistic.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0Vk2PIjkS_TXmEiqUOCGBA4f6EL1cWqve3b6unOmAjClj59iR0NSvH9lOPqfVmu7RlEpVYDvsF-H3XliFQDuLuBKzFzF7G6meW-dX6vSOBzOqnT6tNtCqAwK3CFtnjDuS3cHmi5CvcGypaYECKAi07wxtCTUc0AdyFtwWFHhUBup-Bxsh53toiTnGuwN6UAwtcxdE-SzkWsj1jrjt63Hj9kKumexp556c312-CLnuemOEXJezaRHDijdRnP9WRf415rDPQxq3ZBFoUoGYFh6V_qpMj0IuOvYg5Exp7WMiw9ejIhZyCa7jQB8IYv6SN0LL_nQ5D0CUL6CMcY1ihD3unT_B1qU9DumE87rhO4jyDRplTD5pWqRgIRdUSpBCLm8TydsHdj5WnQJ0jiyjB7LsQEGrvD4qj-BxR4HRP572f7KcTuzYc4w955exsAMq5RCUjzk4o5gMxom7bW6Kk2r1J5ixZNBbJpMYcsHWqgBHT8xo44GPhak9GFWjiRPGuS6Pp083VZazeGenlItxSt_gnDxe23Vjmlwi46L7c24HtLMDoPTpnk45vcZZTRzZTAGCYgqR4nGXuH9K2WPoDcPWu_337n-YvqRAk-oG-t1qj5y5eo4a8MzfHhh-i_O_LULjNMLR-fcAKgwqDQ_5TMbwbMHVv2HDSbIDfTU4m68OVTfOa-UYni-sY5dZeA1NnNFA9ntkHLYox3BFpohD0scdRdhB0yq7y96SKjEET3NwpiuFVLhcdWV1LFPvLerxbXrP24hVVIXrGJ46FQIGUb7tDjbWS76mMzZfwDj3HsDQ-6AtIRdi9vLJ6doZBkP2XczehFzcG1O0lPEuLxpnR_oQcq2-ud___W2y_IgKlst_zpCELCdXN_ppX_k1a_hZb4jXY2hnYfpjld9pPams86hDgnUjUyFn2XZ_xQ0uWCZ_zxju7AF-5uf7eT0ovfgrCv-f3TrPvVWMJgH_9PVzNKYDeg6J16kaV2nExhqH0WpIHSM15yhGG1hFAlTFFUFVRLVRiELrLX7rsOGr2DZQoyE8DHJJvT62c7IRxvjRiYzbUTNMguo6VD5EDHWMH2AlvsaeUBUXxlbFgD3AB3qHeuiqEQYxaIfBCjlnCIig7OncHl3a8bo2QuYWPW7jNPEZ_W2drsVplI3IPHZGNajhSNyCSggGP4J_uSMeMJGbbK5BowKeHeVskqrhXhlzAgyN6jBAfUFw8a_bk4OLTr1J6WS6xoKF1vVGg3Wc31wqhH6P-uqPoEnnOmTnvKv_f9weYyw-Wv8TbAbfJmNitt7pvqHaIBxbtLCBPmC8jgfB3_WoB7FXRbTOGBCfc3eliBS5NI9Th7l2gWPDjG_CND_Yj5DL8Q1IZYK7AMSQLsT1PFxeVmndM2yguxnNN4OZD3v1nhtKaj0KamLYu9SglKHA1IxHelXqZblUI1xNqvmimlVTWYzaVbOs542eLZda6uViIafLalmVM62Xizlup_WIVrKQZVFOpJzIeVGMZSkbicUM59V2MsetmBa4V2TGqWM4vxtRCD2uqklZyVEymJDe2lLuKTRu31EstrNCSiFfhZSpWZTPn75-jkOzt5FfxaGnut8FMS1iCuG6OxMbXEXukG2c99iwOV3NIRE-WcBF-4njsT6iytp7J6uFXAyd4zXLL7aOqgDF7KnuGUe9N6sfPNYT6vzvqfMuvhSEXKfcg5DrlP4fAQAA___sJeHo">