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

    <tr>
        <th>Summary</th>
        <td>
            Missed optimization: `umax(1 << x, 1 << y) => 1 << umax(x, y)`
        </td>
    </tr>

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

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

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

<pre>
    # C code

https://godbolt.org/z/YnEj5KGrW
```c
#include <stdint.h>

uint32_t src1(uint32_t x, uint32_t y) {
    uint32_t shl_x = 1 << x;
    uint32_t shl_y = 1 << y;
    return (shl_x > shl_y) ? shl_x : shl_y;
}

uint32_t tgt1(uint32_t x, uint32_t y) {
    uint32_t shl_x = 1 << x;
    uint32_t shl_y = 1 << y;
    return (x > y) ? shl_x : shl_y;
}

uint32_t src2(uint32_t x, uint32_t y) {
    uint32_t shl_x = 1 << x;
    uint32_t shl_y = 1 << y;
    return (shl_x < shl_y) ? shl_x : shl_y;
}

uint32_t tgt2(uint32_t x, uint32_t y) {
    uint32_t shl_x = 1 << x;
    uint32_t shl_y = 1 << y;
    return (x < y) ? shl_x : shl_y;
}
```

# Alive proof
https://alive2.llvm.org/ce/z/bv698b

```llvm
----------------------------------------
define i32 @src1(i32 noundef %#0, i32 noundef %#1) nofree willreturn memory(none) {
#2:
  %#3 = shl nuw i32 1, noundef %#0
  %#4 = shl nuw i32 1, noundef %#1
  %#5 = umax i32 %#3, %#4
  %#range_0_%#5 = !range i32 %#5, i32 1, i32 2147483649
  ret i32 %#range_0_%#5
}
=>
define i32 @tgt1(i32 noundef %#0, i32 noundef %#1) nofree willreturn memory(none) {
#2:
  %#3 = umax i32 noundef %#0, noundef %#1
  %#4 = shl nuw i32 1, %#3
  %#range_0_%#4 = !range i32 %#4, i32 1, i32 2147483649
  ret i32 %#range_0_%#4
}
Transformation seems to be correct!


----------------------------------------
define i32 @src2(i32 noundef %#0, i32 noundef %#1) nofree willreturn memory(none) {
#2:
  %#3 = shl nuw i32 1, noundef %#0
  %#4 = shl nuw i32 1, noundef %#1
  %#5 = umin i32 %#3, %#4
  %#range_0_%#5 = !range i32 %#5, i32 1, i32 2147483649
  ret i32 %#range_0_%#5
}
=>
define i32 @tgt2(i32 noundef %#0, i32 noundef %#1) nofree willreturn memory(none) {
#2:
  %#3 = umin i32 noundef %#0, noundef %#1
  %#4 = shl nuw i32 1, %#3
  %#range_0_%#4 = !range i32 %#4, i32 1, i32 2147483649
  ret i32 %#range_0_%#4
}
Transformation seems to be correct!

Summary:
  2 correct transformations
  0 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
```

# AArch64 assembly
```asm
src1:
        mov     w8, #1
 lsl     w9, w8, w0
        lsl     w8, w8, w1
        cmp     w9, w8
 csel    w0, w9, w8, hi
        ret

tgt1:
        cmp     w0, w1
 mov     w8, #1
        csel    w9, w0, w1, hi
        lsl     w0, w8, w9
        ret

src2:
        mov     w8, #1
        lsl     w9, w8, w0
        lsl     w8, w8, w1
        cmp     w9, w8
        csel    w0, w9, w8, lo
        ret

tgt2:
        cmp     w0, w1
        mov     w8, #1
        csel    w9, w0, w1, lo
        lsl     w0, w8, w9
 ret
```
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzkV02P6jYU_TVmYw1yrvO5yCIPhi6eumqlqqtRPgz41bGR7cDwfn1l54PADC3tqzpqHxqJiX3Pufcc59qmNIbvJGM5ij6haL0oO7tXOv_csvI3LheVas45AopXuFYNQ6RApNhbezCIFgg2CDY71VRK2KXSOwSbrwg2v8rnL9HnH_QvLjwm_V_tHoByWYuuYRjRlbENl3a5R_S55-24tBReLDa6DhCk0_MrghWens4IMoyST4gUGOPLuNmLl1eM6BoHjh7RFX5F9N2w83XY-RKmme20xAjSke65R_ikdDNlKYZhj0TJ-kaC3dmPl9CX_1dLN7qGDy99pFv9Xfc_XkJf_kOlj03Sy3D9Vgh-ZPigldq-6bjSzcFSiGM7dF3NhtarjnGWVgPNyOoCESmeHvwgUjRsyyXDnAJGIRna0T1J1cmGbTGCCAElzta3w4GTLNVWM4ZPXIjBkpa1Sp8RpFJJdlkCBBScNGdfj6feXLMXWHYnzx-4RLe5L4DwEUAwA0Qe0LXla6-xT-swA-EsVpdyx17IyxyJIPDDM3Q0ehGM_0AQJmFK4zDzbJrZWfgN6-VVoOt-P7xegmE7-ZeXYDLonZz3zb2zGqPJ95wN7zkbfouz4eTsz7qUZqt0W1quJDaMtQZbhSuGa6U1qy2CYOicb2sW-H82C5f_nWb5gCWYDPrOmuWnrm1LfR4tgTEA2ysO42cJ5vKP57clF6x5surpoNWR3YnyxyNgprXS5s4JWuh6H4e4NIa1lTjPo0rjDkR_rg1l959WHf33Ke0XoV8qYUQ_mrnRfu5EZrApIJ0FBLOAuj1cM5AC14Z51Mm_IXPuPZ9BNbO9Jn8EXFU7sZJLwvcVjIAxZTZI6GG3KSc5ZCYne68mv9k94OAt8T9q5K24N34KdcdP-HM_H5F139arzPdtHWoa385Fk9Mmo1m5YHmQhAEENAjJYp-ncZ1CTFJSRTTMEkiiMCvTOK3jKMySNF7wHAhEhJIIIMgIWSY0iJo0bRIoa1KFCQoJa0supsvjghvTsTyALAuThSgrJoz_LQjgr420UAfLW_51aD8ABKvLJJfG1qqtuNshh6mWG8OapznOzUXrhc4d7KnqdgaFRHBjzaUQy61g-Y8ejK_AtMAoJu4ygiCdXc1hNb-B-2u2Ow8ugwPER7oA522nRX7zA5bbfVcta9Ui2Hhd_ZfbgL74nW7jTTIINoNPxxx-DwAA__-Iqwxu">