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

    <tr>
        <th>Summary</th>
        <td>
            [X86] Prefer immediate operand to stack folded operand
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            backend:X86
      </td>
    </tr>

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

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

<pre>
    Raised here: https://reviews.llvm.org/D132520#inline-1278500
```
movl $65536, %eax # imm = 0x10000
orl 4(%esp), %eax
```
This would be even better as:
```
mov  4(%esp), %eax
or      $65536, %eax
```
Only 2 back-end uops (instead of 1 mov-immediate + 1 micro-fused load+or). Pretty much equivalent for the front-end and ROB, but takes one fewer entry in the RS until these execute. The mov-immediate is independent so it can exec early, but still takes a cycle on an execution unit. And then we're left with load and OR uops, just like with my asm.
The one advantage is that the mov-immediate could possibly retire from the ROB while still stalled waiting for the load, but that seems pretty unlikely. (Cache miss on stack memory in a function with stack args, or at the end of a long dependency chain involving storing the arg).

That movzx + or-immediate asm is what we get from C++ source that manually sets a bit, __builtin_ctz(x|0x10000)
https://godbolt.org/z/d63WM5s4c (clang nightly after this revision landed).

Or from std::countr_zero(*p); or on a reference, so it seems this mov-immediate thing is only with by-value stack args, and isn't a concern for the general case of other addressing modes. So always a simple addressing mode, ESP or EBP, where we won't have un-lamination on Sandy/Ivy Bridge. Also of course avoids reading outside the pointed-to 16-bit object, which could cross into an unmapped page. (Or suffer a slowdown from a cache-line split).

Anyway, what we do when dereferencing a pointer like for std::countr_zero(*p);is slightly more efficient than what we do for a by-value stack arg.

But it seems this is not specific to CTTZ lowering; we get mov-immediate / or mem,reg from return x|0x1000;

(vs. 64-bit mode correctly choosing mov %edi, %eax / or $65536, %eax, which puts the mov on the critical path on CPUs without mov-elimination, like Ice Lake with updated microcode :(. But it saves code size. In the 32-bit case there's no latency advantage: a load has to happen as part of the critical path either way, and OR register has the same latency as OR-immediate.)
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyFVl1v4zYQ_DXyC2FDlvz54Id8XIBDWyRIrmjRl4ASVzYvFKmSlB3n13eWspNLLm0PusiiSO7szOxSlVPHzb3UgZTYkaesvBC7GLuAH1lxg8vTXtMhTIzZtxPntxi6npbFvMizotTWaEvjabFczfM8y6-z_CJb5KcrPbZub0RWzBbzebnIiiv8npN8xq0Uum1FVl6L_Hma5-f1zhsxy4oVzwtdVqzfFn0a4NtOB3FwvVGiIkF7srjHSF7IlMW_gBL_HcR5kf79jPzTDW-tOYpCVLJ-GpNVonddwPyVtiGSVMI1YioQdYyUSWkZCW8veUzX3o2bngUwTiqMOg88E3HnkcVRtH29E_R3r_fSkI2iAbK4I9F4Z2OKJfH__vaSEVZ9FFE-URDOYgodwAIW-aPQNq26fxC9jdrwQwBbz1T3kSbiG969hwdStVXUIQKHDU7oKGpp0xpB0pvjOWLAhuYUV4r6WBtCfHGa20eNh97qOBEXgIrIVhwoK5aehKEmioOOu5R8SuX2PrHHm3_vQxRGP9EwpT1C0nZylp1SklLtpY1ymxDHnYwpz_e51MkdnQtBV9AJxGqfGGwHUm4vxWGngXrIJERpDPQ4SB213b5SPuhzYpkjBaI2iG4QqreM1BwnrPuVrBmFDqwEb1g_iZZaNyghRdPbOvGSEhveS79NWSPaKQtWF86RiAwYZzHqo6h3Ettou3dmzwhDdJ7vvEhyja5PLJ25woag5OU5uc75H7gBo8zcgaccSGwpDsRcYSZPDq73NQ35ttL2oOaIxCNLXenIgB8fq14bUPVYxxck_5wtr84ljcpKEN43la1TlTPx1E-w5kYtyj9-m4dZzezVRiIZq7e7iGCy4WKOXObcjALThgmK1Mc8b_2APUTFocoLCA_3P76Qd6nYL1Kpl0xBcig2bND1bE2cx-DxQdQU7r2LMARUmhUFqiRcdRyjLHv6oCDbWAcLi0cuCIf9vX210ZYseWlQTKhAyOswCMmV8gSDIkTrFIWJeHBCmoM8MtNBt52hj5M41peHO87my-UdPx24ibOOBzeE38k9wZpjI1ttZbIcrgcgRPnefN0fxaXXaosWcGGQP-CAMw9gcu-0Ysal4nCuj0ErSgl0TttIahydmC7GMIFw1Xeq4wBAo18NBYfOFriLYJ7kDtDKrkNZdZLDQQ_IFfqm4eRFMO6g3MEOAoI0LqAxny4idIZ99l7qC3sENUPEwbnKcfYWZXIWlXHLE1o_9BHW4H_dAYmDOZkPJYs6bBpda26DKAP7Y0TeT35ig3dYL9Ev3hsLl3UY6ajW2FqAoatv3_5CnaNjAzZb9FSMHw-NG1YbrQSpe9oOdKEB9TDYW91h_Y8AkN0ehlrMkljsHCjkPSQz3EucOzlqn444pd8d0yngJ8fgq9gdrHFuumwu_ll7tM4aJu8kygSDV3e_h1QzMFLKiYw-O5K3Sup8RaP5VZ7bfd8ppKyGI7Jm0Kl_rCbiTCi8HUR6E_QLPPV1CF4WKc9UXzF91RRLJhxdI6b2-Xpm8OeOHI6enQwsw449is6Ati595Hr4OR3SqWJP_judWRBDB_ZZ2ghrgmzpLWLAnDcdJzDaiDbTxaKcrZezVT5Sm1Kty7UcRR0NbbL55Z-rRTa_5s8ArpA3C7gO3YPPUXeyW-MMeuF5fNR7s_nQbYG3rya1g2lu-DvudBt33g11e4ODqif0rpv5cpWvRrvNqpqWaoaPusViVdT4U1NTqyYv17VaNdVyZGRFJjDQrCj4uwdnEyIy6qIA8JHeFHlR5OvpapqXqzyfVKuclrM1Les10XzRZLOcWqnN66flyG8SrKpHG53lBny-fXeOJPre1lLihveXPczkN_e_POjW2VHKYJPg_wNsiZH7">