diff options
author | Victor Costan <pwnall@chromium.org> | 2023-01-12 13:33:26 +0000 |
---|---|---|
committer | Victor Costan <pwnall@chromium.org> | 2023-01-12 13:33:26 +0000 |
commit | 30326e5b8cae9b5f2ea640d74beb2562ced44219 (patch) | |
tree | 05e8f8f85caeaf1111fde0f607844a8fee5e7321 | |
parent | 74960e8bd6e61e3a1f4e6a16097d4a7ce959663a (diff) | |
parent | 6c6e890ef961260b60f9f9a2051ac4618dbd06bd (diff) | |
download | snappy-git-30326e5b8cae9b5f2ea640d74beb2562ced44219.tar.gz |
Merge pull request #150 from davemgreen:betterunalignedloads
PiperOrigin-RevId: 501489679
-rw-r--r-- | snappy-stubs-internal.h | 57 |
1 files changed, 45 insertions, 12 deletions
diff --git a/snappy-stubs-internal.h b/snappy-stubs-internal.h index 7d43c92..1548ed7 100644 --- a/snappy-stubs-internal.h +++ b/snappy-stubs-internal.h @@ -171,27 +171,42 @@ class LittleEndian { public: // Functions to do unaligned loads and stores in little-endian order. static inline uint16_t Load16(const void *ptr) { - const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr); - // Compiles to a single mov/str on recent clang and gcc. +#if SNAPPY_IS_BIG_ENDIAN + const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr); return (static_cast<uint16_t>(buffer[0])) | (static_cast<uint16_t>(buffer[1]) << 8); +#else + // memcpy() turns into a single instruction early in the optimization + // pipeline (relatively to a series of byte accesses). So, using memcpy + // instead of byte accesses may lead to better decisions in more stages of + // the optimization pipeline. + uint16_t value; + std::memcpy(&value, ptr, 2); + return value; +#endif } static inline uint32_t Load32(const void *ptr) { - const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr); - // Compiles to a single mov/str on recent clang and gcc. +#if SNAPPY_IS_BIG_ENDIAN + const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr); return (static_cast<uint32_t>(buffer[0])) | (static_cast<uint32_t>(buffer[1]) << 8) | (static_cast<uint32_t>(buffer[2]) << 16) | (static_cast<uint32_t>(buffer[3]) << 24); +#else + // See Load16() for the rationale of using memcpy(). + uint32_t value; + std::memcpy(&value, ptr, 4); + return value; +#endif } static inline uint64_t Load64(const void *ptr) { - const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr); - // Compiles to a single mov/str on recent clang and gcc. +#if SNAPPY_IS_BIG_ENDIAN + const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr); return (static_cast<uint64_t>(buffer[0])) | (static_cast<uint64_t>(buffer[1]) << 8) | (static_cast<uint64_t>(buffer[2]) << 16) | @@ -200,30 +215,44 @@ class LittleEndian { (static_cast<uint64_t>(buffer[5]) << 40) | (static_cast<uint64_t>(buffer[6]) << 48) | (static_cast<uint64_t>(buffer[7]) << 56); +#else + // See Load16() for the rationale of using memcpy(). + uint64_t value; + std::memcpy(&value, ptr, 8); + return value; +#endif } static inline void Store16(void *dst, uint16_t value) { - uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst); - // Compiles to a single mov/str on recent clang and gcc. +#if SNAPPY_IS_BIG_ENDIAN + uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst); buffer[0] = static_cast<uint8_t>(value); buffer[1] = static_cast<uint8_t>(value >> 8); +#else + // See Load16() for the rationale of using memcpy(). + std::memcpy(dst, &value, 2); +#endif } static void Store32(void *dst, uint32_t value) { - uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst); - // Compiles to a single mov/str on recent clang and gcc. +#if SNAPPY_IS_BIG_ENDIAN + uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst); buffer[0] = static_cast<uint8_t>(value); buffer[1] = static_cast<uint8_t>(value >> 8); buffer[2] = static_cast<uint8_t>(value >> 16); buffer[3] = static_cast<uint8_t>(value >> 24); +#else + // See Load16() for the rationale of using memcpy(). + std::memcpy(dst, &value, 4); +#endif } static void Store64(void* dst, uint64_t value) { - uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst); - // Compiles to a single mov/str on recent clang and gcc. +#if SNAPPY_IS_BIG_ENDIAN + uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst); buffer[0] = static_cast<uint8_t>(value); buffer[1] = static_cast<uint8_t>(value >> 8); buffer[2] = static_cast<uint8_t>(value >> 16); @@ -232,6 +261,10 @@ class LittleEndian { buffer[5] = static_cast<uint8_t>(value >> 40); buffer[6] = static_cast<uint8_t>(value >> 48); buffer[7] = static_cast<uint8_t>(value >> 56); +#else + // See Load16() for the rationale of using memcpy(). + std::memcpy(dst, &value, 8); +#endif } static inline constexpr bool IsLittleEndian() { |