xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ProfileData/IndexedMemProfData.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- IndexedMemProfData.h - MemProf format support ------------*- 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 implements IndexedMemProfData, a data structure to hold MemProf
10 // in a space optimized format. It also provides utility methods for writing
11 // MemProf data.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_PROFILEDATA_INDEXEDMEMPROFDATA_H
16 #define LLVM_PROFILEDATA_INDEXEDMEMPROFDATA_H
17 
18 #include "llvm/ProfileData/DataAccessProf.h"
19 #include "llvm/ProfileData/InstrProf.h"
20 #include "llvm/ProfileData/MemProf.h"
21 #include "llvm/Support/Compiler.h"
22 
23 #include <functional>
24 #include <optional>
25 
26 namespace llvm {
27 namespace memprof {
28 class MemProfSummary;
29 struct IndexedMemProfData {
30   // A map to hold memprof data per function. The lower 64 bits obtained from
31   // the md5 hash of the function name is used to index into the map.
32   llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord> Records;
33 
34   // A map to hold frame id to frame mappings. The mappings are used to
35   // convert IndexedMemProfRecord to MemProfRecords with frame information
36   // inline.
37   llvm::MapVector<FrameId, Frame> Frames;
38 
39   // A map to hold call stack id to call stacks.
40   llvm::MapVector<CallStackId, llvm::SmallVector<FrameId>> CallStacks;
41 
addFrameIndexedMemProfData42   FrameId addFrame(const Frame &F) {
43     const FrameId Id = hashFrame(F);
44     Frames.try_emplace(Id, F);
45     return Id;
46   }
47 
addCallStackIndexedMemProfData48   CallStackId addCallStack(ArrayRef<FrameId> CS) {
49     CallStackId CSId = hashCallStack(CS);
50     CallStacks.try_emplace(CSId, CS);
51     return CSId;
52   }
53 
addCallStackIndexedMemProfData54   CallStackId addCallStack(SmallVector<FrameId> &&CS) {
55     CallStackId CSId = hashCallStack(CS);
56     CallStacks.try_emplace(CSId, std::move(CS));
57     return CSId;
58   }
59 
60 private:
61   // Return a hash value based on the contents of the frame. Here we use a
62   // cryptographic hash function to minimize the chance of hash collisions.  We
63   // do persist FrameIds as part of memprof formats up to Version 2, inclusive.
64   // However, the deserializer never calls this function; it uses FrameIds
65   // merely as keys to look up Frames proper.
hashFrameIndexedMemProfData66   FrameId hashFrame(const Frame &F) const {
67     llvm::HashBuilder<llvm::TruncatedBLAKE3<8>, llvm::endianness::little>
68         HashBuilder;
69     HashBuilder.add(F.Function, F.LineOffset, F.Column, F.IsInlineFrame);
70     llvm::BLAKE3Result<8> Hash = HashBuilder.final();
71     FrameId Id;
72     std::memcpy(&Id, Hash.data(), sizeof(Hash));
73     return Id;
74   }
75 
76   // Compute a CallStackId for a given call stack.
hashCallStackIndexedMemProfData77   CallStackId hashCallStack(ArrayRef<FrameId> CS) const {
78     llvm::HashBuilder<llvm::TruncatedBLAKE3<8>, llvm::endianness::little>
79         HashBuilder;
80     for (FrameId F : CS)
81       HashBuilder.add(F);
82     llvm::BLAKE3Result<8> Hash = HashBuilder.final();
83     CallStackId CSId;
84     std::memcpy(&CSId, Hash.data(), sizeof(Hash));
85     return CSId;
86   }
87 };
88 } // namespace memprof
89 
90 // Write the MemProf data to OS.
91 LLVM_ABI Error writeMemProf(
92     ProfOStream &OS, memprof::IndexedMemProfData &MemProfData,
93     memprof::IndexedVersion MemProfVersionRequested, bool MemProfFullSchema,
94     std::unique_ptr<memprof::DataAccessProfData> DataAccessProfileData,
95     std::unique_ptr<memprof::MemProfSummary> MemProfSum);
96 } // namespace llvm
97 #endif
98