From fc7f58b3007fb356a52cb21f3aa5f5478cb46791 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 19 Jun 2017 11:03:33 +0200 Subject: [PATCH] Mark bswap and related methods constexpr Marks the bswap methods constexpr and removes the special versions explicitly using builtins as both clang and gcc automatically recognizes bswap code and replaces it with builtins. Change-Id: I07258431ac2588f6046682ffb9c832e650faf66a Reviewed-by: Thiago Macieira --- src/corelib/global/qendian.h | 114 ++++++++++------------------------- 1 file changed, 33 insertions(+), 81 deletions(-) diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h index 4e9cd2e6e3..cacb822947 100644 --- a/src/corelib/global/qendian.h +++ b/src/corelib/global/qendian.h @@ -52,22 +52,6 @@ QT_BEGIN_NAMESPACE /* * ENDIAN FUNCTIONS */ -inline void qbswap_helper(const void *src, void *dest, int size) -{ - for (int i = 0; i < size ; ++i) - static_cast(dest)[i] = static_cast(src)[size - 1 - i]; -} - -/* - * qbswap(const T src, const void *dest); - * Changes the byte order of \a src from big endian to little endian or vice versa - * and stores the result in \a dest. - * There is no alignment requirements for \a dest. -*/ -template inline void qbswap(const T src, void *dest) -{ - qbswap_helper(&src, dest, sizeof(T)); -} // Used to implement a type-safe and alignment-safe copy operation // If you want to avoid the memcpy, you must write specializations for these functions @@ -103,30 +87,11 @@ template Q_ALWAYS_INLINE T qFromUnaligned(const void *src) * This function can be used if you are not concerned about alignment issues, * and it is therefore a bit more convenient and in most cases more efficient. */ -template T qbswap(T source); +template Q_DECL_CONSTEXPR T qbswap(T source); -// GCC 4.3 implemented all the intrinsics, but the 16-bit one only got implemented in 4.8; -// Clang 2.6 implemented the 32- and 64-bit but waited until 3.2 to implement the 16-bit one -#if (defined(Q_CC_GNU) && Q_CC_GNU >= 403) || QT_HAS_BUILTIN(__builtin_bswap32) -template <> inline quint64 qbswap(quint64 source) -{ - return __builtin_bswap64(source); -} -template <> inline quint32 qbswap(quint32 source) -{ - return __builtin_bswap32(source); -} - -template <> inline void qbswap(quint64 source, void *dest) -{ - qToUnaligned(__builtin_bswap64(source), dest); -} -template <> inline void qbswap(quint32 source, void *dest) -{ - qToUnaligned(__builtin_bswap32(source), dest); -} -#else -template <> inline quint64 qbswap(quint64 source) +// These definitions are written so that they are recognized by most compilers +// as bswap and replaced with single instruction builtins if available. +template <> inline Q_DECL_CONSTEXPR quint64 qbswap(quint64 source) { return 0 | ((source & Q_UINT64_C(0x00000000000000ff)) << 56) @@ -139,7 +104,7 @@ template <> inline quint64 qbswap(quint64 source) | ((source & Q_UINT64_C(0xff00000000000000)) >> 56); } -template <> inline quint32 qbswap(quint32 source) +template <> inline Q_DECL_CONSTEXPR quint32 qbswap(quint32 source) { return 0 | ((source & 0x000000ff) << 24) @@ -147,65 +112,61 @@ template <> inline quint32 qbswap(quint32 source) | ((source & 0x00ff0000) >> 8) | ((source & 0xff000000) >> 24); } -#endif // GCC & Clang intrinsics -#if (defined(Q_CC_GNU) && Q_CC_GNU >= 408) || QT_HAS_BUILTIN(__builtin_bswap16) -template <> inline quint16 qbswap(quint16 source) -{ - return __builtin_bswap16(source); -} -template <> inline void qbswap(quint16 source, void *dest) -{ - qToUnaligned(__builtin_bswap16(source), dest); -} -#else -template <> inline quint16 qbswap(quint16 source) + +template <> inline Q_DECL_CONSTEXPR quint16 qbswap(quint16 source) { return quint16( 0 | ((source & 0x00ff) << 8) | ((source & 0xff00) >> 8) ); } -#endif // GCC & Clang intrinsics + +template <> inline Q_DECL_CONSTEXPR quint8 qbswap(quint8 source) +{ + return source; +} // signed specializations -template <> inline qint64 qbswap(qint64 source) +template <> inline Q_DECL_CONSTEXPR qint64 qbswap(qint64 source) { return qbswap(quint64(source)); } -template <> inline qint32 qbswap(qint32 source) +template <> inline Q_DECL_CONSTEXPR qint32 qbswap(qint32 source) { return qbswap(quint32(source)); } -template <> inline qint16 qbswap(qint16 source) +template <> inline Q_DECL_CONSTEXPR qint16 qbswap(qint16 source) { return qbswap(quint16(source)); } -template <> inline void qbswap(qint64 source, void *dest) +template <> inline Q_DECL_CONSTEXPR qint8 qbswap(qint8 source) { - qbswap(quint64(source), dest); + return source; } -template <> inline void qbswap(qint32 source, void *dest) +/* + * qbswap(const T src, const void *dest); + * Changes the byte order of \a src from big endian to little endian or vice versa + * and stores the result in \a dest. + * There is no alignment requirements for \a dest. +*/ +template inline void qbswap(const T src, void *dest) { - qbswap(quint32(source), dest); + qToUnaligned(qbswap(src), dest); } -template <> inline void qbswap(qint16 source, void *dest) -{ - qbswap(quint16(source), dest); -} #if Q_BYTE_ORDER == Q_BIG_ENDIAN -template inline T qToBigEndian(T source) +template inline Q_DECL_CONSTEXPR T qToBigEndian(T source) { return source; } -template inline T qFromBigEndian(T source) +template inline Q_DECL_CONSTEXPR T qFromBigEndian(T source) { return source; } -template inline T qToLittleEndian(T source) +template inline Q_DECL_CONSTEXPR T qToLittleEndian(T source) { return qbswap(source); } -template inline T qFromLittleEndian(T source) +template inline Q_DECL_CONSTEXPR T qFromLittleEndian(T source) { return qbswap(source); } template inline void qToBigEndian(T src, void *dest) { qToUnaligned(src, dest); } @@ -213,13 +174,13 @@ template inline void qToLittleEndian(T src, void *dest) { qbswap(src, dest); } #else // Q_LITTLE_ENDIAN -template inline T qToBigEndian(T source) +template inline Q_DECL_CONSTEXPR T qToBigEndian(T source) { return qbswap(source); } -template inline T qFromBigEndian(T source) +template inline Q_DECL_CONSTEXPR T qFromBigEndian(T source) { return qbswap(source); } -template inline T qToLittleEndian(T source) +template inline Q_DECL_CONSTEXPR T qToLittleEndian(T source) { return source; } -template inline T qFromLittleEndian(T source) +template inline Q_DECL_CONSTEXPR T qFromLittleEndian(T source) { return source; } template inline void qToBigEndian(T src, void *dest) { qbswap(src, dest); } @@ -228,15 +189,6 @@ template inline void qToLittleEndian(T src, void *dest) #endif // Q_BYTE_ORDER == Q_BIG_ENDIAN -template <> inline quint8 qbswap(quint8 source) -{ - return source; -} - -template <> inline qint8 qbswap(qint8 source) -{ - return source; -} /* T qFromLittleEndian(const void *src) * This function will read a little-endian encoded value from \a src