Export of internal Abseil changes

--
291f7ef542f73e4801ab5108014bc02344ef31df by Derek Mauro <dmauro@google.com>:

Internal change

PiperOrigin-RevId: 437835981
Change-Id: I42fd92e74903894533ac9984d7f622e3ba20f468

--
2e8caf1a57c50b518e05b4bca48e4fe1bb19af82 by Andy Getzendanner <durandal@google.com>:

Internal change

PiperOrigin-RevId: 437832673
Change-Id: I61b35089418d01a54cecf161b254b68252bebff3

--
b927482ccc399f7e337b60582988b914d9946e4e by Derek Mauro <dmauro@google.com>:

Simplify endian intrinsics for modern compilers

All modern compilers have either __builtin_bswapN (gcc, clang) or
_byteswap_TYPE (MSVC).  The other intrinsic definitions are no longer
necessary.

PiperOrigin-RevId: 437772295
Change-Id: Ifb3d88ba24b9097f87ceb202272b36d2f5e5117f

--
b6782a2247a16d5c14706a74ec577c19963d9f97 by Derek Mauro <dmauro@google.com>:

Internal change

PiperOrigin-RevId: 437373174
Change-Id: I0f77e1780dee90d7a3c32a08d96c4aeb624a57b4

--
a53e0c724e37b0b01515a99bd25394b8e21ffdfc by Derek Mauro <dmauro@google.com>:

Unify detection of SSE2 and SSSE3 instruction sets and
include the proper headers

Fix the intrinsic implementation of FastHexToBufferZeroPad16 in
numbers.h which only relies on SSSE3, not SSE 4.2.
https://godbolt.org/z/Pf5bn1Yv9

Closes #639

PiperOrigin-RevId: 437286940
Change-Id: Ic97948399b61b91e9c0bccd09313b795b904d714

--
f173f597cb2a75ef2a989f45a496334b85e6f40d by Abseil Team <absl-team@google.com>:

Change assertion function to enable clearer error messages.

PiperOrigin-RevId: 437227057
Change-Id: If420d2f63b51feef6648762f344d5be012cd9c85
GitOrigin-RevId: 291f7ef542f73e4801ab5108014bc02344ef31df
pull/1157/head
Abseil Team 3 years ago committed by rogeeff
parent 0c6302fe42
commit 3204cc0625
  1. 2
      CMake/AbseilDll.cmake
  2. 32
      absl/base/config.h
  3. 79
      absl/base/internal/endian.h
  4. 13
      absl/container/BUILD.bazel
  5. 14
      absl/container/CMakeLists.txt
  6. 4
      absl/container/internal/hashtablez_sampler.cc
  7. 4
      absl/container/internal/hashtablez_sampler.h
  8. 4
      absl/container/internal/hashtablez_sampler_test.cc
  9. 50
      absl/container/internal/have_sse.h
  10. 51
      absl/container/internal/raw_hash_set.h
  11. 2
      absl/container/internal/raw_hash_set_test.cc
  12. 17
      absl/strings/numbers.h

@ -78,7 +78,6 @@ set(ABSL_INTERNAL_DLL_FILES
"container/internal/hashtablez_sampler.cc"
"container/internal/hashtablez_sampler.h"
"container/internal/hashtablez_sampler_force_weak_definition.cc"
"container/internal/have_sse.h"
"container/internal/inlined_vector.h"
"container/internal/layout.h"
"container/internal/node_slot_policy.h"
@ -456,7 +455,6 @@ set(ABSL_INTERNAL_DLL_TARGETS
"hashtablez_sampler"
"hashtable_debug"
"hashtable_debug_hooks"
"have_sse"
"node_slot_policy"
"raw_hash_map"
"container_common"

@ -269,6 +269,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1
#elif ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(5, 0)
#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1
#elif defined(_MSC_VER) && _MSC_VER >= 1926
#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1
#endif
#endif
@ -818,4 +820,34 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_INTERNAL_HAS_RTTI 1
#endif // !defined(__GNUC__) || defined(__GXX_RTTI)
// ABSL_INTERNAL_HAVE_SSE2 is used for compile-time detection of SSE2 support.
// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of
// which architectures support the various x86 instruction sets.
#ifdef ABSL_INTERNAL_HAVE_SSE2
#error ABSL_INTERNAL_HAVE_SSE2 cannot be directly set
#elif defined(__SSE2__)
#define ABSL_INTERNAL_HAVE_SSE2 1
#elif defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
// MSVC only defines _M_IX86_FP for x86 32-bit code, and _M_IX86_FP >= 2
// indicates that at least SSE2 was targeted with the /arch:SSE2 option.
// All x86-64 processors support SSE2, so support can be assumed.
// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
#define ABSL_INTERNAL_HAVE_SSE2 1
#endif
// ABSL_INTERNAL_HAVE_SSSE3 is used for compile-time detection of SSSE3 support.
// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of
// which architectures support the various x86 instruction sets.
//
// MSVC does not have a mode that targets SSSE3 at compile-time. To use SSSE3
// with MSVC requires either assuming that the code will only every run on CPUs
// that support SSSE3, otherwise __cpuid() can be used to detect support at
// runtime and fallback to a non-SSSE3 implementation when SSSE3 is unsupported
// by the CPU.
#ifdef ABSL_INTERNAL_HAVE_SSSE3
#error ABSL_INTERNAL_HAVE_SSSE3 cannot be directly set
#elif defined(__SSSE3__)
#define ABSL_INTERNAL_HAVE_SSSE3 1
#endif
#endif // ABSL_BASE_CONFIG_H_

@ -16,16 +16,9 @@
#ifndef ABSL_BASE_INTERNAL_ENDIAN_H_
#define ABSL_BASE_INTERNAL_ENDIAN_H_
// The following guarantees declaration of the byte swap functions
#ifdef _MSC_VER
#include <stdlib.h> // NOLINT(build/include)
#elif defined(__FreeBSD__)
#include <sys/endian.h>
#elif defined(__GLIBC__)
#include <byteswap.h> // IWYU pragma: export
#endif
#include <cstdint>
#include <cstdlib>
#include "absl/base/casts.h"
#include "absl/base/config.h"
#include "absl/base/internal/unaligned_access.h"
@ -34,47 +27,11 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
// Use compiler byte-swapping intrinsics if they are available. 32-bit
// and 64-bit versions are available in Clang and GCC as of GCC 4.3.0.
// The 16-bit version is available in Clang and GCC only as of GCC 4.8.0.
// For simplicity, we enable them all only for GCC 4.8.0 or later.
#if defined(__clang__) || \
(defined(__GNUC__) && \
((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ >= 5))
inline uint64_t gbswap_64(uint64_t host_int) {
#if ABSL_HAVE_BUILTIN(__builtin_bswap64) || defined(__GNUC__)
return __builtin_bswap64(host_int);
}
inline uint32_t gbswap_32(uint32_t host_int) {
return __builtin_bswap32(host_int);
}
inline uint16_t gbswap_16(uint16_t host_int) {
return __builtin_bswap16(host_int);
}
#elif defined(_MSC_VER)
inline uint64_t gbswap_64(uint64_t host_int) {
return _byteswap_uint64(host_int);
}
inline uint32_t gbswap_32(uint32_t host_int) {
return _byteswap_ulong(host_int);
}
inline uint16_t gbswap_16(uint16_t host_int) {
return _byteswap_ushort(host_int);
}
#else
inline uint64_t gbswap_64(uint64_t host_int) {
#if defined(__GNUC__) && defined(__x86_64__) && !defined(__APPLE__)
// Adapted from /usr/include/byteswap.h. Not available on Mac.
if (__builtin_constant_p(host_int)) {
return __bswap_constant_64(host_int);
} else {
uint64_t result;
__asm__("bswap %0" : "=r"(result) : "0"(host_int));
return result;
}
#elif defined(__GLIBC__)
return bswap_64(host_int);
#else
return (((host_int & uint64_t{0xFF}) << 56) |
((host_int & uint64_t{0xFF00}) << 40) |
@ -84,12 +41,14 @@ inline uint64_t gbswap_64(uint64_t host_int) {
((host_int & uint64_t{0xFF0000000000}) >> 24) |
((host_int & uint64_t{0xFF000000000000}) >> 40) |
((host_int & uint64_t{0xFF00000000000000}) >> 56));
#endif // bswap_64
#endif
}
inline uint32_t gbswap_32(uint32_t host_int) {
#if defined(__GLIBC__)
return bswap_32(host_int);
#if ABSL_HAVE_BUILTIN(__builtin_bswap32) || defined(__GNUC__)
return __builtin_bswap32(host_int);
#elif defined(_MSC_VER)
return _byteswap_ulong(host_int);
#else
return (((host_int & uint32_t{0xFF}) << 24) |
((host_int & uint32_t{0xFF00}) << 8) |
@ -99,33 +58,29 @@ inline uint32_t gbswap_32(uint32_t host_int) {
}
inline uint16_t gbswap_16(uint16_t host_int) {
#if defined(__GLIBC__)
return bswap_16(host_int);
#if ABSL_HAVE_BUILTIN(__builtin_bswap16) || defined(__GNUC__)
return __builtin_bswap16(host_int);
#elif defined(_MSC_VER)
return _byteswap_ushort(host_int);
#else
return (((host_int & uint16_t{0xFF}) << 8) |
((host_int & uint16_t{0xFF00}) >> 8));
#endif
}
#endif // intrinsics available
#ifdef ABSL_IS_LITTLE_ENDIAN
// Definitions for ntohl etc. that don't require us to include
// netinet/in.h. We wrap gbswap_32 and gbswap_16 in functions rather
// than just #defining them because in debug mode, gcc doesn't
// correctly handle the (rather involved) definitions of bswap_32.
// gcc guarantees that inline functions are as fast as macros, so
// this isn't a performance hit.
// Portable definitions for htonl (host-to-network) and friends on little-endian
// architectures.
inline uint16_t ghtons(uint16_t x) { return gbswap_16(x); }
inline uint32_t ghtonl(uint32_t x) { return gbswap_32(x); }
inline uint64_t ghtonll(uint64_t x) { return gbswap_64(x); }
#elif defined ABSL_IS_BIG_ENDIAN
// These definitions are simpler on big-endian machines
// These are functions instead of macros to avoid self-assignment warnings
// on calls such as "i = ghtnol(i);". This also provides type checking.
// Portable definitions for htonl (host-to-network) etc on big-endian
// architectures. These definitions are simpler since the host byte order is the
// same as network byte order.
inline uint16_t ghtons(uint16_t x) { return x; }
inline uint32_t ghtonl(uint32_t x) { return x; }
inline uint64_t ghtonll(uint64_t x) { return x; }

@ -509,8 +509,8 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":have_sse",
"//absl/base",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/debugging:stacktrace",
"//absl/memory",
@ -527,7 +527,7 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hashtablez_sampler",
":have_sse",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/profiling:sample_recorder",
"//absl/synchronization",
@ -569,14 +569,6 @@ cc_library(
],
)
cc_library(
name = "have_sse",
hdrs = ["internal/have_sse.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = ["//visibility:private"],
)
cc_library(
name = "common",
hdrs = ["internal/common.h"],
@ -601,7 +593,6 @@ cc_library(
":hash_policy_traits",
":hashtable_debug_hooks",
":hashtablez_sampler",
":have_sse",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:endian",

@ -550,8 +550,8 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
DEPS
absl::base
absl::config
absl::exponential_biased
absl::have_sse
absl::sample_recorder
absl::synchronization
)
@ -564,8 +564,8 @@ absl_cc_test(
COPTS
${ABSL_TEST_COPTS}
DEPS
absl::config
absl::hashtablez_sampler
absl::have_sse
GTest::gmock_main
)
@ -592,15 +592,6 @@ absl_cc_library(
PUBLIC
)
absl_cc_library(
NAME
have_sse
HDRS
"internal/have_sse.h"
COPTS
${ABSL_DEFAULT_COPTS}
)
absl_cc_library(
NAME
node_slot_policy
@ -670,7 +661,6 @@ absl_cc_library(
absl::endian
absl::hash_policy_traits
absl::hashtable_debug_hooks
absl::have_sse
absl::memory
absl::meta
absl::optional

@ -21,7 +21,7 @@
#include <limits>
#include "absl/base/attributes.h"
#include "absl/container/internal/have_sse.h"
#include "absl/base/config.h"
#include "absl/debugging/stacktrace.h"
#include "absl/memory/memory.h"
#include "absl/profiling/internal/exponential_biased.h"
@ -160,7 +160,7 @@ void RecordInsertSlow(HashtablezInfo* info, size_t hash,
// SwissTables probe in groups of 16, so scale this to count items probes and
// not offset from desired.
size_t probe_length = distance_from_desired;
#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
#ifdef ABSL_INTERNAL_HAVE_SSE2
probe_length /= 16;
#else
probe_length /= 8;

@ -44,9 +44,9 @@
#include <memory>
#include <vector>
#include "absl/base/config.h"
#include "absl/base/internal/per_thread_tls.h"
#include "absl/base/optimization.h"
#include "absl/container/internal/have_sse.h"
#include "absl/profiling/internal/sample_recorder.h"
#include "absl/synchronization/mutex.h"
#include "absl/utility/utility.h"
@ -96,7 +96,7 @@ struct HashtablezInfo : public profiling_internal::Sample<HashtablezInfo> {
};
inline void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length) {
#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
#ifdef ABSL_INTERNAL_HAVE_SSE2
total_probe_length /= 16;
#else
total_probe_length /= 8;

@ -21,7 +21,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
#include "absl/container/internal/have_sse.h"
#include "absl/base/config.h"
#include "absl/profiling/internal/sample_recorder.h"
#include "absl/synchronization/blocking_counter.h"
#include "absl/synchronization/internal/thread_pool.h"
@ -30,7 +30,7 @@
#include "absl/time/clock.h"
#include "absl/time/time.h"
#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
#ifdef ABSL_INTERNAL_HAVE_SSE2
constexpr int kProbeLength = 16;
#else
constexpr int kProbeLength = 8;

@ -1,50 +0,0 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Shared config probing for SSE instructions used in Swiss tables.
#ifndef ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
#define ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
#ifndef ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
#if defined(__SSE2__) || \
(defined(_MSC_VER) && \
(defined(_M_X64) || (defined(_M_IX86) && _M_IX86_FP >= 2)))
#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 1
#else
#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 0
#endif
#endif
#ifndef ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
#ifdef __SSSE3__
#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 1
#else
#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 0
#endif
#endif
#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 && \
!ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
#error "Bad configuration!"
#endif
#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
#include <emmintrin.h>
#endif
#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
#include <tmmintrin.h>
#endif
#endif // ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_

@ -176,6 +176,18 @@
#ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
#define ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
#ifdef __SSE2__
#include <emmintrin.h>
#endif
#ifdef __SSSE3__
#include <tmmintrin.h>
#endif
#ifdef _MSC_VER
#include <intrin.h>
#endif
#include <algorithm>
#include <cmath>
#include <cstdint>
@ -187,6 +199,7 @@
#include <type_traits>
#include <utility>
#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
#include "absl/base/optimization.h"
#include "absl/base/port.h"
@ -196,7 +209,6 @@
#include "absl/container/internal/hash_policy_traits.h"
#include "absl/container/internal/hashtable_debug_hooks.h"
#include "absl/container/internal/hashtablez_sampler.h"
#include "absl/container/internal/have_sse.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
#include "absl/numeric/bits.h"
@ -461,7 +473,7 @@ inline bool IsFull(ctrl_t c) { return c >= static_cast<ctrl_t>(0); }
inline bool IsDeleted(ctrl_t c) { return c == ctrl_t::kDeleted; }
inline bool IsEmptyOrDeleted(ctrl_t c) { return c < ctrl_t::kSentinel; }
#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
#ifdef ABSL_INTERNAL_HAVE_SSE2
// Quick reference guide for intrinsics used below:
//
// * __m128i: An XMM (128-bit) word.
@ -522,7 +534,7 @@ struct GroupSse2Impl {
// Returns a bitmask representing the positions of empty slots.
BitMask<uint32_t, kWidth> MatchEmpty() const {
#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
#ifdef ABSL_INTERNAL_HAVE_SSSE3
// This only works because ctrl_t::kEmpty is -128.
return BitMask<uint32_t, kWidth>(
static_cast<uint32_t>(_mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl))));
@ -548,7 +560,7 @@ struct GroupSse2Impl {
void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
auto msbs = _mm_set1_epi8(static_cast<char>(-128));
auto x126 = _mm_set1_epi8(126);
#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
#ifdef ABSL_INTERNAL_HAVE_SSSE3
auto res = _mm_or_si128(_mm_shuffle_epi8(x126, ctrl), msbs);
#else
auto zero = _mm_setzero_si128();
@ -614,7 +626,7 @@ struct GroupPortableImpl {
uint64_t ctrl;
};
#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
#ifdef ABSL_INTERNAL_HAVE_SSE2
using Group = GroupSse2Impl;
#else
using Group = GroupPortableImpl;
@ -700,13 +712,8 @@ size_t SelectBucketCountForIterRange(InputIter first, InputIter last,
return 0;
}
inline void AssertIsFull(ctrl_t* ctrl) {
ABSL_HARDENING_ASSERT(
(ctrl != nullptr && IsFull(*ctrl)) &&
"Invalid operation on iterator. The element might have "
"been erased, the table might have rehashed, or this may "
"be an end() iterator.");
}
#define ABSL_INTERNAL_ASSERT_IS_FULL(ctrl, msg) \
ABSL_HARDENING_ASSERT((ctrl != nullptr && IsFull(*ctrl)) && msg);
inline void AssertIsValid(ctrl_t* ctrl) {
ABSL_HARDENING_ASSERT(
@ -942,16 +949,22 @@ class raw_hash_set {
// PRECONDITION: not an end() iterator.
reference operator*() const {
AssertIsFull(ctrl_);
ABSL_INTERNAL_ASSERT_IS_FULL(ctrl_,
"operator*() called on invalid iterator.");
return PolicyTraits::element(slot_);
}
// PRECONDITION: not an end() iterator.
pointer operator->() const { return &operator*(); }
pointer operator->() const {
ABSL_INTERNAL_ASSERT_IS_FULL(ctrl_,
"operator-> called on invalid iterator.");
return &operator*();
}
// PRECONDITION: not an end() iterator.
iterator& operator++() {
AssertIsFull(ctrl_);
ABSL_INTERNAL_ASSERT_IS_FULL(ctrl_,
"operator++ called on invalid iterator.");
++ctrl_;
++slot_;
skip_empty_or_deleted();
@ -1500,7 +1513,8 @@ class raw_hash_set {
// This overload is necessary because otherwise erase<K>(const K&) would be
// a better match if non-const iterator is passed as an argument.
void erase(iterator it) {
AssertIsFull(it.ctrl_);
ABSL_INTERNAL_ASSERT_IS_FULL(it.ctrl_,
"erase() called on invalid iterator.")
PolicyTraits::destroy(&alloc_ref(), it.slot_);
erase_meta_only(it);
}
@ -1534,7 +1548,8 @@ class raw_hash_set {
}
node_type extract(const_iterator position) {
AssertIsFull(position.inner_.ctrl_);
ABSL_INTERNAL_ASSERT_IS_FULL(position.inner_.ctrl_,
"extract() called on invalid iterator.")
auto node =
CommonAccess::Transfer<node_type>(alloc_ref(), position.inner_.slot_);
erase_meta_only(position);
@ -2263,4 +2278,6 @@ struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
ABSL_NAMESPACE_END
} // namespace absl
#undef ABSL_INTERNAL_ASSERT_IS_FULL
#endif // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_

@ -2030,7 +2030,7 @@ TEST(TableDeathTest, EraseOfEndAsserts) {
IntTable t;
// Extra simple "regexp" as regexp support is highly varied across platforms.
constexpr char kDeathMsg[] = "Invalid operation on iterator";
constexpr char kDeathMsg[] = "erase.. called on invalid iterator";
EXPECT_DEATH_IF_SUPPORTED(t.erase(t.end()), kDeathMsg);
}

@ -23,8 +23,12 @@
#ifndef ABSL_STRINGS_NUMBERS_H_
#define ABSL_STRINGS_NUMBERS_H_
#ifdef __SSE4_2__
#include <x86intrin.h>
#ifdef __SSSE3__
#include <tmmintrin.h>
#endif
#ifdef _MSC_VER
#include <intrin.h>
#endif
#include <cstddef>
@ -36,14 +40,7 @@
#include <type_traits>
#include "absl/base/config.h"
#ifdef __SSE4_2__
// TODO(jorg): Remove this when we figure out the right way
// to swap bytes on SSE 4.2 that works with the compilers
// we claim to support. Also, add tests for the compiler
// that doesn't support the Intel _bswap64 intrinsic but
// does support all the SSE 4.2 intrinsics
#include "absl/base/internal/endian.h"
#endif
#include "absl/base/macros.h"
#include "absl/base/port.h"
#include "absl/numeric/bits.h"
@ -246,7 +243,7 @@ ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s, int_type* out,
// Returns the number of non-pad digits of the output (it can never be zero
// since 0 has one digit).
inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) {
#ifdef __SSE4_2__
#ifdef ABSL_INTERNAL_HAVE_SSSE3
uint64_t be = absl::big_endian::FromHost64(val);
const auto kNibbleMask = _mm_set1_epi8(0xf);
const auto kHexDigits = _mm_setr_epi8('0', '1', '2', '3', '4', '5', '6', '7',

Loading…
Cancel
Save