[clang] [llvm] Move KCFI type ID hash helpers out of LLVMSupport (PR #196784)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sun May 10 00:29:52 PDT 2026
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/196784
>From 4221477ec2409ccdcb2d133bf211de40e48135b8 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 9 May 2026 23:58:08 -0700
Subject: [PATCH 1/2] Move KCFI type ID hash helpers out of LLVMSupport
PR #167254 inappropriately introduced llvm/Support/Hash.{h,cpp} for the
KCFI helpers. The name is misleading - it has nothing to do with the
generic hashing facility in llvm/ADT/Hashing.h. KCFI is a CodeGen/IR
feature that does not belong in the foundational LLVMSupport.
Move the files to llvm/lib/Transforms/Utils/KCFIHash.cpp, alongside
setKCFIType, which is the only existing KCFI helper in TransformUtils.
---
clang/include/clang/Basic/CodeGenOptions.h | 2 +-
clang/lib/CodeGen/CodeGenModule.cpp | 2 +-
.../{Support/Hash.h => Transforms/Utils/KCFIHash.h} | 10 +++++-----
llvm/lib/Support/CMakeLists.txt | 1 -
llvm/lib/Transforms/Utils/CMakeLists.txt | 1 +
.../Hash.cpp => Transforms/Utils/KCFIHash.cpp} | 8 ++------
llvm/lib/Transforms/Utils/ModuleUtils.cpp | 2 +-
7 files changed, 11 insertions(+), 15 deletions(-)
rename llvm/include/llvm/{Support/Hash.h => Transforms/Utils/KCFIHash.h} (78%)
rename llvm/lib/{Support/Hash.cpp => Transforms/Utils/KCFIHash.cpp} (91%)
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index 3cbbf1a3074ac..e43112b4bb98b 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -22,10 +22,10 @@
#include "llvm/Frontend/Driver/CodeGenOptions.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/CodeGen.h"
-#include "llvm/Support/Hash.h"
#include "llvm/Support/Regex.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
+#include "llvm/Transforms/Utils/KCFIHash.h"
#include <map>
#include <memory>
#include <string>
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 106f1e63cd904..2d91b7eaa52dc 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -70,7 +70,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Hash.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/TargetParser/AArch64TargetParser.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
@@ -78,6 +77,7 @@
#include "llvm/TargetParser/X86TargetParser.h"
#include "llvm/Transforms/Instrumentation/KCFI.h"
#include "llvm/Transforms/Utils/BuildLibCalls.h"
+#include "llvm/Transforms/Utils/KCFIHash.h"
#include <optional>
#include <set>
diff --git a/llvm/include/llvm/Support/Hash.h b/llvm/include/llvm/Transforms/Utils/KCFIHash.h
similarity index 78%
rename from llvm/include/llvm/Support/Hash.h
rename to llvm/include/llvm/Transforms/Utils/KCFIHash.h
index 7a2cfb8774ae8..553c24d1289aa 100644
--- a/llvm/include/llvm/Support/Hash.h
+++ b/llvm/include/llvm/Transforms/Utils/KCFIHash.h
@@ -1,4 +1,4 @@
-//===- llvm/Support/Hash.h - Hash functions --------------------*- C++ -*-===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
//
-// This file provides hash functions.
+// Helpers for computing the 32-bit KCFI type ID from a mangled type name.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_HASH_H
-#define LLVM_SUPPORT_HASH_H
+#ifndef LLVM_TRANSFORMS_UTILS_KCFIHASH_H
+#define LLVM_TRANSFORMS_UTILS_KCFIHASH_H
#include "llvm/ADT/StringRef.h"
#include <cstdint>
@@ -34,4 +34,4 @@ LLVM_ABI uint32_t getKCFITypeID(StringRef MangledTypeName,
} // end namespace llvm
-#endif // LLVM_SUPPORT_HASH_H
+#endif // LLVM_TRANSFORMS_UTILS_KCFIHASH_H
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index e8d505f218b69..100cfb567c348 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -204,7 +204,6 @@ add_llvm_component_library(LLVMSupport
FormatVariadic.cpp
GlobPattern.cpp
GraphWriter.cpp
- Hash.cpp
HexagonAttributeParser.cpp
HexagonAttributes.cpp
InitLLVM.cpp
diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt b/llvm/lib/Transforms/Utils/CMakeLists.txt
index 82e9edf674866..933e204081ad2 100644
--- a/llvm/lib/Transforms/Utils/CMakeLists.txt
+++ b/llvm/lib/Transforms/Utils/CMakeLists.txt
@@ -40,6 +40,7 @@ add_llvm_component_library(LLVMTransformUtils
Instrumentation.cpp
IntegerDivision.cpp
IRNormalizer.cpp
+ KCFIHash.cpp
LCSSA.cpp
LibCallsShrinkWrap.cpp
Local.cpp
diff --git a/llvm/lib/Support/Hash.cpp b/llvm/lib/Transforms/Utils/KCFIHash.cpp
similarity index 91%
rename from llvm/lib/Support/Hash.cpp
rename to llvm/lib/Transforms/Utils/KCFIHash.cpp
index 6b5d000ee27c9..b02163e84ca78 100644
--- a/llvm/lib/Support/Hash.cpp
+++ b/llvm/lib/Transforms/Utils/KCFIHash.cpp
@@ -1,16 +1,12 @@
-//===- Hash.cpp - Hash functions ---------------------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-//
-// This file implements hash functions.
-//
-//===----------------------------------------------------------------------===//
-#include "llvm/Support/Hash.h"
+#include "llvm/Transforms/Utils/KCFIHash.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/xxhash.h"
diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index 63a234960a0ad..2976ebf46c9b7 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -19,9 +19,9 @@
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Casting.h"
-#include "llvm/Support/Hash.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Utils/KCFIHash.h"
using namespace llvm;
>From e7c21fa05285cf01f49a5e1f7d9d1a990ee838d0 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 10 May 2026 00:29:42 -0700
Subject: [PATCH 2/2] relocate xxHash64
---
llvm/include/llvm/Support/xxhash.h | 6 --
llvm/lib/Support/xxhash.cpp | 75 --------------------
llvm/lib/Transforms/Utils/KCFIHash.cpp | 94 +++++++++++++++++++++++++-
llvm/unittests/Support/xxhashTest.cpp | 12 ----
4 files changed, 93 insertions(+), 94 deletions(-)
diff --git a/llvm/include/llvm/Support/xxhash.h b/llvm/include/llvm/Support/xxhash.h
index 15c4f1bfd4563..b03aaa1e907b4 100644
--- a/llvm/include/llvm/Support/xxhash.h
+++ b/llvm/include/llvm/Support/xxhash.h
@@ -32,9 +32,6 @@
- xxHash source repository : https://github.com/Cyan4973/xxHash
*/
-/* based on revision d2df04efcbef7d7f6886d345861e5dfda4edacc1 Removed
- * everything but a simple interface for computing XXh64. */
-
#ifndef LLVM_SUPPORT_XXHASH_H
#define LLVM_SUPPORT_XXHASH_H
@@ -44,9 +41,6 @@
namespace llvm {
-// Deprecated pre-xxh3 64-bit hash.
-LLVM_ABI uint64_t xxHash64(const uint8_t *data, size_t len);
-
/// 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);
diff --git a/llvm/lib/Support/xxhash.cpp b/llvm/lib/Support/xxhash.cpp
index 6997fed7e8336..a1aee00b82637 100644
--- a/llvm/lib/Support/xxhash.cpp
+++ b/llvm/lib/Support/xxhash.cpp
@@ -32,9 +32,6 @@
* - xxHash source repository : https://github.com/Cyan4973/xxHash
*/
-// xxhash64 is based on commit d2df04efcbef7d7f6886d345861e5dfda4edacc1. Removed
-// everything but a simple interface for computing xxh64.
-
// xxh3_64bits is based on commit d5891596637d21366b9b1dcf2c0007a3edb26a9e (July
// 2023).
@@ -77,20 +74,6 @@ static const uint64_t PRIME64_3 = 1609587929392839161ULL;
static const uint64_t PRIME64_4 = 9650029242287828579ULL;
static const uint64_t PRIME64_5 = 2870177450012600261ULL;
-static uint64_t round(uint64_t Acc, uint64_t Input) {
- Acc += Input * PRIME64_2;
- Acc = rotl64(Acc, 31);
- Acc *= PRIME64_1;
- return Acc;
-}
-
-static uint64_t mergeRound(uint64_t Acc, uint64_t Val) {
- Val = round(0, Val);
- Acc ^= Val;
- Acc = Acc * PRIME64_1 + PRIME64_4;
- return Acc;
-}
-
static uint64_t XXH64_avalanche(uint64_t hash) {
hash ^= hash >> 33;
hash *= PRIME64_2;
@@ -100,64 +83,6 @@ static uint64_t XXH64_avalanche(uint64_t hash) {
return hash;
}
-uint64_t llvm::xxHash64(const uint8_t *P, size_t Len) {
- uint64_t Seed = 0;
- const uint8_t *const BEnd = P + Len;
- uint64_t H64;
-
- if (Len >= 32) {
- const unsigned char *const Limit = BEnd - 32;
- uint64_t V1 = Seed + PRIME64_1 + PRIME64_2;
- uint64_t V2 = Seed + PRIME64_2;
- uint64_t V3 = Seed + 0;
- uint64_t V4 = Seed - PRIME64_1;
-
- do {
- V1 = round(V1, endian::read64le(P));
- P += 8;
- V2 = round(V2, endian::read64le(P));
- P += 8;
- V3 = round(V3, endian::read64le(P));
- P += 8;
- V4 = round(V4, endian::read64le(P));
- P += 8;
- } while (P <= Limit);
-
- H64 = rotl64(V1, 1) + rotl64(V2, 7) + rotl64(V3, 12) + rotl64(V4, 18);
- H64 = mergeRound(H64, V1);
- H64 = mergeRound(H64, V2);
- H64 = mergeRound(H64, V3);
- H64 = mergeRound(H64, V4);
-
- } else {
- H64 = Seed + PRIME64_5;
- }
-
- H64 += (uint64_t)Len;
-
- while (reinterpret_cast<uintptr_t>(P) + 8 <=
- reinterpret_cast<uintptr_t>(BEnd)) {
- uint64_t const K1 = round(0, endian::read64le(P));
- H64 ^= K1;
- H64 = rotl64(H64, 27) * PRIME64_1 + PRIME64_4;
- P += 8;
- }
-
- if (reinterpret_cast<uintptr_t>(P) + 4 <= reinterpret_cast<uintptr_t>(BEnd)) {
- H64 ^= (uint64_t)(endian::read32le(P)) * PRIME64_1;
- H64 = rotl64(H64, 23) * PRIME64_2 + PRIME64_3;
- P += 4;
- }
-
- while (P < BEnd) {
- H64 ^= (*P) * PRIME64_5;
- H64 = rotl64(H64, 11) * PRIME64_1;
- P++;
- }
-
- return XXH64_avalanche(H64);
-}
-
constexpr size_t XXH3_SECRETSIZE_MIN = 136;
constexpr size_t XXH_SECRET_DEFAULT_SIZE = 192;
diff --git a/llvm/lib/Transforms/Utils/KCFIHash.cpp b/llvm/lib/Transforms/Utils/KCFIHash.cpp
index b02163e84ca78..df65ed53b66b6 100644
--- a/llvm/lib/Transforms/Utils/KCFIHash.cpp
+++ b/llvm/lib/Transforms/Utils/KCFIHash.cpp
@@ -7,10 +7,102 @@
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/KCFIHash.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/xxhash.h"
using namespace llvm;
+using namespace support;
+
+// xxHash64 is a deprecated pre-xxh3 hash, retained here only as the default
+// KCFI type-ID hash for ABI compatibility.
+
+static uint64_t rotl64(uint64_t X, size_t R) {
+ return (X << R) | (X >> (64 - R));
+}
+
+constexpr uint64_t PRIME64_1 = 11400714785074694791ULL;
+constexpr uint64_t PRIME64_2 = 14029467366897019727ULL;
+constexpr uint64_t PRIME64_3 = 1609587929392839161ULL;
+constexpr uint64_t PRIME64_4 = 9650029242287828579ULL;
+constexpr uint64_t PRIME64_5 = 2870177450012600261ULL;
+
+static uint64_t round(uint64_t Acc, uint64_t Input) {
+ Acc += Input * PRIME64_2;
+ Acc = rotl64(Acc, 31);
+ Acc *= PRIME64_1;
+ return Acc;
+}
+
+static uint64_t mergeRound(uint64_t Acc, uint64_t Val) {
+ Val = round(0, Val);
+ Acc ^= Val;
+ Acc = Acc * PRIME64_1 + PRIME64_4;
+ return Acc;
+}
+
+static uint64_t avalanche(uint64_t H) {
+ H ^= H >> 33;
+ H *= PRIME64_2;
+ H ^= H >> 29;
+ H *= PRIME64_3;
+ H ^= H >> 32;
+ return H;
+}
+
+static uint64_t xxHash64(const uint8_t *P, size_t Len) {
+ const uint8_t *const BEnd = P + Len;
+ uint64_t H64;
+
+ if (Len >= 32) {
+ const uint8_t *const Limit = BEnd - 32;
+ uint64_t V1 = PRIME64_1 + PRIME64_2;
+ uint64_t V2 = PRIME64_2;
+ uint64_t V3 = 0;
+ uint64_t V4 = -PRIME64_1;
+
+ do {
+ V1 = round(V1, endian::read64le(P));
+ P += 8;
+ V2 = round(V2, endian::read64le(P));
+ P += 8;
+ V3 = round(V3, endian::read64le(P));
+ P += 8;
+ V4 = round(V4, endian::read64le(P));
+ P += 8;
+ } while (P <= Limit);
+
+ H64 = rotl64(V1, 1) + rotl64(V2, 7) + rotl64(V3, 12) + rotl64(V4, 18);
+ H64 = mergeRound(H64, V1);
+ H64 = mergeRound(H64, V2);
+ H64 = mergeRound(H64, V3);
+ H64 = mergeRound(H64, V4);
+ } else {
+ H64 = PRIME64_5;
+ }
+
+ H64 += (uint64_t)Len;
+
+ while (reinterpret_cast<uintptr_t>(P) + 8 <=
+ reinterpret_cast<uintptr_t>(BEnd)) {
+ H64 ^= round(0, endian::read64le(P));
+ H64 = rotl64(H64, 27) * PRIME64_1 + PRIME64_4;
+ P += 8;
+ }
+
+ if (reinterpret_cast<uintptr_t>(P) + 4 <= reinterpret_cast<uintptr_t>(BEnd)) {
+ H64 ^= (uint64_t)endian::read32le(P) * PRIME64_1;
+ H64 = rotl64(H64, 23) * PRIME64_2 + PRIME64_3;
+ P += 4;
+ }
+
+ while (P < BEnd) {
+ H64 ^= (*P) * PRIME64_5;
+ H64 = rotl64(H64, 11) * PRIME64_1;
+ ++P;
+ }
+
+ return avalanche(H64);
+}
KCFIHashAlgorithm llvm::parseKCFIHashAlgorithm(StringRef Name) {
if (Name == "FNV-1a")
diff --git a/llvm/unittests/Support/xxhashTest.cpp b/llvm/unittests/Support/xxhashTest.cpp
index 9f91fc79e1f62..6097f0525e2b2 100644
--- a/llvm/unittests/Support/xxhashTest.cpp
+++ b/llvm/unittests/Support/xxhashTest.cpp
@@ -32,18 +32,6 @@ static void fillTestBuffer(uint8_t *buffer, size_t len) {
}
}
-TEST(xxhashTest, Basic) {
- EXPECT_EQ(0xef46db3751d8e999U, xxHash64(nullptr, 0));
- EXPECT_EQ(0x33bf00a859c4ba3fU,
- xxHash64(reinterpret_cast<const uint8_t *>("foo"), 3));
- EXPECT_EQ(0x48a37c90ad27a659U,
- xxHash64(reinterpret_cast<const uint8_t *>("bar"), 3));
- EXPECT_EQ(0x69196c1b3af0bff9U,
- xxHash64(reinterpret_cast<const uint8_t *>(
- "0123456789abcdefghijklmnopqrstuvwxyz"),
- 36));
-}
-
TEST(xxhashTest, xxh3) {
constexpr size_t size = 2243;
uint8_t a[size];
More information about the llvm-commits
mailing list