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

    <tr>
        <th>Summary</th>
        <td>
            Missed optimization for `*(ptr << 2)`
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

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

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

<pre>
    For this function (which is essentially `*(ptr << 2)`) llvm generates the following assembly:
```llvm
define noundef i32 @shift_read2(ptr noundef nonnull %packed) unnamed_addr #1 personality ptr @rust_eh_personality {
start:
  %n.i.i = ptrtoint ptr %packed to i64
  %offset.i.i.i = mul i64 %n.i.i, 3
  %0 = getelementptr i8, ptr %packed, i64 %offset.i.i.i
  %1 = icmp ne ptr %0, null
  tail call void @llvm.assume(i1 %1)
  %2 = load i32, ptr %0, align 4 ; , !noundef !10
 ret i32 %2
}
```
```asm
shift_read2:                            # @shift_read2
        lea     rax, [rdi + 2*rdi]
        mov     eax, dword ptr [rdi + rax]
        ret
```

This looks suboptimal, since a single instruction can be generated instead:
```asm
shift_read2:                            # @shift_read2
        mov     eax, dword ptr [4*rdi]
 ret
```

Moreover if you change the function slightly (replace 3 by 7 which is equivalent to replacing `*(ptr << 2)` by `*(ptr << 3)`) the generated assembly is better:
```llvm
define noundef i32 @shift_read3(ptr noundef nonnull %packed) unnamed_addr #1 personality ptr @rust_eh_personality {
start:
  %n.i.i = ptrtoint ptr %packed to i64
  %offset.i.i.i = mul i64 %n.i.i, 7
  %0 = getelementptr i8, ptr %packed, i64 %offset.i.i.i
  %1 = icmp ne ptr %0, null
  tail call void @llvm.assume(i1 %1)
  %2 = load i32, ptr %0, align 4 ; , !noundef !10
 ret i32 %2
}
```
```asm
shift_read3:                            # @shift_read3
        mov     eax, dword ptr [8*rdi]
 ret
```


- [Compiler explorer](https://godbolt.org/z/1cPzPdbzq)
- [Original Rust code that reproduces the issue](https://godbolt.org/z/aa7eqY5Tr)
- [llvm-mca showing that there is no benefit in compiling this to two instructions](https://godbolt.org/z/Y913sMdWb)
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsVstu47gS_Rp6U4ghkfJDCy3ygFc3uI1BA41eBZRYkmpCkQpJJe18_YCUHTueRpCewWwGIxgiJNU5VazHMaX31BnEiq1u2OpuIafQW1d9k22r8X9yfCSzqK3aVzvrIPTkoZ1ME8gaYHz70lPTA3lA79EEklrvga0zxq8Z347BARO3TNwCZ7xM70vQ-nmADg06GdBD6BFaq7V9IdOB9B6HWu-ZuGbZHcuuIyj9Imx-pbAlg2DsZBS2QIIDKzLfUxseHErFD66PBsYaM2kNjK9G2TyiilFMxsgB1YNUygHjIocRnbdGagp7SJEXmZt8eMD-4fwT29zMYfggXXiLEyK9WdKSgIm7SBAsmTAzHR1DsEDr4gxh29ZjiLADcJh0NHljY_wWxBkgS1YdBtQ4oAmRn7bR6p2n-OJAc-7ijChPRNQMIxg8grOIi8k6GgZJGhqpNTxbUjEnsQ5L6f00IONbyhNXrO6JmidqbaWKxTmLLdFLTZ2BApi4gfjMeH6sFON5nh2IHIa5tHzFD62wubvoiYtH6Q8dct4L4ho-uBgXl81z2Md8aZRpdfJHinV14xQB4zexo6-dIra6e48Y7HNacUaoF-vUvP8TNrJd4hyGn-8u3b_GydPWPnrwU23HQIPUkd-TaRBkXDuNQMYHN83z2UgDNb6NmkofUao_z9Y_kLiP0lBcpu7jvd9bh_YZHVALeztB00vT4SwcRy3ymro-RPHhW4ejlg2CgHoPGzhp1NNEz1KjCXEOZ6uoOR_oVWT42WdxkrMYxinFR_2K_moMAd3fUTLxb1OyzX9K9leVTPzqQIrPD-T21wZyvl9F5K0dRtLoAH-M2jp0kYNv-xBGHzuK7xjfdVbVVoeldR3ju1fGd3nz5fWLql-f3tKd2P7vqCMjNfw2-QCNVXHKZYiz6qyamsNxgbyf8HOOpNzg0_fVV_feUSz91dBI8P187khuQo8usoOxUKPBlgKQgSbtcbYiHzs_vNhzpfWfi-V7mQt_r77VjJcLVQlVilIusMrX21xk5bpYL_qqbuq1VGUu8rwsynXbymzdFMW23TYFL7f1giqecZEVOc8LvuF8WbaizFFtigx52Ww2rMhwkKSXqb-t6xYpX9WaZ6VYaFmj9sfTnqtSJuqp83EgyAd_ggUKGqt78h4VpL8cepVJbVvrPlLNxeR0dZENCv1ULxs7ML5LAjgvV6Ozv2MTGN-lKD3juxToHwEAAP__yqUVJw">