From b3819d9cc200100bcf3fc30bcd3353c50cc73c4c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 16 Nov 2023 10:38:35 +0100 Subject: [PATCH] Qt::*_ordering: use std::bit_cast when converting to std::_ordering GCC, in particular, doesn't understand that the types are fundamentally the same unless you compile with -O3, so help the compiler by using bit_cast when it is available. GCC now produces the same code at -O2 as previously only at -O3. Still no tail-calls, though. Task-number: QTBUG-118913 Change-Id: Ib1241a98f1de49c59a2e16b7d1f5cf813db4edf7 Reviewed-by: Ivan Solovev --- src/corelib/global/qcompare.cpp | 3 --- src/corelib/global/qcompare.h | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/corelib/global/qcompare.cpp b/src/corelib/global/qcompare.cpp index e02c78b6ae..9275ff7a8e 100644 --- a/src/corelib/global/qcompare.cpp +++ b/src/corelib/global/qcompare.cpp @@ -11,9 +11,6 @@ QT_BEGIN_NAMESPACE #ifdef __cpp_lib_three_way_comparison -static_assert(sizeof(std::partial_ordering) == sizeof(Qt::partial_ordering)); -static_assert(sizeof(std::weak_ordering) == sizeof(Qt::weak_ordering)); -static_assert(sizeof(std::strong_ordering) == sizeof(Qt::strong_ordering)); #ifdef __cpp_lib_bit_cast #define CHECK(type, flag) \ static_assert(std::bit_cast(std:: type ## _ordering:: flag) \ diff --git a/src/corelib/global/qcompare.h b/src/corelib/global/qcompare.h index e01751ce11..5be0a4877d 100644 --- a/src/corelib/global/qcompare.h +++ b/src/corelib/global/qcompare.h @@ -12,6 +12,9 @@ #include #include +#ifdef __cpp_lib_bit_cast +#include +#endif #ifdef __cpp_lib_three_way_comparison #include #endif @@ -266,6 +269,10 @@ public: constexpr Q_IMPLICIT operator std::partial_ordering() const noexcept { + static_assert(sizeof(*this) == sizeof(std::partial_ordering)); +#ifdef __cpp_lib_bit_cast + return std::bit_cast(*this); +#else switch (m_order) { case qToUnderlying(QtPrivate::Ordering::Less): return std::partial_ordering::less; case qToUnderlying(QtPrivate::Ordering::Greater): return std::partial_ordering::greater; @@ -273,6 +280,7 @@ public: case qToUnderlying(QtPrivate::Uncomparable::Unordered): return std::partial_ordering::unordered; } Q_UNREACHABLE_RETURN(std::partial_ordering::unordered); +#endif // __cpp_lib_bit_cast } friend constexpr bool operator==(partial_ordering lhs, std::partial_ordering rhs) noexcept @@ -414,12 +422,17 @@ public: constexpr Q_IMPLICIT operator std::weak_ordering() const noexcept { + static_assert(sizeof(*this) == sizeof(std::weak_ordering)); +#ifdef __cpp_lib_bit_cast + return std::bit_cast(*this); +#else switch (m_order) { case qToUnderlying(QtPrivate::Ordering::Less): return std::weak_ordering::less; case qToUnderlying(QtPrivate::Ordering::Greater): return std::weak_ordering::greater; case qToUnderlying(QtPrivate::Ordering::Equivalent): return std::weak_ordering::equivalent; } Q_UNREACHABLE_RETURN(std::weak_ordering::equivalent); +#endif // __cpp_lib_bit_cast } friend constexpr bool operator==(weak_ordering lhs, std::weak_ordering rhs) noexcept @@ -593,12 +606,17 @@ public: constexpr Q_IMPLICIT operator std::strong_ordering() const noexcept { + static_assert(sizeof(*this) == sizeof(std::strong_ordering)); +#ifdef __cpp_lib_bit_cast + return std::bit_cast(*this); +#else switch (m_order) { case qToUnderlying(QtPrivate::Ordering::Less): return std::strong_ordering::less; case qToUnderlying(QtPrivate::Ordering::Greater): return std::strong_ordering::greater; case qToUnderlying(QtPrivate::Ordering::Equal): return std::strong_ordering::equal; } Q_UNREACHABLE_RETURN(std::strong_ordering::equal); +#endif // __cpp_lib_bit_cast } friend constexpr bool operator==(strong_ordering lhs, std::strong_ordering rhs) noexcept