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