Skip to content

Commit 96aad6c

Browse files
committed
[ctxprof] Prepare profile format for flat profiles
1 parent a8e4d64 commit 96aad6c

29 files changed

+435
-260
lines changed

compiler-rt/lib/ctx_profile/CtxInstrContextNode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ class ContextNode final {
115115

116116
class ProfileWriter {
117117
public:
118+
virtual void startContextSection() = 0;
118119
virtual void writeContextual(const ctx_profile::ContextNode &RootNode) = 0;
120+
virtual void endContextSection() = 0;
119121
virtual ~ProfileWriter() = default;
120122
};
121123
} // namespace ctx_profile

llvm/include/llvm/Analysis/CtxProfAnalysis.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class PGOContextualProfile {
5454
return Profiles.Contexts;
5555
}
5656

57+
const PGOCtxProfile &profiles() const { return Profiles; }
58+
5759
bool isFunctionKnown(const Function &F) const {
5860
return getDefinedFunctionGUID(F) != 0;
5961
}

llvm/include/llvm/ProfileData/CtxInstrContextNode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ class ContextNode final {
115115

116116
class ProfileWriter {
117117
public:
118+
virtual void startContextSection() = 0;
118119
virtual void writeContextual(const ctx_profile::ContextNode &RootNode) = 0;
120+
virtual void endContextSection() = 0;
119121
virtual ~ProfileWriter() = default;
120122
};
121123
} // namespace ctx_profile

llvm/include/llvm/ProfileData/PGOCtxProfReader.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,12 @@ class PGOCtxProfileReader final {
190190
Error unsupported(const Twine &);
191191

192192
Expected<std::pair<std::optional<uint32_t>, PGOCtxProfContext>>
193-
readContext(bool ExpectIndex);
194-
bool canReadContext();
193+
readProfile(PGOCtxProfileBlockIDs Kind);
194+
195+
bool canEnterBlockWithID(PGOCtxProfileBlockIDs ID);
196+
Error enterBlockWithID(PGOCtxProfileBlockIDs ID);
197+
198+
Error loadContexts(CtxProfContextualProfiles &);
195199

196200
public:
197201
PGOCtxProfileReader(StringRef Buffer)
@@ -201,7 +205,6 @@ class PGOCtxProfileReader final {
201205
Expected<PGOCtxProfile> loadProfiles();
202206
};
203207

204-
void convertCtxProfToYaml(raw_ostream &OS,
205-
const PGOCtxProfContext::CallTargetMapTy &);
208+
void convertCtxProfToYaml(raw_ostream &OS, const PGOCtxProfile &);
206209
} // namespace llvm
207210
#endif

llvm/include/llvm/ProfileData/PGOCtxProfWriter.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ enum PGOCtxProfileRecords { Invalid = 0, Version, Guid, CalleeIndex, Counters };
2323

2424
enum PGOCtxProfileBlockIDs {
2525
ProfileMetadataBlockID = bitc::FIRST_APPLICATION_BLOCKID,
26-
ContextNodeBlockID = ProfileMetadataBlockID + 1
26+
ContextsSectionBlockID = ProfileMetadataBlockID + 1,
27+
ContextRootBlockID = ContextsSectionBlockID + 1,
28+
ContextNodeBlockID = ContextRootBlockID + 1,
2729
};
2830

2931
/// Write one or more ContextNodes to the provided raw_fd_stream.
@@ -60,23 +62,30 @@ enum PGOCtxProfileBlockIDs {
6062
/// like value profiling - which would appear as additional records. For
6163
/// example, value profiling would produce a new record with a new record ID,
6264
/// containing the profiled values (much like the counters)
63-
class PGOCtxProfileWriter final {
65+
class PGOCtxProfileWriter : public ctx_profile::ProfileWriter {
66+
enum class EmptyContextCriteria { None, EntryIsZero, AllAreZero };
67+
6468
BitstreamWriter Writer;
69+
const bool IncludeEmpty;
6570

66-
void writeCounters(const ctx_profile::ContextNode &Node);
71+
void writeGuid(ctx_profile::GUID Guid);
72+
void writeCounters(ArrayRef<uint64_t> Counters);
6773
void writeImpl(std::optional<uint32_t> CallerIndex,
6874
const ctx_profile::ContextNode &Node);
6975

7076
public:
7177
PGOCtxProfileWriter(raw_ostream &Out,
72-
std::optional<unsigned> VersionOverride = std::nullopt);
78+
std::optional<unsigned> VersionOverride = std::nullopt,
79+
bool IncludeEmpty = false);
7380
~PGOCtxProfileWriter() { Writer.ExitBlock(); }
7481

75-
void write(const ctx_profile::ContextNode &);
82+
void startContextSection() override;
83+
void writeContextual(const ctx_profile::ContextNode &RootNode) override;
84+
void endContextSection() override;
7685

7786
// constants used in writing which a reader may find useful.
7887
static constexpr unsigned CodeLen = 2;
79-
static constexpr uint32_t CurrentVersion = 1;
88+
static constexpr uint32_t CurrentVersion = 2;
8089
static constexpr unsigned VBREncodingBits = 6;
8190
static constexpr StringRef ContainerMagic = "CTXP";
8291
};

llvm/lib/Analysis/CtxProfAnalysis.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ PreservedAnalyses CtxProfAnalysisPrinterPass::run(Module &M,
180180

181181
if (Mode == PrintMode::Everything)
182182
OS << "\nCurrent Profile:\n";
183-
convertCtxProfToYaml(OS, C.contexts());
183+
convertCtxProfToYaml(OS, C.profiles());
184184
OS << "\n";
185185
if (Mode == PrintMode::YAML)
186186
return PreservedAnalyses::all();

llvm/lib/ProfileData/PGOCtxProfReader.cpp

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -58,26 +58,34 @@ Error PGOCtxProfileReader::unsupported(const Twine &Msg) {
5858
return make_error<InstrProfError>(instrprof_error::unsupported_version, Msg);
5959
}
6060

61-
bool PGOCtxProfileReader::canReadContext() {
61+
bool PGOCtxProfileReader::canEnterBlockWithID(PGOCtxProfileBlockIDs ID) {
6262
auto Blk = advance();
6363
if (!Blk) {
6464
consumeError(Blk.takeError());
6565
return false;
6666
}
67-
return Blk->Kind == BitstreamEntry::SubBlock &&
68-
Blk->ID == PGOCtxProfileBlockIDs::ContextNodeBlockID;
67+
return Blk->Kind == BitstreamEntry::SubBlock && Blk->ID == ID;
68+
}
69+
70+
Error PGOCtxProfileReader::enterBlockWithID(PGOCtxProfileBlockIDs ID) {
71+
RET_ON_ERR(Cursor.EnterSubBlock(ID));
72+
return Error::success();
6973
}
7074

7175
Expected<std::pair<std::optional<uint32_t>, PGOCtxProfContext>>
72-
PGOCtxProfileReader::readContext(bool ExpectIndex) {
73-
RET_ON_ERR(Cursor.EnterSubBlock(PGOCtxProfileBlockIDs::ContextNodeBlockID));
76+
PGOCtxProfileReader::readProfile(PGOCtxProfileBlockIDs Kind) {
77+
assert((Kind == PGOCtxProfileBlockIDs::ContextRootBlockID ||
78+
Kind == PGOCtxProfileBlockIDs::ContextNodeBlockID) &&
79+
"Unexpected profile kind");
80+
RET_ON_ERR(enterBlockWithID(Kind));
7481

7582
std::optional<ctx_profile::GUID> Guid;
7683
std::optional<SmallVector<uint64_t, 16>> Counters;
7784
std::optional<uint32_t> CallsiteIndex;
7885

7986
SmallVector<uint64_t, 1> RecordValues;
8087

88+
const bool ExpectIndex = Kind == PGOCtxProfileBlockIDs::ContextNodeBlockID;
8189
// We don't prescribe the order in which the records come in, and we are ok
8290
// if other unsupported records appear. We seek in the current subblock until
8391
// we get all we know.
@@ -121,8 +129,8 @@ PGOCtxProfileReader::readContext(bool ExpectIndex) {
121129

122130
PGOCtxProfContext Ret(*Guid, std::move(*Counters));
123131

124-
while (canReadContext()) {
125-
EXPECT_OR_RET(SC, readContext(true));
132+
while (canEnterBlockWithID(PGOCtxProfileBlockIDs::ContextNodeBlockID)) {
133+
EXPECT_OR_RET(SC, readProfile(PGOCtxProfileBlockIDs::ContextNodeBlockID));
126134
auto &Targets = Ret.callsites()[*SC->first];
127135
auto [_, Inserted] =
128136
Targets.insert({SC->second.guid(), std::move(SC->second)});
@@ -168,15 +176,23 @@ Error PGOCtxProfileReader::readMetadata() {
168176
return Error::success();
169177
}
170178

179+
Error PGOCtxProfileReader::loadContexts(CtxProfContextualProfiles &P) {
180+
if (canEnterBlockWithID(PGOCtxProfileBlockIDs::ContextsSectionBlockID)) {
181+
RET_ON_ERR(enterBlockWithID(PGOCtxProfileBlockIDs::ContextsSectionBlockID));
182+
while (canEnterBlockWithID(PGOCtxProfileBlockIDs::ContextRootBlockID)) {
183+
EXPECT_OR_RET(E, readProfile(PGOCtxProfileBlockIDs::ContextRootBlockID));
184+
auto Key = E->second.guid();
185+
if (!P.insert({Key, std::move(E->second)}).second)
186+
return wrongValue("Duplicate roots");
187+
}
188+
}
189+
return Error::success();
190+
}
191+
171192
Expected<PGOCtxProfile> PGOCtxProfileReader::loadProfiles() {
172-
PGOCtxProfile Ret;
173193
RET_ON_ERR(readMetadata());
174-
while (canReadContext()) {
175-
EXPECT_OR_RET(E, readContext(false));
176-
auto Key = E->second.guid();
177-
if (!Ret.Contexts.insert({Key, std::move(E->second)}).second)
178-
return wrongValue("Duplicate roots");
179-
}
194+
PGOCtxProfile Ret;
195+
RET_ON_ERR(loadContexts(Ret.Contexts));
180196
return std::move(Ret);
181197
}
182198

@@ -224,41 +240,54 @@ void toYaml(yaml::Output &Out,
224240
Out.endSequence();
225241
}
226242

227-
void toYaml(yaml::Output &Out, const PGOCtxProfContext &Ctx) {
243+
void toYaml(yaml::Output &Out, GlobalValue::GUID Guid,
244+
const SmallVectorImpl<uint64_t> &Counters,
245+
const PGOCtxProfContext::CallsiteMapTy &Callsites) {
228246
yaml::EmptyContext Empty;
229247
Out.beginMapping();
230248
void *SaveInfo = nullptr;
231249
bool UseDefault = false;
232250
{
233251
Out.preflightKey("Guid", /*Required=*/true, /*SameAsDefault=*/false,
234252
UseDefault, SaveInfo);
235-
auto Guid = Ctx.guid();
236253
yaml::yamlize(Out, Guid, true, Empty);
237254
Out.postflightKey(nullptr);
238255
}
239256
{
240257
Out.preflightKey("Counters", true, false, UseDefault, SaveInfo);
241258
Out.beginFlowSequence();
242-
for (size_t I = 0U, E = Ctx.counters().size(); I < E; ++I) {
259+
for (size_t I = 0U, E = Counters.size(); I < E; ++I) {
243260
Out.preflightFlowElement(I, SaveInfo);
244-
uint64_t V = Ctx.counters()[I];
261+
uint64_t V = Counters[I];
245262
yaml::yamlize(Out, V, true, Empty);
246263
Out.postflightFlowElement(SaveInfo);
247264
}
248265
Out.endFlowSequence();
249266
Out.postflightKey(nullptr);
250267
}
251-
if (!Ctx.callsites().empty()) {
268+
if (!Callsites.empty()) {
252269
Out.preflightKey("Callsites", true, false, UseDefault, SaveInfo);
253-
toYaml(Out, Ctx.callsites());
270+
toYaml(Out, Callsites);
254271
Out.postflightKey(nullptr);
255272
}
256273
Out.endMapping();
257274
}
275+
void toYaml(yaml::Output &Out, const PGOCtxProfContext &Ctx) {
276+
toYaml(Out, Ctx.guid(), Ctx.counters(), Ctx.callsites());
277+
}
278+
258279
} // namespace
259280

260-
void llvm::convertCtxProfToYaml(
261-
raw_ostream &OS, const PGOCtxProfContext::CallTargetMapTy &Profiles) {
281+
void llvm::convertCtxProfToYaml(raw_ostream &OS,
282+
const PGOCtxProfile &Profiles) {
262283
yaml::Output Out(OS);
263-
toYaml(Out, Profiles);
264-
}
284+
void *SaveInfo = nullptr;
285+
bool UseDefault = false;
286+
Out.beginMapping();
287+
if (!Profiles.Contexts.empty()) {
288+
Out.preflightKey("Contexts", false, false, UseDefault, SaveInfo);
289+
toYaml(Out, Profiles.Contexts);
290+
Out.postflightKey(nullptr);
291+
}
292+
Out.endMapping();
293+
}

0 commit comments

Comments
 (0)