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

    <tr>
        <th>Summary</th>
        <td>
            Loop invariant expression using pointers not being optimized
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            llvm:optimizations,
            missed-optimization
      </td>
    </tr>

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

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

<pre>
    For the following snippet (https://godbolt.org/z/3zMhr13rj):

```
#include <iostream>

template <typename T>
void bar(T arg);

void foo0(char *ptr) {
    while (true) {
        const auto mask = (uintptr_t)ptr & 0xf;
        bar(mask);
        ptr += 16;
 }
}

void foo1(int64_t ptr) {
    while (true) {
        const auto mask = ptr & 0xf;
        bar(mask);
        ptr += 16;
 }
}
```

In both cases, the computation of `mask` can be moved outside the loop, as `ptr` is incremented `0x10`, which is greater that the value of the mask `0xf`, therefore the 4 LSB of ptr remain the same as `bar` does not modify its value. However, in the first case `mask` is always computed within the loop. Taking a loop at the IR:

```
define dso_local void @_Z4foo0Pc(ptr noundef %0) local_unnamed_addr #3 !dbg !908 {
  call void @llvm.dbg.value(metadata ptr %0, metadata !912, metadata !DIExpression()), !dbg !916
  br label %2, !dbg !917

2: ; preds = %1, %2
  %3 = phi ptr [ %0, %1 ], [ %6, %2 ]
  call void @llvm.dbg.value(metadata ptr %3, metadata !912, metadata !DIExpression()), !dbg !916
  %4 = ptrtoint ptr %3 to i64, !dbg !918
  %5 = and i64 %4, 15, !dbg !919
  call void @llvm.dbg.value(metadata i64 %5, metadata !913, metadata !DIExpression()), !dbg !920
  tail call void @_Z3barImEvT_(i64 noundef %5), !dbg !921
 %6 = getelementptr inbounds i8, ptr %3, i64 16, !dbg !922
  call void @llvm.dbg.value(metadata ptr %6, metadata !912, metadata !DIExpression()), !dbg !916
  br label %2, !dbg !917, !llvm.loop !923
}

define dso_local void @_Z4foo1l(i64 noundef %0) local_unnamed_addr #3 !dbg !932 {
  call void @llvm.dbg.value(metadata i64 %0, metadata !936, metadata !DIExpression()), !dbg !940
  %2 = and i64 %0, 15, !dbg !941
  br label %3, !dbg !941

3:                                                ; preds = %1, %3
  call void @llvm.dbg.value(metadata i64 poison, metadata !936, metadata !DIExpression()), !dbg !940
  call void @llvm.dbg.value(metadata i64 %2, metadata !937, metadata !DIExpression()), !dbg !942
  tail call void @_Z3barIlEvT_(i64 noundef %2), !dbg !943
 call void @llvm.dbg.value(metadata i64 poison, metadata !936, metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_stack_value)), !dbg !940
  br label %3, !dbg !941, !llvm.loop !944
}
```
For `foo0`, even though the cast `%4 = ptrtoint ptr %3 to i64, !dbg !918` is necessary, couldn't LLVM infer that this is, still, loop invariant?



</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy8V01v2zwS_jX0ZVBDIiXZOviQxDU2QIotdoNdoBeDEimLDUUKJOU0_fUvhpITx3Y_EhQ1DFki5_PhM-MR917tjJQrkl-TfD3jQ2itW3XcPVjfWufsrLLiabWxDkIrobFa20dlduCN6nsZgNBlG0LvCbsidEPoZmdFZXWYW7cjdPOd0A37_ql1KXNfCS1RLFmT5HAtkuk7PlKmTK0HIYGwG2V9cJJ3hH081gmy6zUPUSQ89dLwTsL9s9DeKgEVd4Qu74FjECVh18cGokRjbULosm65A0Kv-uAILYEsJkkAgMdWaYkJBjfIs1381Nb4AHwIFjruH4CwNcoPyoQ-uG0gtOwD2i8g-dY8h3FQH6NEzeMgD7uj5jXaTIuXXbJYT8k837zKKiV0qUwosm2AP5fV30jjhAvxemugsqGFmnvpCb2JLKxt1w-BB2UN2AZIkUTnRQI1N1BJ6OxeCrBD8ErIqKKt7VGdexRHXIoElAdlaic7aYIUuJF8S2ME9AZxqlsU2TnJg0T-8xBt7bkeJDrGhxEh1GwmxdBKJxvrRscZ3P33GoURByc7rkxc98jaMRrEr0hAWOnB2ACdFap5AhX86GoO_7KPci8dWp_UG-V8iKgcp688cP3In_wEkRTwqEI76SAGc7jnD1i_PD7ClNLtf35emEI2ykgQ3m61rbmGyDaSJdsvGVbS55rQJWZo7GCEbIDQPEFyRentYLBIxZYLgWRgDAhNRbXDnzJZHlOw5vrFutb7bi6q3TzigCSTgQse-MSqPAL-vIjWUnq6tL79-K130ntlDaFL5Ch-b45jSIuD_8qB5pXUaJ2eSi2OIaKEXQFh19A7KfxU-3k66uT0YJDQnI0l1Kox7Pz6OXRUAJKv4_24XhwMxPV3ocL-OCqE5tmhDwSrTHh2BcGCKrJTzeWRZh41uREoGE2hdJqf6pRvzHaylp9newbA72RLk4P_wJV-HcT2C6u4u-0-7u-32F-L7Jjp-QVj6aHP0byI-e9kkDq2GoROmQr1Paglah4fHBpPi1N79H1UKP52gYwLMa7YYGLw7OI_1i-aSqrPkf7dnsLoO3rKxKfznsLOUPwdyLLkqAboaQ0kF2sgSy_BzH4gNV4Z9qE3fn7Yttg7MOut8gjDH0btbad2xuqSLd7ln_6yC-jLXYBeMHaA8y-guf7_9t-ft70e_HaIE1wkWNQat3zg9cN28vlT5H_BvUslnmU_n-bwBYIUSZy6xzFJ7iWOJXbYteNQx32AuPfmv5px8jGylt5z94QCtR20MIQuAtzd_e8TKNO8jHA498Vh0gelNd7EPJTZc6e4CYRtXs1C8ToTKyZKVvKZXKXFIi3SjBblrF2VKS_LoqrymtXLnKf1YpEnebWoUkHTJWcztaIJpSmlaVKmi6yc56JqyrpZZsUiSRuxJFmCg6GeR0yt282U94Nc5WXB2CwehY9vaJSiBGFXtg-qU9_jCOwJRfITSjvlvRQfjjdxL1_P3AoVP1TDziMBlQ_-xVlQQcvV3SsIQD5zCwaPA2OPZyHdOKJWEpcmR1LMBqdXJ6-BKrRDNa9tR-gmRj3-fOid_SrrQOgmJukJ3cQ8_wkAAP__WnkmZQ">