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

    <tr>
        <th>Summary</th>
        <td>
            [llvm:optimizations] [missed-optimization] Unable to hoist out call to readonly function in a loop
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

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

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

<pre>
    In clang 21.1.0 (and earlier), in the following code, which is about as reduced as I can get:

```cpp
#include <cstddef>

// [[gnu::noinline]]
// [[gnu::const]]
// [[gnu::noinline, gnu::const]]
static std::size_t count_ints(const int *ints) {
  std::size_t num{};
  while (*ints) {
    num++;
    ints++;
  }
  return num;
}

std::size_t num_compares{};

// Returns if a zero-termed list of ints has 1234
bool has_1234(const int *ints) {
  for (std::size_t index = 0; index < count_ints(ints); ++index) {
    ++num_compares;
    if (ints[index] == 1234) {
      return true;
    }
  }
  return false;
}
```
CE link: https://godbolt.org/z/raPrvq9aT

Here I would expect:
- the `count_ints` function to be noted as `const` (or similar) Certainly "pure". TBAA should note that it only reads through an `int*` if at all. Maybe `argmemonly` (I think?)
- as a result the `count_ints` is called inside the loop (even though it's cleverly been turned into a `wcslen`. I'd hope LICM could yank it out
- that results in poor performance (O(n2)) though naturally this code is awful (on purpose!)

Interestingly, marking it `gnu::const` (not strictly true) still causes the wcslen to be inlined and called every iteration. Making it `noinline` _and_ `const` "fixes" this but I think is not strictly true (as I understand it the read through `*ints` makes it non-const which is to say "readnone" in llvm).

Similar reported to [gcc](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122240).

I discussed this over Discord with a few folks more familiar with LLVM and they said to file this with the tags in the title. Sorry if this is not the correct way to do this.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJyEVtuO2zwOfhrlhpjAkXO8yEVm5g82QItdbLt7O5Al2taOLGUlatLM0_-g7Dm2RQEDicWDyI_kR6uUbOcR92J1K1b3M5WpD3E_KKIumCY4mjXBXPcnD9op34FczBfzCoTcKm8AVXQWo5A7Ie_AeqAeoQ3OhYv1HehgkAWX3uoebALVhEygEkQ0WaPhvyfQykOHJOqDqMqzrsZHn8_8KmvrtcsGQdR3OpEx2Ir6r0lZHoU8Qon_tvOZvdQHH6x31qNY3fPzOzUdfKI_6Ly6knfwG8NEiqyGRGaUJvuMDwQ6ZE8P1lMSclsswHoCIQ_j2Q7E5lZUB_jJ0ueBRZt7UY8Kl946ZNR_YQxFXd7yU78cjUrvz9gb_0akHH2xKZLxvGTxUxAPOgxnFTG9j-YNqX8XVwlsCwqeMYYbwjigAWcTQWhLFNCrBAtZL0V1aEJw_P5Q3v8AShsiZ_w5LOsN_gBR30Ml6tvX17uPcE_OWGOEoeh9hG0UfEjzDb8WXrysJtvVPd_KF4_Rv3f1CivFjG9eXjD_hH2rXMIP6L90vKgOd3-Bs_5R1Afoic6Jky9wTwM5D7ET8vgs5DGqf8Wn_-_U97Eq_8CIcIJLyM4A_jijnmbqpswlD9QbROsK2uw12eCBAjQIPtA4kUWR-3tdBj1ESHawTvGcwx1GUta7KwgpzzmikHIO328PB0h9uZn9APWKwBIE1oyoTALqY8hdD8rzDdaTkJx46R4C5dwcvqprUwJVsRtwYOMpiBNQX1A5clU5JZVAQcSUHf06PZtAK-fQgPXJGixaLoQz-8MnZLYqAVkScpNAO3zC6K7QIMty9MWUAih2ftHJoRfrag4nITcG-nBG-HK6-8qd5wxclX8sKWeaMFc0BZiYG88hRDhjbEMclNdlnP8p5NbLwp-7l3C8ohyVc1dOORUSLdx5abMr9fBwzvEcEgq5GNEQ1eHkCSMmsr5zV-aqQcVHJmFLHP0n5hpB9YEgUbSa-DLuXLmDRNY50ConTAWyMfGpSUYuNMDsP6HLqF3BEkbF3cRVfHfxK32uK3hQ3jx8ai_Z2h-YhJRjtk0mmGrNSf8UYdk8vDSyNxgTcRx2bADustcm41maKGVdwaAeMbGeD_5mJJ3XnUQBkirdzA58YKaXXC_nngYhd_MR32_jCEDEc4g8KBR4U3Ra8w6Q20-zqvW883ma1SZ3z9Y5JeQx9eHy0ORurjsr6qM1or5fSCmX1dtVJzA26ZwS38KghCeMcG-TDtHAxVIPClq88KZ9TDCEiNCqwTqr4ij-8uW_X0uJqMcrJGVLuC3vkOKwKDFmpLr0srfJksM5fAuRy9mOmlMNWK5DjKgJLurK3kwoGvOZ2ddmV-_UDPeLzbqqKym3y1m_39SV3Cwa09SIcrc0SsqtWW4Xu3UlVdvImd3LSq4W1ULKarWQy_l6gwp3Zr3Q27puN1uxrHBQ1s25FIzlzKaUcb9Y19VuM3OqQZfKp4uUHi9QpEJK_pKJeza6aXKXxLLihZTe3JRU2bDUuD6EM9nBPpf-TYXoV7eD5QLcvBex5D9eNQxjgD6ULZepDAKfcAMVwntlVutBFc6Z5ej2n3rEUp-buQ6DkMex2crPzTmG_zF3y2NJKAl5nDJ-2su_AwAA__-v5g6s">