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
26namespace llvm {
27namespace memprof {
28class MemProfSummary;
29struct 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
42 FrameId addFrame(const Frame &F) {
43 const FrameId Id = hashFrame(F);
44 Frames.try_emplace(Key: Id, Args: F);
45 return Id;
46 }
47
48 CallStackId addCallStack(ArrayRef<FrameId> CS) {
49 CallStackId CSId = hashCallStack(CS);
50 CallStacks.try_emplace(Key: CSId, Args&: CS);
51 return CSId;
52 }
53
54 CallStackId addCallStack(SmallVector<FrameId> &&CS) {
55 CallStackId CSId = hashCallStack(CS);
56 CallStacks.try_emplace(Key: CSId, Args: std::move(CS));
57 return CSId;
58 }
59
60private:
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.
66 FrameId hashFrame(const Frame &F) const {
67 llvm::HashBuilder<llvm::TruncatedBLAKE3<8>, llvm::endianness::little>
68 HashBuilder;
69 HashBuilder.add(Args: F.Function, Args: F.LineOffset, Args: F.Column, Args: F.IsInlineFrame);
70 llvm::BLAKE3Result<8> Hash = HashBuilder.final();
71 FrameId Id;
72 std::memcpy(dest: &Id, src: Hash.data(), n: sizeof(Hash));
73 return Id;
74 }
75
76 // Compute a CallStackId for a given call stack.
77 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(Value: F);
82 llvm::BLAKE3Result<8> Hash = HashBuilder.final();
83 CallStackId CSId;
84 std::memcpy(dest: &CSId, src: Hash.data(), n: sizeof(Hash));
85 return CSId;
86 }
87};
88} // namespace memprof
89
90// Write the MemProf data to OS.
91LLVM_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