Issue |
100875
|
Summary |
Suboptimal codegen for `std::midpoint`
|
Labels |
missed-optimization
|
Assignees |
|
Reporter |
Kmeakin
|
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;
}
```
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs