xref: /llvm-project/llvm/include/llvm/ADT/StableHashing.h (revision 0f525452896771cc8c579eb362dc7645e38fd0b9)
1 //===- llvm/ADT/StableHashing.h - Utilities for stable hashing * C++ *-----===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file provides types and functions for computing and combining stable
10 // hashes. Stable hashes can be useful for hashing across different modules,
11 // processes, machines, or compiler runs for a specific compiler version. It
12 // currently employs the xxh3_64bits hashing algorithm. Be aware that this
13 // implementation may be adjusted or updated as improvements to the compiler are
14 // made.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #ifndef LLVM_ADT_STABLEHASHING_H
19 #define LLVM_ADT_STABLEHASHING_H
20 
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/xxhash.h"
23 
24 namespace llvm {
25 
26 /// An opaque object representing a stable hash code. It can be serialized,
27 /// deserialized, and is stable across processes and executions.
28 using stable_hash = uint64_t;
29 
30 inline stable_hash stable_hash_combine(ArrayRef<stable_hash> Buffer) {
31   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(Buffer.data());
32   size_t Size = Buffer.size() * sizeof(stable_hash);
33   return xxh3_64bits(ArrayRef<uint8_t>(Ptr, Size));
34 }
35 
36 inline stable_hash stable_hash_combine(stable_hash A, stable_hash B) {
37   stable_hash Hashes[2] = {A, B};
38   return stable_hash_combine(Hashes);
39 }
40 
41 inline stable_hash stable_hash_combine(stable_hash A, stable_hash B,
42                                        stable_hash C) {
43   stable_hash Hashes[3] = {A, B, C};
44   return stable_hash_combine(Hashes);
45 }
46 
47 inline stable_hash stable_hash_combine(stable_hash A, stable_hash B,
48                                        stable_hash C, stable_hash D) {
49   stable_hash Hashes[4] = {A, B, C, D};
50   return stable_hash_combine(Hashes);
51 }
52 
53 // Removes suffixes introduced by LLVM from the name to enhance stability and
54 // maintain closeness to the original name across different builds.
55 inline StringRef get_stable_name(StringRef Name) {
56   // Return the part after ".content." that represents contents.
57   auto [P0, S0] = Name.rsplit(".content.");
58   if (!S0.empty())
59     return S0;
60 
61   // Ignore these suffixes.
62   auto [P1, S1] = Name.rsplit(".llvm.");
63   auto [P2, S2] = P1.rsplit(".__uniq.");
64   return P2;
65 }
66 
67 // Generates a consistent hash value for a given input name across different
68 // program executions and environments. This function first converts the input
69 // name into a stable form using the `get_stable_name` function, and then
70 // computes a hash of this stable name. For instance, `foo.llvm.1234` would have
71 // the same hash as `foo.llvm.5678.
72 inline stable_hash stable_hash_name(StringRef Name) {
73   return xxh3_64bits(get_stable_name(Name));
74 }
75 
76 } // namespace llvm
77 
78 #endif
79