File indexing completed on 2026-05-10 08:44:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H
0016 #define LLVM_PROFILEDATA_CTXINSTRPROFILEREADER_H
0017
0018 #include "llvm/Bitstream/BitstreamReader.h"
0019 #include "llvm/IR/GlobalValue.h"
0020 #include "llvm/ProfileData/PGOCtxProfWriter.h"
0021 #include "llvm/Support/Error.h"
0022 #include <map>
0023
0024 namespace llvm {
0025 class PGOContextualProfile;
0026 class PGOCtxProfContext;
0027
0028 namespace internal {
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 class IndexNode {
0041
0042
0043 friend class ::llvm::PGOCtxProfContext;
0044 friend class ::llvm::PGOContextualProfile;
0045
0046 IndexNode *Previous = nullptr;
0047 IndexNode *Next = nullptr;
0048
0049 ~IndexNode() {
0050 if (Next)
0051 Next->Previous = Previous;
0052 if (Previous)
0053 Previous->Next = Next;
0054 }
0055
0056 IndexNode(const IndexNode &Other) = delete;
0057
0058 IndexNode(IndexNode &&Other) {
0059
0060 Next = Other.Next;
0061 Previous = Other.Previous;
0062
0063
0064 if (Other.Next)
0065 Other.Next->Previous = this;
0066 if (Other.Previous)
0067 Other.Previous->Next = this;
0068
0069
0070 Other.Next = nullptr;
0071 Other.Previous = nullptr;
0072 }
0073 IndexNode() = default;
0074 };
0075 }
0076
0077
0078
0079
0080
0081
0082
0083
0084 class PGOCtxProfContext final : public internal::IndexNode {
0085 public:
0086 using CallTargetMapTy = std::map<GlobalValue::GUID, PGOCtxProfContext>;
0087 using CallsiteMapTy = std::map<uint32_t, CallTargetMapTy>;
0088
0089 private:
0090 friend class PGOCtxProfileReader;
0091 friend class PGOContextualProfile;
0092
0093 GlobalValue::GUID GUID = 0;
0094 SmallVector<uint64_t, 16> Counters;
0095 CallsiteMapTy Callsites;
0096
0097 PGOCtxProfContext(GlobalValue::GUID G, SmallVectorImpl<uint64_t> &&Counters)
0098 : GUID(G), Counters(std::move(Counters)) {}
0099
0100 Expected<PGOCtxProfContext &>
0101 getOrEmplace(uint32_t Index, GlobalValue::GUID G,
0102 SmallVectorImpl<uint64_t> &&Counters);
0103
0104
0105
0106 PGOCtxProfContext() = default;
0107
0108 public:
0109 PGOCtxProfContext(const PGOCtxProfContext &) = delete;
0110 PGOCtxProfContext &operator=(const PGOCtxProfContext &) = delete;
0111 PGOCtxProfContext(PGOCtxProfContext &&) = default;
0112 PGOCtxProfContext &operator=(PGOCtxProfContext &&) = delete;
0113
0114 GlobalValue::GUID guid() const { return GUID; }
0115 const SmallVectorImpl<uint64_t> &counters() const { return Counters; }
0116 SmallVectorImpl<uint64_t> &counters() { return Counters; }
0117
0118 uint64_t getEntrycount() const {
0119 assert(!Counters.empty() &&
0120 "Functions are expected to have at their entry BB instrumented, so "
0121 "there should always be at least 1 counter.");
0122 return Counters[0];
0123 }
0124
0125 const CallsiteMapTy &callsites() const { return Callsites; }
0126 CallsiteMapTy &callsites() { return Callsites; }
0127
0128 void ingestContext(uint32_t CSId, PGOCtxProfContext &&Other) {
0129 callsites()[CSId].emplace(Other.guid(), std::move(Other));
0130 }
0131
0132 void ingestAllContexts(uint32_t CSId, CallTargetMapTy &&Other) {
0133 auto [_, Inserted] = callsites().try_emplace(CSId, std::move(Other));
0134 (void)Inserted;
0135 assert(Inserted &&
0136 "CSId was expected to be newly created as result of e.g. inlining");
0137 }
0138
0139 void resizeCounters(uint32_t Size) { Counters.resize(Size); }
0140
0141 bool hasCallsite(uint32_t I) const {
0142 return Callsites.find(I) != Callsites.end();
0143 }
0144
0145 const CallTargetMapTy &callsite(uint32_t I) const {
0146 assert(hasCallsite(I) && "Callsite not found");
0147 return Callsites.find(I)->second;
0148 }
0149
0150 CallTargetMapTy &callsite(uint32_t I) {
0151 assert(hasCallsite(I) && "Callsite not found");
0152 return Callsites.find(I)->second;
0153 }
0154
0155
0156
0157
0158 template <class TSetOfGUIDs>
0159 void getContainedGuids(TSetOfGUIDs &Guids) const {
0160 Guids.insert(GUID);
0161 for (const auto &[_, Callsite] : Callsites)
0162 for (const auto &[_, Callee] : Callsite)
0163 Callee.getContainedGuids(Guids);
0164 }
0165 };
0166
0167 class PGOCtxProfileReader final {
0168 StringRef Magic;
0169 BitstreamCursor Cursor;
0170 Expected<BitstreamEntry> advance();
0171 Error readMetadata();
0172 Error wrongValue(const Twine &);
0173 Error unsupported(const Twine &);
0174
0175 Expected<std::pair<std::optional<uint32_t>, PGOCtxProfContext>>
0176 readContext(bool ExpectIndex);
0177 bool canReadContext();
0178
0179 public:
0180 PGOCtxProfileReader(StringRef Buffer)
0181 : Magic(Buffer.substr(0, PGOCtxProfileWriter::ContainerMagic.size())),
0182 Cursor(Buffer.substr(PGOCtxProfileWriter::ContainerMagic.size())) {}
0183
0184 Expected<std::map<GlobalValue::GUID, PGOCtxProfContext>> loadContexts();
0185 };
0186
0187 void convertCtxProfToYaml(raw_ostream &OS,
0188 const PGOCtxProfContext::CallTargetMapTy &);
0189 }
0190 #endif