Replace direct uses of __builtin_prefetch from SwissTable with the wrapper functions.

Add a new (internal) feature test macro to detect whether the wrappers are no-ops on a given platform.

Note that one-arg __builtin_prefetch(x) is equivalent to __builtin_prefetch(x, 0, 3), per `man BUILTIN_PREFETCH(3)` and gcc docs.

PiperOrigin-RevId: 449508660
Change-Id: I144e750205eec0c956d8dd62bc72e10bdb87c4f7
diff --git a/absl/base/internal/prefetch.h b/absl/base/internal/prefetch.h
index a71b389..d4971a6 100644
--- a/absl/base/internal/prefetch.h
+++ b/absl/base/internal/prefetch.h
@@ -72,6 +72,8 @@
 
 #if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
 
+#define ABSL_INTERNAL_HAVE_PREFETCH 1
+
 // See __builtin_prefetch:
 // https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
 //
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index d733cb2..9ef7066 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -589,6 +589,7 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:endian",
+        "//absl/base:prefetch",
         "//absl/memory",
         "//absl/meta:type_traits",
         "//absl/numeric:bits",
@@ -611,6 +612,7 @@
         "//absl/base",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:prefetch",
         "//absl/base:raw_logging_internal",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index aad69fa..9b5c59a 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -681,6 +681,7 @@
     absl::memory
     absl::meta
     absl::optional
+    absl::prefetch
     absl::utility
     absl::hashtablez_sampler
   PUBLIC
@@ -702,6 +703,7 @@
     absl::base
     absl::config
     absl::core_headers
+    absl::prefetch
     absl::raw_logging_internal
     absl::strings
     GTest::gmock_main
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index 56251b2..769af50 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -197,6 +197,7 @@
 
 #include "absl/base/config.h"
 #include "absl/base/internal/endian.h"
+#include "absl/base/internal/prefetch.h"
 #include "absl/base/optimization.h"
 #include "absl/base/port.h"
 #include "absl/container/internal/common.h"
@@ -1636,12 +1637,13 @@
   template <class K = key_type>
   void prefetch(const key_arg<K>& key) const {
     (void)key;
-#if defined(__GNUC__)
+    // Avoid probing if we won't be able to prefetch the addresses received.
+#ifdef ABSL_INTERNAL_HAVE_PREFETCH
     prefetch_heap_block();
     auto seq = probe(ctrl_, hash_ref()(key), capacity_);
-    __builtin_prefetch(static_cast<const void*>(ctrl_ + seq.offset()));
-    __builtin_prefetch(static_cast<const void*>(slots_ + seq.offset()));
-#endif  // __GNUC__
+    base_internal::PrefetchT0(ctrl_ + seq.offset());
+    base_internal::PrefetchT0(slots_ + seq.offset());
+#endif  // ABSL_INTERNAL_HAVE_PREFETCH
   }
 
   // The API of find() has two extensions.
@@ -2159,9 +2161,7 @@
   // This is intended to overlap with execution of calculating the hash for a
   // key.
   void prefetch_heap_block() const {
-#if defined(__GNUC__)
-    __builtin_prefetch(static_cast<const void*>(ctrl_), 0, 1);
-#endif  // __GNUC__
+    base_internal::PrefetchT2(ctrl_);
   }
 
   HashtablezInfoHandle& infoz() { return settings_.template get<1>(); }
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index 9cd88a2..914ec0c 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -31,6 +31,7 @@
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/cycleclock.h"
+#include "absl/base/internal/prefetch.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/container/internal/container_memory.h"
 #include "absl/container/internal/hash_function_defaults.h"