Skip to content

Commit 7278206

Browse files
committed
[ctxprof] Prepare profile format for flat profiles
1 parent 3e303bf commit 7278206

File tree

15 files changed

+187
-107
lines changed

15 files changed

+187
-107
lines changed

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/PGOCtxProfReader.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ using CtxProfContextualProfiles =
174174
std::map<GlobalValue::GUID, PGOCtxProfContext>;
175175
struct PGOCtxProfile {
176176
CtxProfContextualProfiles Contexts;
177+
CtxProfFlatProfile FlatProfiles;
177178

178179
PGOCtxProfile() = default;
179180
PGOCtxProfile(const PGOCtxProfile &) = delete;
@@ -190,8 +191,12 @@ class PGOCtxProfileReader final {
190191
Error unsupported(const Twine &);
191192

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

196201
public:
197202
PGOCtxProfileReader(StringRef Buffer)
@@ -201,7 +206,6 @@ class PGOCtxProfileReader final {
201206
Expected<PGOCtxProfile> loadProfiles();
202207
};
203208

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

llvm/include/llvm/ProfileData/PGOCtxProfWriter.h

Lines changed: 12 additions & 5 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,10 +62,13 @@ 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;
6569

66-
void writeCounters(const ctx_profile::ContextNode &Node);
70+
void writeGuid(ctx_profile::GUID Guid);
71+
void writeCounters(ArrayRef<uint64_t> Counters);
6772
void writeImpl(std::optional<uint32_t> CallerIndex,
6873
const ctx_profile::ContextNode &Node);
6974

@@ -72,11 +77,13 @@ class PGOCtxProfileWriter final {
7277
std::optional<unsigned> VersionOverride = std::nullopt);
7378
~PGOCtxProfileWriter() { Writer.ExitBlock(); }
7479

75-
void write(const ctx_profile::ContextNode &);
80+
void startContextSection() override;
81+
void writeContextual(const ctx_profile::ContextNode &RootNode) override;
82+
void endContextSection() override;
7683

7784
// constants used in writing which a reader may find useful.
7885
static constexpr unsigned CodeLen = 2;
79-
static constexpr uint32_t CurrentVersion = 1;
86+
static constexpr uint32_t CurrentVersion = 2;
8087
static constexpr unsigned VBREncodingBits = 6;
8188
static constexpr StringRef ContainerMagic = "CTXP";
8289
};

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: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -58,26 +58,33 @@ 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+
Error PGOCtxProfileReader::enterBlockWithID(PGOCtxProfileBlockIDs ID) {
70+
RET_ON_ERR(Cursor.EnterSubBlock(ID));
71+
return Error::success();
6972
}
7073

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

7581
std::optional<ctx_profile::GUID> Guid;
7682
std::optional<SmallVector<uint64_t, 16>> Counters;
7783
std::optional<uint32_t> CallsiteIndex;
7884

7985
SmallVector<uint64_t, 1> RecordValues;
8086

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

122129
PGOCtxProfContext Ret(*Guid, std::move(*Counters));
123130

124-
while (canReadContext()) {
125-
EXPECT_OR_RET(SC, readContext(true));
131+
while (canEnterBlockWithID(PGOCtxProfileBlockIDs::ContextNodeBlockID)) {
132+
EXPECT_OR_RET(SC, readProfile(PGOCtxProfileBlockIDs::ContextNodeBlockID));
126133
auto &Targets = Ret.callsites()[*SC->first];
127134
auto [_, Inserted] =
128135
Targets.insert({SC->second.guid(), std::move(SC->second)});
@@ -168,15 +175,23 @@ Error PGOCtxProfileReader::readMetadata() {
168175
return Error::success();
169176
}
170177

178+
Error PGOCtxProfileReader::loadContexts(CtxProfContextualProfiles &P) {
179+
if (canEnterBlockWithID(PGOCtxProfileBlockIDs::ContextsSectionBlockID)) {
180+
RET_ON_ERR(enterBlockWithID(PGOCtxProfileBlockIDs::ContextsSectionBlockID));
181+
while (canEnterBlockWithID(PGOCtxProfileBlockIDs::ContextRootBlockID)) {
182+
EXPECT_OR_RET(E, readProfile(PGOCtxProfileBlockIDs::ContextRootBlockID));
183+
auto Key = E->second.guid();
184+
if (!P.insert({Key, std::move(E->second)}).second)
185+
return wrongValue("Duplicate roots");
186+
}
187+
}
188+
return Error::success();
189+
}
190+
171191
Expected<PGOCtxProfile> PGOCtxProfileReader::loadProfiles() {
172-
PGOCtxProfile Ret;
173192
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-
}
193+
PGOCtxProfile Ret;
194+
RET_ON_ERR(loadContexts(Ret.Contexts));
180195
return std::move(Ret);
181196
}
182197

@@ -224,41 +239,54 @@ void toYaml(yaml::Output &Out,
224239
Out.endSequence();
225240
}
226241

227-
void toYaml(yaml::Output &Out, const PGOCtxProfContext &Ctx) {
242+
void toYaml(yaml::Output &Out, GlobalValue::GUID Guid,
243+
const SmallVectorImpl<uint64_t> &Counters,
244+
const PGOCtxProfContext::CallsiteMapTy &Callsites) {
228245
yaml::EmptyContext Empty;
229246
Out.beginMapping();
230247
void *SaveInfo = nullptr;
231248
bool UseDefault = false;
232249
{
233250
Out.preflightKey("Guid", /*Required=*/true, /*SameAsDefault=*/false,
234251
UseDefault, SaveInfo);
235-
auto Guid = Ctx.guid();
236252
yaml::yamlize(Out, Guid, true, Empty);
237253
Out.postflightKey(nullptr);
238254
}
239255
{
240256
Out.preflightKey("Counters", true, false, UseDefault, SaveInfo);
241257
Out.beginFlowSequence();
242-
for (size_t I = 0U, E = Ctx.counters().size(); I < E; ++I) {
258+
for (size_t I = 0U, E = Counters.size(); I < E; ++I) {
243259
Out.preflightFlowElement(I, SaveInfo);
244-
uint64_t V = Ctx.counters()[I];
260+
uint64_t V = Counters[I];
245261
yaml::yamlize(Out, V, true, Empty);
246262
Out.postflightFlowElement(SaveInfo);
247263
}
248264
Out.endFlowSequence();
249265
Out.postflightKey(nullptr);
250266
}
251-
if (!Ctx.callsites().empty()) {
267+
if (!Callsites.empty()) {
252268
Out.preflightKey("Callsites", true, false, UseDefault, SaveInfo);
253-
toYaml(Out, Ctx.callsites());
269+
toYaml(Out, Callsites);
254270
Out.postflightKey(nullptr);
255271
}
256272
Out.endMapping();
257273
}
274+
void toYaml(yaml::Output &Out, const PGOCtxProfContext &Ctx) {
275+
toYaml(Out, Ctx.guid(), Ctx.counters(), Ctx.callsites());
276+
}
277+
258278
} // namespace
259279

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

llvm/lib/ProfileData/PGOCtxProfWriter.cpp

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,19 @@
1313
#include "llvm/ProfileData/PGOCtxProfWriter.h"
1414
#include "llvm/Bitstream/BitCodeEnums.h"
1515
#include "llvm/ProfileData/CtxInstrContextNode.h"
16+
#include "llvm/Support/CommandLine.h"
1617
#include "llvm/Support/Error.h"
17-
#include "llvm/Support/MemoryBuffer.h"
1818
#include "llvm/Support/YAMLTraits.h"
1919
#include "llvm/Support/raw_ostream.h"
2020

2121
using namespace llvm;
2222
using namespace llvm::ctx_profile;
2323

24+
static cl::opt<bool> IncludeEmpty(
25+
"ctx-prof-include-empty", cl::init(false),
26+
cl::desc(
27+
"Also write profiles with all-zero counters. Mostly for debugging."));
28+
2429
PGOCtxProfileWriter::PGOCtxProfileWriter(
2530
raw_ostream &Out, std::optional<unsigned> VersionOverride)
2631
: Writer(Out, 0) {
@@ -44,9 +49,11 @@ PGOCtxProfileWriter::PGOCtxProfileWriter(
4449
DescribeBlock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID, "Metadata");
4550
DescribeRecord(PGOCtxProfileRecords::Version, "Version");
4651
DescribeBlock(PGOCtxProfileBlockIDs::ContextNodeBlockID, "Context");
52+
DescribeBlock(PGOCtxProfileBlockIDs::ContextRootBlockID, "Root");
4753
DescribeRecord(PGOCtxProfileRecords::Guid, "GUID");
4854
DescribeRecord(PGOCtxProfileRecords::CalleeIndex, "CalleeIndex");
4955
DescribeRecord(PGOCtxProfileRecords::Counters, "Counters");
56+
DescribeBlock(PGOCtxProfileBlockIDs::ContextsSectionBlockID, "Contexts");
5057
}
5158
Writer.ExitBlock();
5259
Writer.EnterSubblock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID, CodeLen);
@@ -55,12 +62,16 @@ PGOCtxProfileWriter::PGOCtxProfileWriter(
5562
SmallVector<unsigned, 1>({Version}));
5663
}
5764

58-
void PGOCtxProfileWriter::writeCounters(const ContextNode &Node) {
65+
void PGOCtxProfileWriter::writeCounters(ArrayRef<uint64_t> Counters) {
5966
Writer.EmitCode(bitc::UNABBREV_RECORD);
6067
Writer.EmitVBR(PGOCtxProfileRecords::Counters, VBREncodingBits);
61-
Writer.EmitVBR(Node.counters_size(), VBREncodingBits);
62-
for (uint32_t I = 0U; I < Node.counters_size(); ++I)
63-
Writer.EmitVBR64(Node.counters()[I], VBREncodingBits);
68+
Writer.EmitVBR(Counters.size(), VBREncodingBits);
69+
for (uint32_t I = 0U; I < Counters.size(); ++I)
70+
Writer.EmitVBR64(Counters[I], VBREncodingBits);
71+
}
72+
73+
void PGOCtxProfileWriter::writeGuid(ctx_profile::GUID Guid) {
74+
Writer.EmitRecord(PGOCtxProfileRecords::Guid, SmallVector<uint64_t, 1>{Guid});
6475
}
6576

6677
// recursively write all the subcontexts. We do need to traverse depth first to
@@ -69,21 +80,30 @@ void PGOCtxProfileWriter::writeCounters(const ContextNode &Node) {
6980
// keep the implementation simple.
7081
void PGOCtxProfileWriter::writeImpl(std::optional<uint32_t> CallerIndex,
7182
const ContextNode &Node) {
72-
Writer.EnterSubblock(PGOCtxProfileBlockIDs::ContextNodeBlockID, CodeLen);
73-
Writer.EmitRecord(PGOCtxProfileRecords::Guid,
74-
SmallVector<uint64_t, 1>{Node.guid()});
83+
if (!IncludeEmpty && Node.entrycount() == 0)
84+
return;
85+
Writer.EnterSubblock(CallerIndex ? PGOCtxProfileBlockIDs::ContextNodeBlockID
86+
: PGOCtxProfileBlockIDs::ContextRootBlockID,
87+
CodeLen);
88+
writeGuid(Node.guid());
7589
if (CallerIndex)
7690
Writer.EmitRecord(PGOCtxProfileRecords::CalleeIndex,
7791
SmallVector<uint64_t, 1>{*CallerIndex});
78-
writeCounters(Node);
92+
writeCounters({Node.counters(), Node.counters_size()});
7993
for (uint32_t I = 0U; I < Node.callsites_size(); ++I)
8094
for (const auto *Subcontext = Node.subContexts()[I]; Subcontext;
8195
Subcontext = Subcontext->next())
8296
writeImpl(I, *Subcontext);
8397
Writer.ExitBlock();
8498
}
8599

86-
void PGOCtxProfileWriter::write(const ContextNode &RootNode) {
100+
void PGOCtxProfileWriter::startContextSection() {
101+
Writer.EnterSubblock(PGOCtxProfileBlockIDs::ContextsSectionBlockID, CodeLen);
102+
}
103+
104+
void PGOCtxProfileWriter::endContextSection() { Writer.ExitBlock(); }
105+
106+
void PGOCtxProfileWriter::writeContextual(const ContextNode &RootNode) {
87107
writeImpl(std::nullopt, RootNode);
88108
}
89109

@@ -96,6 +116,9 @@ struct SerializableCtxRepresentation {
96116
std::vector<uint64_t> Counters;
97117
std::vector<std::vector<SerializableCtxRepresentation>> Callsites;
98118
};
119+
struct SerializableProfileRepresentation {
120+
std::vector<SerializableCtxRepresentation> Contexts;
121+
};
99122

100123
ctx_profile::ContextNode *
101124
createNode(std::vector<std::unique_ptr<char[]>> &Nodes,
@@ -142,23 +165,34 @@ template <> struct yaml::MappingTraits<SerializableCtxRepresentation> {
142165
}
143166
};
144167

168+
template <> struct yaml::MappingTraits<SerializableProfileRepresentation> {
169+
static void mapping(yaml::IO &IO, SerializableProfileRepresentation &SPR) {
170+
IO.mapOptional("Contexts", SPR.Contexts);
171+
}
172+
};
173+
145174
Error llvm::createCtxProfFromYAML(StringRef Profile, raw_ostream &Out) {
146175
yaml::Input In(Profile);
147-
std::vector<SerializableCtxRepresentation> DCList;
148-
In >> DCList;
176+
SerializableProfileRepresentation SPR;
177+
In >> SPR;
149178
if (In.error())
150179
return createStringError(In.error(), "incorrect yaml content");
151180
std::vector<std::unique_ptr<char[]>> Nodes;
152181
std::error_code EC;
153182
if (EC)
154183
return createStringError(EC, "failed to open output");
155184
PGOCtxProfileWriter Writer(Out);
156-
for (const auto &DC : DCList) {
157-
auto *TopList = createNode(Nodes, DC);
158-
if (!TopList)
159-
return createStringError(
160-
"Unexpected error converting internal structure to ctx profile");
161-
Writer.write(*TopList);
185+
186+
if (!SPR.Contexts.empty()) {
187+
Writer.startContextSection();
188+
for (const auto &DC : SPR.Contexts) {
189+
auto *TopList = createNode(Nodes, DC);
190+
if (!TopList)
191+
return createStringError(
192+
"Unexpected error converting internal structure to ctx profile");
193+
Writer.writeContextual(*TopList);
194+
}
195+
Writer.endContextSection();
162196
}
163197
if (EC)
164198
return createStringError(EC, "failed to write output");
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
- Guid: 123
2-
Counters: [1, 2]
3-
Callsites: - Guid: 1
1+
Contexts:
2+
- Guid: 123
3+
Counters: [1, 2]
4+
Callsites: - Guid: 1
45

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
- Guid: 1231
1+
Contexts:
2+
- Guid: 1231
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Guid: 1

llvm/test/tools/llvm-ctxprof-util/Inputs/invalid-no-vector.yaml

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)