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