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