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 /// The loaded contextual profile, suitable for mutation during IPO passes. We 28 /// generally expect a fraction of counters and of callsites to be populated. 29 /// We continue to model counters as vectors, but callsites are modeled as a map 30 /// of a map. The expectation is that, typically, there is a small number of 31 /// indirect targets (usually, 1 for direct calls); but potentially a large 32 /// number of callsites, and, as inlining progresses, the callsite count of a 33 /// caller will grow. 34 class PGOContextualProfile final { 35 public: 36 using CallTargetMapTy = std::map<GlobalValue::GUID, PGOContextualProfile>; 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 45 PGOContextualProfile(GlobalValue::GUID G, 46 SmallVectorImpl<uint64_t> &&Counters) 47 : GUID(G), Counters(std::move(Counters)) {} 48 49 Expected<PGOContextualProfile &> 50 getOrEmplace(uint32_t Index, GlobalValue::GUID G, 51 SmallVectorImpl<uint64_t> &&Counters); 52 53 public: 54 PGOContextualProfile(const PGOContextualProfile &) = delete; 55 PGOContextualProfile &operator=(const PGOContextualProfile &) = delete; 56 PGOContextualProfile(PGOContextualProfile &&) = default; 57 PGOContextualProfile &operator=(PGOContextualProfile &&) = default; 58 59 GlobalValue::GUID guid() const { return GUID; } 60 const SmallVectorImpl<uint64_t> &counters() const { return Counters; } 61 const CallsiteMapTy &callsites() const { return Callsites; } 62 CallsiteMapTy &callsites() { return Callsites; } 63 64 bool hasCallsite(uint32_t I) const { 65 return Callsites.find(I) != Callsites.end(); 66 } 67 68 const CallTargetMapTy &callsite(uint32_t I) const { 69 assert(hasCallsite(I) && "Callsite not found"); 70 return Callsites.find(I)->second; 71 } 72 void getContainedGuids(DenseSet<GlobalValue::GUID> &Guids) const; 73 }; 74 75 class PGOCtxProfileReader final { 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>, PGOContextualProfile>> 83 readContext(bool ExpectIndex); 84 bool canReadContext(); 85 86 public: 87 PGOCtxProfileReader(BitstreamCursor &Cursor) : Cursor(Cursor) {} 88 89 Expected<std::map<GlobalValue::GUID, PGOContextualProfile>> loadContexts(); 90 }; 91 } // namespace llvm 92 #endif 93