1 //===--- PGOCtxProfReader.h - Contextual profile reader ---------*- 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 /// \file 10 /// 11 /// Reader for contextual iFDO profile, which comes in bitstream format. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H 16 #define LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H 17 18 #include "llvm/ADT/DenseSet.h" 19 #include "llvm/Bitstream/BitstreamReader.h" 20 #include "llvm/IR/GlobalValue.h" 21 #include "llvm/ProfileData/PGOCtxProfWriter.h" 22 #include "llvm/Support/Error.h" 23 #include <map> 24 #include <vector> 25 26 namespace llvm { 27 /// A node (context) in the loaded contextual profile, suitable for mutation 28 /// during IPO passes. We generally expect a fraction of counters and 29 /// callsites to be populated. We continue to model counters as vectors, but 30 /// callsites are modeled as a map of a map. The expectation is that, typically, 31 /// there is a small number of indirect targets (usually, 1 for direct calls); 32 /// but potentially a large number of callsites, and, as inlining progresses, 33 /// the callsite count of a caller will grow. 34 class PGOCtxProfContext final { 35 public: 36 using CallTargetMapTy = std::map<GlobalValue::GUID, PGOCtxProfContext>; 37 using CallsiteMapTy = DenseMap<uint32_t, CallTargetMapTy>; 38 39 private: 40 friend class PGOCtxProfileReader; 41 GlobalValue::GUID GUID = 0; 42 SmallVector<uint64_t, 16> Counters; 43 CallsiteMapTy Callsites; 44 PGOCtxProfContext(GlobalValue::GUID G,SmallVectorImpl<uint64_t> && Counters)45 PGOCtxProfContext(GlobalValue::GUID G, SmallVectorImpl<uint64_t> &&Counters) 46 : GUID(G), Counters(std::move(Counters)) {} 47 48 Expected<PGOCtxProfContext &> 49 getOrEmplace(uint32_t Index, GlobalValue::GUID G, 50 SmallVectorImpl<uint64_t> &&Counters); 51 52 public: 53 PGOCtxProfContext(const PGOCtxProfContext &) = delete; 54 PGOCtxProfContext &operator=(const PGOCtxProfContext &) = delete; 55 PGOCtxProfContext(PGOCtxProfContext &&) = default; 56 PGOCtxProfContext &operator=(PGOCtxProfContext &&) = default; 57 guid()58 GlobalValue::GUID guid() const { return GUID; } counters()59 const SmallVectorImpl<uint64_t> &counters() const { return Counters; } callsites()60 const CallsiteMapTy &callsites() const { return Callsites; } callsites()61 CallsiteMapTy &callsites() { return Callsites; } 62 hasCallsite(uint32_t I)63 bool hasCallsite(uint32_t I) const { 64 return Callsites.find(I) != Callsites.end(); 65 } 66 callsite(uint32_t I)67 const CallTargetMapTy &callsite(uint32_t I) const { 68 assert(hasCallsite(I) && "Callsite not found"); 69 return Callsites.find(I)->second; 70 } 71 void getContainedGuids(DenseSet<GlobalValue::GUID> &Guids) const; 72 }; 73 74 class PGOCtxProfileReader final { 75 StringRef Magic; 76 BitstreamCursor Cursor; 77 Expected<BitstreamEntry> advance(); 78 Error readMetadata(); 79 Error wrongValue(const Twine &); 80 Error unsupported(const Twine &); 81 82 Expected<std::pair<std::optional<uint32_t>, PGOCtxProfContext>> 83 readContext(bool ExpectIndex); 84 bool canReadContext(); 85 86 public: PGOCtxProfileReader(StringRef Buffer)87 PGOCtxProfileReader(StringRef Buffer) 88 : Magic(Buffer.substr(0, PGOCtxProfileWriter::ContainerMagic.size())), 89 Cursor(Buffer.substr(PGOCtxProfileWriter::ContainerMagic.size())) {} 90 91 Expected<std::map<GlobalValue::GUID, PGOCtxProfContext>> loadContexts(); 92 }; 93 } // namespace llvm 94 #endif 95