[llvm] [ADT] Decouple xxhash.h from ADT. NFC (PR #196774)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sat May 9 20:20:38 PDT 2026


https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/196774

Move xxHash64, xxh3_64bits, and xxh3_128bits ArrayRef/StringRef
overloads from llvm/Support/xxhash.h to inline overloads in
llvm/ADT/ArrayRef.h and llvm/ADT/StringRef.h, so xxhash.h has no ADT
dependencies.

This is prerequisite for using xxh3 as the combine_bytes backend in
llvm/ADT/Hashing.h (#194567), which would otherwise reintroduce a header
dependency cycle.

FoldingSet.h and StableHashing.h adjust to call the new
pointer-and-length entry point.

>From 2cc3af248083de9422de5d27234445918b7eba0e Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 9 May 2026 20:13:53 -0700
Subject: [PATCH] [ADT] Decouple xxhash.h from ADT. NFC

Move xxHash64, xxh3_64bits, and xxh3_128bits ArrayRef/StringRef
overloads from llvm/Support/xxhash.h to inline overloads in
llvm/ADT/ArrayRef.h and llvm/ADT/StringRef.h, so xxhash.h has no ADT
dependencies.

This is prerequisite for using xxh3 as the combine_bytes backend in
llvm/ADT/Hashing.h (#194567), which would otherwise reintroduce a header
dependency cycle.

FoldingSet.h and StableHashing.h adjust to call the new
pointer-and-length entry point.
---
 llvm/benchmarks/xxhash.cpp            |  1 +
 llvm/include/llvm/ADT/ArrayRef.h      | 14 ++++++++++++++
 llvm/include/llvm/ADT/FoldingSet.h    |  4 ++--
 llvm/include/llvm/ADT/StableHashing.h |  5 ++---
 llvm/include/llvm/ADT/StringRef.h     | 12 ++++++++++++
 llvm/include/llvm/Support/xxhash.h    | 20 ++++++++++----------
 llvm/lib/Support/xxhash.cpp           | 19 ++++---------------
 7 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/llvm/benchmarks/xxhash.cpp b/llvm/benchmarks/xxhash.cpp
index 429cbc0fa87d4..ab72ebd649293 100644
--- a/llvm/benchmarks/xxhash.cpp
+++ b/llvm/benchmarks/xxhash.cpp
@@ -1,5 +1,6 @@
 #include "llvm/Support/xxhash.h"
 #include "benchmark/benchmark.h"
+#include "llvm/ADT/ArrayRef.h"
 
 #include <memory>
 
diff --git a/llvm/include/llvm/ADT/ArrayRef.h b/llvm/include/llvm/ADT/ArrayRef.h
index 86d4a6ec0e907..366233fdefd02 100644
--- a/llvm/include/llvm/ADT/ArrayRef.h
+++ b/llvm/include/llvm/ADT/ArrayRef.h
@@ -13,6 +13,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/xxhash.h"
 #include <algorithm>
 #include <array>
 #include <cassert>
@@ -551,6 +552,19 @@ template <typename T> hash_code hash_value(ArrayRef<T> S) {
   return hash_combine_range(S);
 }
 
+/// Inline ArrayRef overloads of the xxhash entry points declared
+/// out-of-line in llvm/Support/xxhash.h. They live here so xxhash.h can stay
+/// free of ADT dependencies.
+inline uint64_t xxHash64(ArrayRef<uint8_t> data) {
+  return xxHash64(data.data(), data.size());
+}
+inline uint64_t xxh3_64bits(ArrayRef<uint8_t> data) {
+  return xxh3_64bits(data.data(), data.size());
+}
+inline XXH128_hash_t xxh3_128bits(ArrayRef<uint8_t> data) {
+  return xxh3_128bits(data.data(), data.size());
+}
+
 // Provide DenseMapInfo for ArrayRefs.
 template <typename T> struct DenseMapInfo<ArrayRef<T>, void> {
   static inline ArrayRef<T> getEmptyKey() {
diff --git a/llvm/include/llvm/ADT/FoldingSet.h b/llvm/include/llvm/ADT/FoldingSet.h
index ab501ad172be6..cde22fe35e390 100644
--- a/llvm/include/llvm/ADT/FoldingSet.h
+++ b/llvm/include/llvm/ADT/FoldingSet.h
@@ -185,8 +185,8 @@ class FoldingSetNodeIDRef {
   // Compute a deterministic hash value across processes that is suitable for
   // on-disk serialization.
   unsigned computeStableHash() const {
-    return static_cast<unsigned>(xxh3_64bits(ArrayRef(
-        reinterpret_cast<const uint8_t *>(Data), sizeof(unsigned) * Size)));
+    return static_cast<unsigned>(xxh3_64bits(
+        reinterpret_cast<const uint8_t *>(Data), sizeof(unsigned) * Size));
   }
 
   LLVM_ABI bool operator==(FoldingSetNodeIDRef) const;
diff --git a/llvm/include/llvm/ADT/StableHashing.h b/llvm/include/llvm/ADT/StableHashing.h
index 0dd83be639424..1beb5b85c9967 100644
--- a/llvm/include/llvm/ADT/StableHashing.h
+++ b/llvm/include/llvm/ADT/StableHashing.h
@@ -30,9 +30,8 @@ namespace llvm {
 using stable_hash = uint64_t;
 
 inline stable_hash stable_hash_combine(ArrayRef<stable_hash> Buffer) {
-  const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(Buffer.data());
-  size_t Size = Buffer.size() * sizeof(stable_hash);
-  return xxh3_64bits(ArrayRef<uint8_t>(Ptr, Size));
+  return xxh3_64bits(reinterpret_cast<const uint8_t *>(Buffer.data()),
+                     Buffer.size() * sizeof(stable_hash));
 }
 
 inline stable_hash stable_hash_combine(stable_hash A, stable_hash B) {
diff --git a/llvm/include/llvm/ADT/StringRef.h b/llvm/include/llvm/ADT/StringRef.h
index 71aa7157dfd98..7ed0d6efdbeb3 100644
--- a/llvm/include/llvm/ADT/StringRef.h
+++ b/llvm/include/llvm/ADT/StringRef.h
@@ -13,6 +13,7 @@
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/xxhash.h"
 #include <algorithm>
 #include <cassert>
 #include <cstddef>
@@ -940,6 +941,17 @@ inline std::string &operator+=(std::string &buffer, StringRef string) {
 /// Compute a hash_code for a StringRef.
 [[nodiscard]] LLVM_ABI hash_code hash_value(StringRef S);
 
+/// Inline StringRef overloads of the xxhash entry points declared out-of-line
+/// in llvm/Support/xxhash.h. They live here so xxhash.h can stay free of ADT
+/// dependencies.
+inline uint64_t xxHash64(StringRef data) {
+  return xxHash64(reinterpret_cast<const uint8_t *>(data.data()), data.size());
+}
+inline uint64_t xxh3_64bits(StringRef data) {
+  return xxh3_64bits(reinterpret_cast<const uint8_t *>(data.data()),
+                     data.size());
+}
+
 // Provide DenseMapInfo for StringRefs.
 template <> struct DenseMapInfo<StringRef, void> {
   static inline StringRef getEmptyKey() {
diff --git a/llvm/include/llvm/Support/xxhash.h b/llvm/include/llvm/Support/xxhash.h
index b521adbef3456..15c4f1bfd4563 100644
--- a/llvm/include/llvm/Support/xxhash.h
+++ b/llvm/include/llvm/Support/xxhash.h
@@ -38,19 +38,18 @@
 #ifndef LLVM_SUPPORT_XXHASH_H
 #define LLVM_SUPPORT_XXHASH_H
 
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
+#include <cstddef>
+#include <cstdint>
 
 namespace llvm {
 
-LLVM_ABI uint64_t xxHash64(llvm::StringRef Data);
-LLVM_ABI uint64_t xxHash64(llvm::ArrayRef<uint8_t> Data);
+// Deprecated pre-xxh3 64-bit hash.
+LLVM_ABI uint64_t xxHash64(const uint8_t *data, size_t len);
 
-LLVM_ABI uint64_t xxh3_64bits(ArrayRef<uint8_t> data);
-inline uint64_t xxh3_64bits(StringRef data) {
-  return xxh3_64bits(ArrayRef(data.bytes_begin(), data.size()));
-}
+/// XXH3's 64-bit variant. Inline ArrayRef and StringRef overloads live in
+/// llvm/ADT/ArrayRef.h and llvm/ADT/StringRef.h.
+LLVM_ABI uint64_t xxh3_64bits(const uint8_t *data, size_t len);
 
 /*-**********************************************************************
  *  XXH3 128-bit variant
@@ -72,8 +71,9 @@ struct XXH128_hash_t {
   }
 };
 
-/// XXH3's 128-bit variant.
-LLVM_ABI XXH128_hash_t xxh3_128bits(ArrayRef<uint8_t> data);
+/// XXH3's 128-bit variant. Inline ArrayRef overload lives in
+/// llvm/ADT/ArrayRef.h.
+LLVM_ABI XXH128_hash_t xxh3_128bits(const uint8_t *data, size_t len);
 
 } // namespace llvm
 
diff --git a/llvm/lib/Support/xxhash.cpp b/llvm/lib/Support/xxhash.cpp
index cdb76d57e2c1d..6997fed7e8336 100644
--- a/llvm/lib/Support/xxhash.cpp
+++ b/llvm/lib/Support/xxhash.cpp
@@ -100,11 +100,9 @@ static uint64_t XXH64_avalanche(uint64_t hash) {
   return hash;
 }
 
-uint64_t llvm::xxHash64(StringRef Data) {
-  size_t Len = Data.size();
+uint64_t llvm::xxHash64(const uint8_t *P, size_t Len) {
   uint64_t Seed = 0;
-  const unsigned char *P = Data.bytes_begin();
-  const unsigned char *const BEnd = Data.bytes_end();
+  const uint8_t *const BEnd = P + Len;
   uint64_t H64;
 
   if (Len >= 32) {
@@ -160,10 +158,6 @@ uint64_t llvm::xxHash64(StringRef Data) {
   return XXH64_avalanche(H64);
 }
 
-uint64_t llvm::xxHash64(ArrayRef<uint8_t> Data) {
-  return xxHash64({(const char *)Data.data(), Data.size()});
-}
-
 constexpr size_t XXH3_SECRETSIZE_MIN = 136;
 constexpr size_t XXH_SECRET_DEFAULT_SIZE = 192;
 
@@ -550,9 +544,7 @@ static uint64_t XXH3_hashLong_64b(const uint8_t *input, size_t len,
                         (uint64_t)len * PRIME64_1);
 }
 
-uint64_t llvm::xxh3_64bits(ArrayRef<uint8_t> data) {
-  auto *in = data.data();
-  size_t len = data.size();
+uint64_t llvm::xxh3_64bits(const uint8_t *in, size_t len) {
   if (len <= 16)
     return XXH3_len_0to16_64b(in, len, kSecret, 0);
   if (len <= 128)
@@ -1020,10 +1012,7 @@ XXH3_hashLong_128b(const uint8_t *input, size_t len, const uint8_t *secret,
   return h128;
 }
 
-llvm::XXH128_hash_t llvm::xxh3_128bits(ArrayRef<uint8_t> data) {
-  size_t len = data.size();
-  const uint8_t *input = data.data();
-
+llvm::XXH128_hash_t llvm::xxh3_128bits(const uint8_t *input, size_t len) {
   /*
    * If an action is to be taken if `secret` conditions are not respected,
    * it should be done here.



More information about the llvm-commits mailing list