LLVM: lib/ProfileData/PGOCtxProfReader.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
22#include
23
24using namespace llvm;
25
26
27
28#define EXPECT_OR_RET(LHS, RHS) \
29 auto LHS = RHS; \
30 if (!LHS) \
31 return LHS.takeError();
32
33#define RET_ON_ERR(EXPR) \
34 if (auto Err = (EXPR)) \
35 return Err;
36
40 auto [Iter, Inserted] =
42 if (!Inserted)
44 "Duplicate GUID for same callsite.");
45 return Iter->second;
46}
47
50}
51
52Error PGOCtxProfileReader::wrongValue(const Twine &Msg) {
54}
55
56Error PGOCtxProfileReader::unsupported(const Twine &Msg) {
58}
59
61 auto Blk = advance();
62 if (!Blk) {
64 return false;
65 }
67 return false;
70 return false;
72 return true;
73}
74
77 return tryGetNextKnownBlockID(Test) && Test == ID;
78}
79
83}
84
85
86
87
93 "Unexpected profile kind");
95
96 std::optional<ctx_profile::GUID> Guid;
97 std::optional<SmallVector<uint64_t, 16>> Counters;
99 std::optional<uint64_t> TotalEntryCount;
100 std::optional Unhandled;
101 SmallVector<uint64_t, 1> RecordValues;
102
105
106
107
108 auto GotAllWeNeed = [&]() {
109 return Guid.has_value() && Counters.has_value() &&
111 ( || TotalEntryCount.has_value()) &&
112 ( || Unhandled.has_value());
113 };
114
115 while (!GotAllWeNeed()) {
116 RecordValues.clear();
123 RET_ON_ERR(loadFlatProfileList(*Unhandled));
124 continue;
125 }
126 return wrongValue(
127 "Expected records before encountering more subcontexts");
128 }
131 switch (*ReadRecord) {
133 if (RecordValues.size() != 1)
134 return wrongValue("The GUID record should have exactly one value");
135 Guid = RecordValues[0];
136 break;
138 Counters = std::move(RecordValues);
140 return wrongValue("Empty counters. At least the entry counter (one "
141 "value) was expected");
142 break;
144 if (!ExpectIndex)
145 return wrongValue("The root context should not have a callee index");
146 if (RecordValues.size() != 1)
147 return wrongValue("The callee index should have exactly one value");
149 break;
151 if (!IsRoot)
152 return wrongValue("Non-root has a total entry count record");
153 if (RecordValues.size() != 1)
154 return wrongValue(
155 "The root total entry count record should have exactly one value");
156 TotalEntryCount = RecordValues[0];
157 break;
158 default:
159
160
161 break;
162 }
163 }
164
165 PGOCtxProfContext Ret(*Guid, std::move(*Counters), TotalEntryCount,
166 std::move(Unhandled));
167
170 auto &Targets = Ret.callsites()[*SC->first];
172 Targets.insert({SC->second.guid(), std::move(SC->second)});
173 if (!Inserted)
174 return wrongValue(
175 "Unexpected duplicate target (callee) at the same callsite.");
176 }
177 return std::make_pair(CallsiteIndex, std::move(Ret));
178}
179
180Error PGOCtxProfileReader::readMetadata() {
184 "Invalid magic");
185
186 BitstreamEntry Entry;
187 RET_ON_ERR(Cursor.advance().moveInto(Entry));
190 return unsupported("Expected Block ID");
191
192
194
197 return unsupported("Expected Version record");
202 return unsupported("Expected Version record");
203
204 SmallVector<uint64_t, 1> Ver;
206 if (*Code != PGOCtxProfileRecords::Version)
207 return unsupported("Expected Version record");
209 return unsupported("Version " + Twine(*Code) +
210 " is higher than supported version " +
213}
214
219 auto Key = E->second.guid();
220 if (.insert({Key, std::move(E->second)}).second)
221 return wrongValue("Duplicate roots");
222 }
224}
225
229 auto Guid = E->second.guid();
230 if (.insert({Guid, std::move(E->second.counters())}).second)
231 return wrongValue("Duplicate flat profile entries");
232 }
234}
235
239 return loadFlatProfileList(P);
240}
241
246 for (auto I = 0; I < 2; ++I) {
247 if (!tryGetNextKnownBlockID(Test))
248 break;
253 } else {
254 return wrongValue("Unexpected section");
255 }
256 }
257
258 return std::move(Ret);
259}
260
261namespace {
262
263
264
265
266
268
272 size_t Index = 0;
273 void *SaveData = nullptr;
274 for (const auto &[_, Ctx] : CallTargets) {
276 toYaml(Out, Ctx);
278 }
280}
281
286 assert(MaxIt != AllCS.end() && "We should have a max value because the "
287 "callsites collection is not empty.");
288 void *SaveData = nullptr;
290 for (auto I = 0U; I <= *MaxIt; ++I) {
292 auto It = Callsites.find(I);
293 if (It == Callsites.end()) {
294
297 } else {
298 toYaml(Out, It->second);
299 }
301 }
303}
304
306
314 void *SaveInfo = nullptr;
315 bool UseDefault = false;
316 {
317 Out.preflightKey("Guid", true, false,
318 UseDefault, SaveInfo);
321 }
323 Out.preflightKey("TotalRootEntryCount", true, false, UseDefault, SaveInfo);
326 }
327 {
328 Out.preflightKey("Counters", true, false, UseDefault, SaveInfo);
330 for (size_t I = 0U, E = Counters.size(); I < E; ++I) {
335 }
338 }
339
340 if (!Unhandled.empty()) {
342 Out.preflightKey("Unhandled", false, false, UseDefault, SaveInfo);
343 toYaml(Out, Unhandled);
345 }
346
347 if (!Callsites.empty()) {
348 Out.preflightKey("Callsites", true, false, UseDefault, SaveInfo);
349 toYaml(Out, Callsites);
351 }
353}
354
356 void *SaveInfo = nullptr;
358 size_t ElemID = 0;
363 }
365}
366
371 else
373}
374
375}
376
379 void *SaveInfo = nullptr;
380 bool UseDefault = false;
382 if (.Contexts.empty()) {
383 Out.preflightKey("Contexts", false, false, UseDefault, SaveInfo);
384 toYaml(Out, Profile.Contexts);
386 }
387 if (.FlatProfiles.empty()) {
388 Out.preflightKey("FlatProfiles", false, false, UseDefault, SaveInfo);
389 toYaml(Out, Profile.FlatProfiles);
391 }
393}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define RET_ON_ERR(EXPR)
Definition PGOCtxProfReader.cpp:33
#define EXPECT_OR_RET(LHS, RHS)
Definition PGOCtxProfReader.cpp:28
Reader for contextual iFDO profile, which comes in bitstream format.
LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty
@ AF_DontAutoprocessAbbrevs
If this flag is used, abbrev entries are returned just like normal records.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
uint64_t GUID
Declare a type to represent a global unique identifier for a global value.
A node (context) in the loaded contextual profile, suitable for mutation during IPO passes.
GlobalValue::GUID guid() const
const SmallVectorImpl< uint64_t > & counters() const
std::map< uint32_t, CallTargetMapTy > CallsiteMapTy
const CtxProfFlatProfile & getUnhandled() const
uint64_t getTotalRootEntryCount() const
std::map< GlobalValue::GUID, PGOCtxProfContext > CallTargetMapTy
const CallsiteMapTy & callsites() const
LLVM_ABI Expected< PGOCtxProfile > loadProfiles()
Definition PGOCtxProfReader.cpp:242
static constexpr uint32_t CurrentVersion
static constexpr StringRef ContainerMagic
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
constexpr size_t size() const
size - Get the string size.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
friend class ::llvm::PGOCtxProfContext
This class implements an extremely fast bulk output stream that can only output to a stream.
The Output class is used to generate a yaml document from in-memory structs and vectors.
unsigned beginFlowSequence() override
void endFlowSequence() override
void postflightElement(void *) override
void beginMapping() override
void postflightFlowElement(void *) override
bool preflightElement(unsigned, void *&) override
bool preflightKey(StringRef Key, bool, bool, bool &, void *&) override
void endSequence() override
unsigned beginSequence() override
void endMapping() override
void postflightKey(void *) override
bool preflightFlowElement(unsigned, void *&) override
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ BLOCKINFO_BLOCK_ID
BLOCKINFO_BLOCK is used to define metadata about blocks, for example, standard abbrevs that should be...
std::enable_if_t< has_ScalarEnumerationTraits< T >::value, void > yamlize(IO &io, T &Val, bool, EmptyContext &Ctx)
This is an optimization pass for GlobalISel generic memory operations.
std::map< GlobalValue::GUID, SmallVector< uint64_t, 1 > > CtxProfFlatProfile
std::map< GlobalValue::GUID, PGOCtxProfContext > CtxProfContextualProfiles
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
auto max_element(R &&Range)
Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...
LLVM_ABI void convertCtxProfToYaml(raw_ostream &OS, const PGOCtxProfile &Profile)
Definition PGOCtxProfReader.cpp:377
void consumeError(Error Err)
Consume a Error without doing anything.
@ FlatProfilesSectionBlockID
CtxProfFlatProfile FlatProfiles
CtxProfContextualProfiles Contexts