summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMake/AbseilDll.cmake1
-rw-r--r--absl/base/BUILD.bazel25
-rw-r--r--absl/base/CMakeLists.txt26
-rw-r--r--absl/base/attributes.h26
-rw-r--r--absl/base/internal/prefetch.h109
-rw-r--r--absl/base/internal/prefetch_test.cc43
-rw-r--r--absl/container/flat_hash_map.h2
-rw-r--r--absl/container/flat_hash_set.h2
-rw-r--r--absl/container/node_hash_map.h2
-rw-r--r--absl/container/node_hash_set.h2
-rw-r--r--absl/debugging/internal/vdso_support.cc4
-rw-r--r--absl/strings/internal/cord_internal.h3
-rw-r--r--absl/strings/internal/escaping.cc2
-rw-r--r--absl/strings/numbers.cc16
-rw-r--r--absl/types/internal/variant.h6
15 files changed, 245 insertions, 24 deletions
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
index 4f7a287c..0b5f0a54 100644
--- a/CMake/AbseilDll.cmake
+++ b/CMake/AbseilDll.cmake
@@ -26,6 +26,7 @@ set(ABSL_INTERNAL_DLL_FILES
"base/internal/low_level_alloc.h"
"base/internal/low_level_scheduling.h"
"base/internal/per_thread_tls.h"
+ "base/internal/prefetch.h"
"base/internal/pretty_function.h"
"base/internal/raw_logging.cc"
"base/internal/raw_logging.h"
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 6f2f09b9..49e3a95f 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -704,6 +704,31 @@ cc_test(
],
)
+cc_library(
+ name = "prefetch",
+ hdrs = ["internal/prefetch.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl:__subpackages__",
+ ],
+ deps = [
+ ":config",
+ ],
+)
+
+cc_test(
+ name = "prefetch_test",
+ size = "small",
+ srcs = ["internal/prefetch_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":prefetch",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
cc_test(
name = "unique_small_name_test",
size = "small",
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
index 7e600f0b..0e1e0413 100644
--- a/absl/base/CMakeLists.txt
+++ b/absl/base/CMakeLists.txt
@@ -642,6 +642,32 @@ absl_cc_test(
GTest::gtest_main
)
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+ NAME
+ prefetch
+ HDRS
+ "internal/prefetch.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ LINKOPTS
+ ${ABSL_DEFAULT_LINKOPTS}
+ DEPS
+ absl::config
+)
+
+absl_cc_test(
+ NAME
+ prefetch_test
+ SRCS
+ "internal/prefetch_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::prefetch
+ GTest::gtest_main
+)
+
absl_cc_test(
NAME
optimization_test
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index c71038c7..e4e7a3d8 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -682,9 +682,18 @@
// not compile (on supported platforms) unless the variable has a constant
// initializer. This is useful for variables with static and thread storage
// duration, because it guarantees that they will not suffer from the so-called
-// "static init order fiasco". Prefer to put this attribute on the most visible
-// declaration of the variable, if there's more than one, because code that
-// accesses the variable can then use the attribute for optimization.
+// "static init order fiasco".
+//
+// This attribute must be placed on the initializing declaration of the
+// variable. Some compilers will give a -Wmissing-constinit warning when this
+// attribute is placed on some other declaration but missing from the
+// initializing declaration.
+//
+// In some cases (notably with thread_local variables), `ABSL_CONST_INIT` can
+// also be used in a non-initializing declaration to tell the compiler that a
+// variable is already initialized, reducing overhead that would otherwise be
+// incurred by a hidden guard variable. Thus annotating all declarations with
+// this attribute is recommended to potentially enhance optimization.
//
// Example:
//
@@ -693,14 +702,19 @@
// ABSL_CONST_INIT static MyType my_var;
// };
//
-// MyType MyClass::my_var = MakeMyType(...);
+// ABSL_CONST_INIT MyType MyClass::my_var = MakeMyType(...);
+//
+// For code or headers that are assured to only build with C++20 and up, prefer
+// just using the standard `constinit` keyword directly over this macro.
//
// Note that this attribute is redundant if the variable is declared constexpr.
-#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
+#if defined(__cpp_constinit) && __cpp_constinit >= 201907L
+#define ABSL_CONST_INIT constinit
+#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
#define ABSL_CONST_INIT [[clang::require_constant_initialization]]
#else
#define ABSL_CONST_INIT
-#endif // ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
+#endif
// ABSL_ATTRIBUTE_PURE_FUNCTION
//
diff --git a/absl/base/internal/prefetch.h b/absl/base/internal/prefetch.h
new file mode 100644
index 00000000..a71b3897
--- /dev/null
+++ b/absl/base/internal/prefetch.h
@@ -0,0 +1,109 @@
+// Copyright 2022 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.
+
+#ifndef ABSL_BASE_INTERNAL_PREFETCH_H_
+#define ABSL_BASE_INTERNAL_PREFETCH_H_
+
+#include "absl/base/config.h"
+
+// Compatibility wrappers around __builtin_prefetch, to prefetch data
+// for read if supported by the toolchain.
+
+// Move data into the cache before it is read, or "prefetch" it.
+//
+// The value of `addr` is the address of the memory to prefetch. If
+// the target and compiler support it, data prefetch instructions are
+// generated. If the prefetch is done some time before the memory is
+// read, it may be in the cache by the time the read occurs.
+//
+// The function names specify the temporal locality heuristic applied,
+// using the names of Intel prefetch instructions:
+//
+// T0 - high degree of temporal locality; data should be left in as
+// many levels of the cache possible
+// T1 - moderate degree of temporal locality
+// T2 - low degree of temporal locality
+// Nta - no temporal locality, data need not be left in the cache
+// after the read
+//
+// Incorrect or gratuitous use of these functions can degrade
+// performance, so use them only when representative benchmarks show
+// an improvement.
+//
+// Example usage:
+//
+// absl::base_internal::PrefetchT0(addr);
+//
+// Currently, the different prefetch calls behave on some Intel
+// architectures as follows:
+//
+// SNB..SKL SKX
+// PrefetchT0() L1/L2/L3 L1/L2
+// PrefetchT1() L2/L3 L2
+// PrefetchT2() L2/L3 L2
+// PrefetchNta() L1/--/L3 L1*
+//
+// * On SKX PrefetchNta() will bring the line into L1 but will evict
+// from L3 cache. This might result in surprising behavior.
+//
+// SNB = Sandy Bridge, SKL = Skylake, SKX = Skylake Xeon.
+//
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+void PrefetchT0(const void* addr);
+void PrefetchT1(const void* addr);
+void PrefetchT2(const void* addr);
+void PrefetchNta(const void* addr);
+
+// Implementation details follow.
+
+#if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
+
+// See __builtin_prefetch:
+// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
+//
+// These functions speculatively load for read only. This is
+// safe for all currently supported platforms. However, prefetch for
+// store may have problems depending on the target platform.
+//
+inline void PrefetchT0(const void* addr) {
+ // Note: this uses prefetcht0 on Intel.
+ __builtin_prefetch(addr, 0, 3);
+}
+inline void PrefetchT1(const void* addr) {
+ // Note: this uses prefetcht1 on Intel.
+ __builtin_prefetch(addr, 0, 2);
+}
+inline void PrefetchT2(const void* addr) {
+ // Note: this uses prefetcht2 on Intel.
+ __builtin_prefetch(addr, 0, 1);
+}
+inline void PrefetchNta(const void* addr) {
+ // Note: this uses prefetchtnta on Intel.
+ __builtin_prefetch(addr, 0, 0);
+}
+#else
+inline void PrefetchT0(const void*) {}
+inline void PrefetchT1(const void*) {}
+inline void PrefetchT2(const void*) {}
+inline void PrefetchNta(const void*) {}
+#endif
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_PREFETCH_H_
diff --git a/absl/base/internal/prefetch_test.cc b/absl/base/internal/prefetch_test.cc
new file mode 100644
index 00000000..7c1dae46
--- /dev/null
+++ b/absl/base/internal/prefetch_test.cc
@@ -0,0 +1,43 @@
+// Copyright 2022 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.
+
+#include "absl/base/internal/prefetch.h"
+
+#include "gtest/gtest.h"
+
+namespace {
+
+int number = 42;
+
+TEST(Prefetch, TemporalLocalityNone) {
+ absl::base_internal::PrefetchNta(&number);
+ EXPECT_EQ(number, 42);
+}
+
+TEST(Prefetch, TemporalLocalityLow) {
+ absl::base_internal::PrefetchT2(&number);
+ EXPECT_EQ(number, 42);
+}
+
+TEST(Prefetch, TemporalLocalityMedium) {
+ absl::base_internal::PrefetchT1(&number);
+ EXPECT_EQ(number, 42);
+}
+
+TEST(Prefetch, TemporalLocalityHigh) {
+ absl::base_internal::PrefetchT0(&number);
+ EXPECT_EQ(number, 42);
+}
+
+} // namespace
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h
index 13779eda..cbb24693 100644
--- a/absl/container/flat_hash_map.h
+++ b/absl/container/flat_hash_map.h
@@ -76,7 +76,7 @@ struct FlatHashMapPolicy;
// absl/hash/hash.h for information on extending Abseil hashing to user-defined
// types.
//
-// Using `absl::flat_hash_map` at interface boundries in dynamically loaded
+// Using `absl::flat_hash_map` at interface boundaries in dynamically loaded
// libraries (e.g. .dll, .so) is unsupported due to way `absl::Hash` values may
// be randomized across dynamically loaded libraries.
//
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h
index 304c2abb..4938c703 100644
--- a/absl/container/flat_hash_set.h
+++ b/absl/container/flat_hash_set.h
@@ -72,7 +72,7 @@ struct FlatHashSetPolicy;
// absl/hash/hash.h for information on extending Abseil hashing to user-defined
// types.
//
-// Using `absl::flat_hash_set` at interface boundries in dynamically loaded
+// Using `absl::flat_hash_set` at interface boundaries in dynamically loaded
// libraries (e.g. .dll, .so) is unsupported due to way `absl::Hash` values may
// be randomized across dynamically loaded libraries.
//
diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h
index f2175d16..c91cae69 100644
--- a/absl/container/node_hash_map.h
+++ b/absl/container/node_hash_map.h
@@ -78,7 +78,7 @@ class NodeHashMapPolicy;
// absl/hash/hash.h for information on extending Abseil hashing to user-defined
// types.
//
-// Using `absl::node_hash_map` at interface boundries in dynamically loaded
+// Using `absl::node_hash_map` at interface boundaries in dynamically loaded
// libraries (e.g. .dll, .so) is unsupported due to way `absl::Hash` values may
// be randomized across dynamically loaded libraries.
//
diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h
index a9ff7e1b..f2cc70c3 100644
--- a/absl/container/node_hash_set.h
+++ b/absl/container/node_hash_set.h
@@ -74,7 +74,7 @@ struct NodeHashSetPolicy;
// absl/hash/hash.h for information on extending Abseil hashing to user-defined
// types.
//
-// Using `absl::node_hash_set` at interface boundries in dynamically loaded
+// Using `absl::node_hash_set` at interface boundaries in dynamically loaded
// libraries (e.g. .dll, .so) is unsupported due to way `absl::Hash` values may
// be randomized across dynamically loaded libraries.
//
diff --git a/absl/debugging/internal/vdso_support.cc b/absl/debugging/internal/vdso_support.cc
index e63ac4a3..40eb055f 100644
--- a/absl/debugging/internal/vdso_support.cc
+++ b/absl/debugging/internal/vdso_support.cc
@@ -69,7 +69,9 @@ ABSL_CONST_INIT
std::atomic<const void *> VDSOSupport::vdso_base_(
debugging_internal::ElfMemImage::kInvalidBase);
-std::atomic<VDSOSupport::GetCpuFn> VDSOSupport::getcpu_fn_(&InitAndGetCPU);
+ABSL_CONST_INIT std::atomic<VDSOSupport::GetCpuFn> VDSOSupport::getcpu_fn_(
+ &InitAndGetCPU);
+
VDSOSupport::VDSOSupport()
// If vdso_base_ is still set to kInvalidBase, we got here
// before VDSOSupport::Init has been called. Call it now.
diff --git a/absl/strings/internal/cord_internal.h b/absl/strings/internal/cord_internal.h
index 5ca5e589..6ae418e7 100644
--- a/absl/strings/internal/cord_internal.h
+++ b/absl/strings/internal/cord_internal.h
@@ -411,7 +411,8 @@ struct ConstInitExternalStorage {
};
template <typename Str>
-CordRepExternal ConstInitExternalStorage<Str>::value(Str::value);
+ABSL_CONST_INIT CordRepExternal
+ ConstInitExternalStorage<Str>::value(Str::value);
enum {
kMaxInline = 15,
diff --git a/absl/strings/internal/escaping.cc b/absl/strings/internal/escaping.cc
index 7f87e124..cfea0961 100644
--- a/absl/strings/internal/escaping.cc
+++ b/absl/strings/internal/escaping.cc
@@ -21,7 +21,7 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace strings_internal {
-const char kBase64Chars[] =
+ABSL_CONST_INIT const char kBase64Chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding) {
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index cbd84c91..e798fc69 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -757,8 +757,8 @@ struct LookupTables {
//
// uint128& operator/=(uint128) is not constexpr, so hardcode the resulting
// array to avoid a static initializer.
-template<>
-const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
+template <>
+ABSL_CONST_INIT const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
0,
0,
MakeUint128(9223372036854775807u, 18446744073709551615u),
@@ -809,8 +809,8 @@ const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
//
// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
// to avoid a static initializer.
-template<>
-const int128 LookupTables<int128>::kVmaxOverBase[] = {
+template <>
+ABSL_CONST_INIT const int128 LookupTables<int128>::kVmaxOverBase[] = {
0,
0,
MakeInt128(4611686018427387903, 18446744073709551615u),
@@ -862,8 +862,8 @@ const int128 LookupTables<int128>::kVmaxOverBase[] = {
//
// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
// to avoid a static initializer.
-template<>
-const int128 LookupTables<int128>::kVminOverBase[] = {
+template <>
+ABSL_CONST_INIT const int128 LookupTables<int128>::kVminOverBase[] = {
0,
0,
MakeInt128(-4611686018427387904, 0u),
@@ -904,11 +904,11 @@ const int128 LookupTables<int128>::kVminOverBase[] = {
};
template <typename IntType>
-const IntType LookupTables<IntType>::kVmaxOverBase[] =
+ABSL_CONST_INIT const IntType LookupTables<IntType>::kVmaxOverBase[] =
X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max());
template <typename IntType>
-const IntType LookupTables<IntType>::kVminOverBase[] =
+ABSL_CONST_INIT const IntType LookupTables<IntType>::kVminOverBase[] =
X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::min());
#undef X_OVER_BASE_INITIALIZER
diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h
index 772008c7..7c402ece 100644
--- a/absl/types/internal/variant.h
+++ b/absl/types/internal/variant.h
@@ -16,8 +16,8 @@
// separate file to avoid cluttering the top of the API header with
// implementation details.
-#ifndef ABSL_TYPES_variant_internal_H_
-#define ABSL_TYPES_variant_internal_H_
+#ifndef ABSL_TYPES_VARIANT_INTERNAL_H_
+#define ABSL_TYPES_VARIANT_INTERNAL_H_
#include <cassert>
#include <cstddef>
@@ -1643,4 +1643,4 @@ ABSL_NAMESPACE_END
} // namespace absl
#endif // !defined(ABSL_USES_STD_VARIANT)
-#endif // ABSL_TYPES_variant_internal_H_
+#endif // ABSL_TYPES_VARIANT_INTERNAL_H_