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

    <tr>
        <th>Summary</th>
        <td>
            `switch (p ? a + C1 : C2)` should eliminate the add
        </td>
    </tr>

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

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

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

<pre>
    Here's some IR I got from rust on LLVM21 when matching on an enum:

```llvm
define noundef range(i8 0, 101) i8 @match5(i8 noundef range(i8 0, 5) %0) unnamed_addr #2 {
start:
  %1 = icmp ne i8 %0, 3
  tail call void @llvm.assume(i1 %1)
  %2 = add nsw i8 %0, -2
 %3 = zext i8 %2 to i64
  %4 = icmp samesign ugt i8 %0, 1
  %5 = add nuw nsw i64 %3, 257         // <--
  %_2 = select i1 %4, i64 %5, i64 258  // <--
  switch i64 %_2, label %bb1 [         // <--
    i64 257, label %bb5
 i64 258, label %bb3
    i64 259, label %bb2
  ]

bb1: ; preds = %start
  unreachable

bb3: ; preds = %start
  %6 = and i8 %0, 1
 br label %bb5

bb2:                                              ; preds = %start
  br label %bb5

bb5: ; preds = %start, %bb2, %bb3
  %_0.sroa.0.0 = phi i8 [ %6, %bb3 ], [ 100, %bb2 ], [ 13, %start ]
  ret i8 %_0.sroa.0.0
}
```

Where on trunk it's a bit improved by not using `i64` <https://llvm.godbolt.org/z/4TqMdTKjW>, but could still be much better.

Most notably, that `%5 = add` is only used in the `select`, which is only used in the `switch`.  As such, it can be removed entirely by adjusting the `switch` arms accordingly: <https://alive2.llvm.org/ce/z/mR6wBE>
```llvm
  %_2 = select i1 %4, i64 %3, i64 1
  switch i64 %_2, label %bb1 [
    i64 0, label %bb5
    i64 1, label %bb3
    i64 2, label %bb2
  ]
```

And that would unblock other optimizations as well, for example having done it `opt` can already remove the `zext` as well, letting the `switch` can stay over `i8` (instead of `i9` or `i64`): <https://llvm.godbolt.org/z/Ybf8zafGE>

---

This is basically a follow-up to #134024 and #134086 and https://github.com/rust-lang/rust/pull/144764, all of which are motivated by improving `match`ing in Rust.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJyUVk1v2zgT_jX0ZWCDor6cgw-2U79vse2lKLbYU0FJI4stRXpJyq7z6xdDSXWSJtmuYUASOfPM1zNDSu_V0SBuWL5j-f1CDqGzbuNrG0Jf94vKNtfN_9EhE6UHb3uE95_gPRxtgNbZHtzgA1gDHz78-VEkcOnQQC9D3SlzpHVpAM3Qs3TLePwXfPxrfe4Z3zbYKoNg7GAabMFJc0Qm1moNnIk9JDxh4g7UGljGI24-7r6mkJM4Ezmn52CM7LH5KpvGAROpAFbuGN_6IF0YXQISToCl96Dq_gQGo7EIsIc0SgSpNNRSazhb1ZAn5PxKej_00XYSQZi4mwFFBJRNA8ZfHgMuBYkwkadR4gF_hGlbQLCgimyGyG4-edkjlQmGY3gMlsyy-c3ccBlNFlm0QmIiL2H-MXFg4gAs3S-Xs_bX0VuPGusAYzAZKU4g-fwu8vULCP6iQt3Nwl8FSWtZoabPqkqA5bvX7cOEXD5Ty2l3MvpsK32iePdsV4xh5fcj36oqYekWWLqDk8PGx1CZyEcKkOhgHMq6k5XGWSX9FxUm8mJMuWl-KUjlnscRMQVh_qffGw68YiN_w2-xn_Mzv6U_CcBX3lm54isedU6dilHluxjpTSGmlb7yHSSc3zCfbKTTerQ7VQLA4czdR-bI8fL-8VgYQ_nSoUMaH8EN5juoEMePhEoFUP3J2TM2UF3B2ACDp1HDCk7NU1AE-y6Ek6f-jmyLzXq0TWV1WFl3ZOLwwMQh-_z3x-bzH9--sPQdeVwNAWo76AZ8UFpDhdAPdQcVhoBuNTr20fpAVmWlr6QUOhnI9uMmJCeUB2v0FQaPDSgDoUMSG3ssyu_h0inqm1ckY1exgq8Ath78UHexDQPU0pBvDvuYBTRBOdRXSodsvg0-UDqeo4B0vQdZ19Y1yhz1dWTKs0xJrc4oVjFhY6JqnLLVfyouu3eUql9n-G9NkXR-T357ajzqc_7SeJj2krfmw1vT4SnntqYZy3mJJBhMpW39HWzo0IE9BdWrBxmUNR6khwtqTditdYA_ZH_SCJ08U-4bS4dIpIU9UbFjyaR2KJvrVLe5QHQAxPLcEDWGl0tIKD7IK9gzukj4deS7WCvjA8oGbBuX72jZultP0Mn0Ur1f6Yy_qnb9INv_zeXm22Wc1oxvP3fKE2Ur6RWdiFeQ0Fqt7WU5nOgEYyJN0oyLLM7G6WtdxK-nxo8qdEO1qm3PxIGuEUstzXF6Z-JwGigfhyTLyiISiQ5g205tIx1Cb4M6yzCOgnEsTKMg3hQofHOknvo0-LBaNJu0uUvv5AI3SZlnheBFVi66TZ21rSh5iSXmXErJk1LwRIiiSGS6brOF2ggucr7may7SUpSrJEFelNU6lW0i2zRlGcdeKv2zcxbK-wE3SS4KUSwi_3y8Yglh8AJxlwlBNy63IaVlNRw9XSyUD_4GE1TQuPnJAqr1CVh6AAlM7GBPF5ct7AUVuODgu0hd1KpXRoaRZbJpFoPTmzeyH_t4fCxPzn6jGSUO0UtPJRjDOG_EPwEAAP__YnPihQ">