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

    <tr>
        <th>Summary</th>
        <td>
            Suboptimal codegen for `std::midpoint`
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            missed-optimization
      </td>
    </tr>

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

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

<pre>
    https://godbolt.org/z/dx5TY9WxY

The reference implementation of `std::midpoint` provided in [P0811R3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0811r3.html) produces better assembly than either libc++'s or libstdc++'s implementations, at least for u32, i32, u64 and i64. For u8, i8, u16 and i16, LLVM is unable to remove the unnecessary extensions and truncations

```c++
// taken from https://github.com/llvm/llvm-project/blob/main/libcxx/include/__numeric/midpoint.h#L36
template <typename T>
T libcpp(T a, T b) {
    using U = std::make_unsigned_t<T>;
    constexpr U bitshift = std::numeric_limits<U>::digits - 1;

    U diff = U(b) - U(a);
    U sign_bit = b < a;

    U half_diff = (diff / 2) + (sign_bit << bitshift) + (sign_bit & diff);

    return a + half_diff;
}

// taken from https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/numeric#L217
template <typename T>
T libstdcpp(T a, T b) {
    using U = std::make_unsigned_t<T>;

    int k = 1;
    U m = a;
    U M = b;
    if (a > b) {
        k = -1;
        m = b;
        M = a;
    }
    return a + k * T(U(M - m) / 2);
}

// taken from https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0811r3.html
template <typename Integer>
Integer P0811R3(Integer a, Integer b) noexcept {
 using U = std::make_unsigned_t<Integer>;
    U x = a - (U(a) - b) / 2;
 U y = a + (U(b) - a) / 2;
    return a > b ? x : y;
}
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0Vl2PozYU_TXOy1UiuEBCHvIwH4tUdUaq2qTVPkXG3ATvgI1sM5vsr69syNc0q26rFiHA1_a5h3sO2NxauVdEK5Y9sux5wntXa7P6uSX-JtWk1NVxVTvXWZY8MCwYFntdlbpxM232DItvDIvqkK0_L_84fGbRM4sehuu6JjC0I0NKEMi2a6gl5biTWoHeAZtH1lUeNXloZdVpqRybR9AZ_S4rqkAqYNnjL1Eex78mLHtmmN8S-fr160x3pKbWVSObL07EDAsrEP2APfpWpYVlWHS8I-MfMIqXvu2RTTKrXdswXPrEVS_IQknOkQFuLbVlcwRXcwUkXU0GGlkKho_hXFjQIWJddR28fVfL8Am4g4a4dbDTBvoEfUwOt36eAlcVyHk6g8J356E3XPt4PnTGc998efn9FaSFXvGyIXAaDLX6ncDVBL1SJMhabo5AB0fK-uxhujO9EiObK4nYPBrOE_shGooLjr-Rgp3RLXzQX7q6L2dCtwyLpnk_3aad0V9IOIZF2eiSYdFyqXynLMXhwLCQSjR9RQyL7Vb1LRkp_KhR_FnNMHlJ5gMLR23XcEfAkid37EjxlmDNkk-ju4ISXccwXwP3tVlD6VVki_E1AAB6K9UeNsCSZ7iYjb_RtlfB9tXWseQpwCZX84RW1tGhM7CBUjpby527BRnpbxvZSmdZ8rQJGL6rknvpLEwhPmNekDdQyd0uYG0Y5oHyNDxyhssbEhvwFLelHFKXvhLA72LWvNltz8AM8-EZC8BQE3z0wSu4J491erO7Q3AemF6TumQ05HqjgIdp5-SXgYvnG5v9E0PthZi20hhthsa1m6wjM_hp-OIy79oMH6fvyY27vEpYnB2WvGC8-HFXeez_w1iX2VI5eAtz4w-KtyHKP0RfBwPcRKXXN-fAkk93-PljyDC9TeGP9g6cP17vJD9L-RfZ34DhA6wZ5t69rzCFdjDSYLp_a4b_8qf-fcl_Uo72ZM7Cj204rTaYnyLBAqdGKLTSdBDUuauK_6AdrrLeCnwYKg9TGMvJh_9CeanoecIGjuPo8Zu9-o_wO-NvdPNmAZYUIeMDHO-odFoTJtUqqZbJkk9oFS8Qo2UUpTipV0kWRTnmi4SyNBKCqmzBF0tKs0xE-ZJoIlcYYRotcBGnGKU4K9M4KZdpVs1LIVJcsjSilstm5pcNL_JEWtvTKo6ifJFNGl5SY8OGBLGV1lI11Z2TrfwW1jCG6HcqZhVWnbLfW5ZGjbTOXgCddA2tfuvLMJE3IHRFe285bb639Zj0pvm41_n7tS5Q9w4c2b-v8M8AAAD__0yErRI">