28#define EXPECT_OR_RET(LHS, RHS) \
31 return LHS.takeError();
33#define RET_ON_ERR(EXPR) \
34 if (auto Err = (EXPR)) \
40 auto [Iter, Inserted] =
44 "Duplicate GUID for same callsite.");
52Error PGOCtxProfileReader::wrongValue(
const Twine &Msg) {
56Error PGOCtxProfileReader::unsupported(
const Twine &Msg) {
77 return tryGetNextKnownBlockID(
Test) &&
Test ==
ID;
93 "Unexpected profile kind");
96 std::optional<ctx_profile::GUID>
Guid;
97 std::optional<SmallVector<uint64_t, 16>>
Counters;
99 std::optional<uint64_t> TotalEntryCount;
100 std::optional<CtxProfFlatProfile> Unhandled;
101 SmallVector<uint64_t, 1> RecordValues;
108 auto GotAllWeNeed = [&]() {
111 (!
IsRoot || TotalEntryCount.has_value()) &&
112 (!
IsRoot || Unhandled.has_value());
115 while (!GotAllWeNeed()) {
116 RecordValues.
clear();
127 "Expected records before encountering more subcontexts");
131 switch (*ReadRecord) {
133 if (RecordValues.
size() != 1)
134 return wrongValue(
"The GUID record should have exactly one value");
135 Guid = RecordValues[0];
140 return wrongValue(
"Empty counters. At least the entry counter (one "
141 "value) was expected");
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");
152 return wrongValue(
"Non-root has a total entry count record");
153 if (RecordValues.
size() != 1)
155 "The root total entry count record should have exactly one value");
156 TotalEntryCount = RecordValues[0];
166 std::move(Unhandled));
170 auto &Targets =
Ret.callsites()[*SC->first];
172 Targets.insert({SC->second.guid(), std::move(SC->second)});
175 "Unexpected duplicate target (callee) at the same callsite.");
180Error PGOCtxProfileReader::readMetadata() {
186 BitstreamEntry
Entry;
190 return unsupported(
"Expected Block ID");
197 return unsupported(
"Expected Version record");
202 return unsupported(
"Expected Version record");
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 " +
219 auto Key =
E->second.guid();
220 if (!
P.insert({Key, std::move(E->second)}).second)
221 return wrongValue(
"Duplicate roots");
229 auto Guid =
E->second.guid();
230 if (!
P.insert({Guid, std::move(E->second.counters())}).second)
231 return wrongValue(
"Duplicate flat profile entries");
239 return loadFlatProfileList(
P);
246 for (
auto I = 0;
I < 2; ++
I) {
247 if (!tryGetNextKnownBlockID(
Test))
252 RET_ON_ERR(loadFlatProfiles(Ret.FlatProfiles));
254 return wrongValue(
"Unexpected section");
258 return std::move(Ret);
273 void *SaveData =
nullptr;
274 for (
const auto &[
_, Ctx] : CallTargets) {
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()) {
298 toYaml(Out, It->second);
314 void *SaveInfo =
nullptr;
315 bool UseDefault =
false;
318 UseDefault, SaveInfo);
323 Out.
preflightKey(
"TotalRootEntryCount",
true,
false, UseDefault, SaveInfo);
328 Out.
preflightKey(
"Counters",
true,
false, UseDefault, SaveInfo);
340 if (!Unhandled.empty()) {
342 Out.
preflightKey(
"Unhandled",
false,
false, UseDefault, SaveInfo);
343 toYaml(Out, Unhandled);
347 if (!Callsites.empty()) {
348 Out.
preflightKey(
"Callsites",
true,
false, UseDefault, SaveInfo);
349 toYaml(Out, Callsites);
356 void *SaveInfo =
nullptr;
379 void *SaveInfo =
nullptr;
380 bool UseDefault =
false;
382 if (!
Profile.Contexts.empty()) {
383 Out.
preflightKey(
"Contexts",
false,
false, UseDefault, SaveInfo);
387 if (!
Profile.FlatProfiles.empty()) {
388 Out.
preflightKey(
"FlatProfiles",
false,
false, UseDefault, SaveInfo);
389 toYaml(Out,
Profile.FlatProfiles);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define EXPECT_OR_RET(LHS, RHS)
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()
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
bool preflightKey(const char *key, bool, bool, bool &, void *&) override
void postflightFlowElement(void *) override
bool preflightElement(unsigned, 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)
void consumeError(Error Err)
Consume a Error without doing anything.
@ FlatProfilesSectionBlockID