From 327b5011696c90b96eb30964aea0623d71878d24 Mon Sep 17 00:00:00 2001 From: William Jagels Date: Sat, 24 Mar 2018 20:37:01 -0400 Subject: [PATCH] Take advantage of unaligned load/store for big endian --- include/boost/endian/buffers.hpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/include/boost/endian/buffers.hpp b/include/boost/endian/buffers.hpp index 258bbec..cbec541 100644 --- a/include/boost/endian/buffers.hpp +++ b/include/boost/endian/buffers.hpp @@ -281,6 +281,21 @@ namespace endian inline T load_big_endian(const void* bytes) BOOST_NOEXCEPT { +# if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) + // On x86 (which is little endian), unaligned loads are permitted + if (sizeof(T) == n_bytes) // GCC 4.9, VC++ 14.0, and probably others, elide this + // test and generate code only for the applicable return + // case since sizeof(T) and n_bytes are known at compile + // time. + { + // Avoids -fsanitize=undefined violations due to unaligned loads + // All major x86 compilers optimize a short-sized memcpy into a single instruction + + T t = 0; + std::memcpy( &t, bytes, sizeof(T) ); + return big_to_native(t); + } +# endif return unrolled_byte_loops::load_big (static_cast(bytes) + n_bytes); } @@ -312,6 +327,21 @@ namespace endian inline void store_big_endian(void* bytes, T value) BOOST_NOEXCEPT { +# if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) + // On x86 (which is little endian), unaligned stores are permitted + if (sizeof(T) == n_bytes) // GCC 4.9, VC++ 14.0, and probably others, elide this + // test and generate code only for the applicable return + // case since sizeof(T) and n_bytes are known at compile + // time. + { + // Avoids -fsanitize=undefined violations due to unaligned stores + // All major x86 compilers optimize a short-sized memcpy into a single instruction + + boost::endian::native_to_big_inplace(value); + std::memcpy( bytes, &value, sizeof(T) ); + return; + } +# endif unrolled_byte_loops::store_big (static_cast(bytes) + n_bytes, value); }