Skip to content

Commit cc7308a

Browse files
authored
[ctx_prof] Make the profile output analyzable by llvm-bcanalyzer (#99563)
This requires output-ing a "Magic" 4-byte header. We also emit a block info block, to describe our blocks and records. The output of `llvm-bcanalyzer` would look like: ``` <BLOCKINFO_BLOCK/> <Metadata NumWords=17 BlockCodeSize=2> <Version op0=1/> <Context NumWords=13 BlockCodeSize=2> <GUID op0=2/> <Counters op0=1 op1=2 op2=3/> ``` Instead of having `Unknown` for block and record IDs.
1 parent 1ee686a commit cc7308a

File tree

5 files changed

+81
-28
lines changed

5 files changed

+81
-28
lines changed

llvm/include/llvm/ProfileData/PGOCtxProfReader.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ class PGOContextualProfile final {
7373
};
7474

7575
class PGOCtxProfileReader final {
76-
BitstreamCursor &Cursor;
76+
StringRef Magic;
77+
BitstreamCursor Cursor;
7778
Expected<BitstreamEntry> advance();
7879
Error readMetadata();
7980
Error wrongValue(const Twine &);
@@ -84,7 +85,9 @@ class PGOCtxProfileReader final {
8485
bool canReadContext();
8586

8687
public:
87-
PGOCtxProfileReader(BitstreamCursor &Cursor) : Cursor(Cursor) {}
88+
PGOCtxProfileReader(StringRef Buffer)
89+
: Magic(Buffer.substr(0, PGOCtxProfileWriter::ContainerMagic.size())),
90+
Cursor(Buffer.substr(PGOCtxProfileWriter::ContainerMagic.size())) {}
8891

8992
Expected<std::map<GlobalValue::GUID, PGOContextualProfile>> loadContexts();
9093
};

llvm/include/llvm/ProfileData/PGOCtxProfWriter.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_
1414
#define LLVM_PROFILEDATA_PGOCTXPROFWRITER_H_
1515

16+
#include "llvm/ADT/StringExtras.h"
1617
#include "llvm/Bitstream/BitCodeEnums.h"
1718
#include "llvm/Bitstream/BitstreamWriter.h"
1819
#include "llvm/ProfileData/CtxInstrContextNode.h"
@@ -68,15 +69,7 @@ class PGOCtxProfileWriter final {
6869

6970
public:
7071
PGOCtxProfileWriter(raw_ostream &Out,
71-
std::optional<unsigned> VersionOverride = std::nullopt)
72-
: Writer(Out, 0) {
73-
Writer.EnterSubblock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID,
74-
CodeLen);
75-
const auto Version = VersionOverride ? *VersionOverride : CurrentVersion;
76-
Writer.EmitRecord(PGOCtxProfileRecords::Version,
77-
SmallVector<unsigned, 1>({Version}));
78-
}
79-
72+
std::optional<unsigned> VersionOverride = std::nullopt);
8073
~PGOCtxProfileWriter() { Writer.ExitBlock(); }
8174

8275
void write(const ctx_profile::ContextNode &);
@@ -85,6 +78,7 @@ class PGOCtxProfileWriter final {
8578
static constexpr unsigned CodeLen = 2;
8679
static constexpr uint32_t CurrentVersion = 1;
8780
static constexpr unsigned VBREncodingBits = 6;
81+
static constexpr StringRef ContainerMagic = "CTXP";
8882
};
8983

9084
} // namespace llvm

llvm/lib/ProfileData/PGOCtxProfReader.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "llvm/ProfileData/PGOCtxProfReader.h"
15+
#include "llvm/ADT/StringExtras.h"
1516
#include "llvm/Bitstream/BitCodeEnums.h"
1617
#include "llvm/Bitstream/BitstreamReader.h"
1718
#include "llvm/ProfileData/InstrProf.h"
@@ -139,6 +140,20 @@ PGOCtxProfileReader::readContext(bool ExpectIndex) {
139140
}
140141

141142
Error PGOCtxProfileReader::readMetadata() {
143+
if (Magic.size() < PGOCtxProfileWriter::ContainerMagic.size() ||
144+
Magic != PGOCtxProfileWriter::ContainerMagic)
145+
return make_error<InstrProfError>(instrprof_error::invalid_prof,
146+
"Invalid magic");
147+
148+
BitstreamEntry Entry;
149+
RET_ON_ERR(Cursor.advance().moveInto(Entry));
150+
if (Entry.Kind != BitstreamEntry::SubBlock ||
151+
Entry.ID != bitc::BLOCKINFO_BLOCK_ID)
152+
return unsupported("Expected Block ID");
153+
// We don't need the blockinfo to read the rest, it's metadata usable for e.g.
154+
// llvm-bcanalyzer.
155+
RET_ON_ERR(Cursor.SkipBlock());
156+
142157
EXPECT_OR_RET(Blk, advance());
143158
if (Blk->Kind != BitstreamEntry::SubBlock)
144159
return unsupported("Expected Version record");

llvm/lib/ProfileData/PGOCtxProfWriter.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,40 @@
1616
using namespace llvm;
1717
using namespace llvm::ctx_profile;
1818

19+
PGOCtxProfileWriter::PGOCtxProfileWriter(
20+
raw_ostream &Out, std::optional<unsigned> VersionOverride)
21+
: Writer(Out, 0) {
22+
static_assert(ContainerMagic.size() == 4);
23+
Out.write(ContainerMagic.data(), ContainerMagic.size());
24+
Writer.EnterBlockInfoBlock();
25+
{
26+
auto DescribeBlock = [&](unsigned ID, StringRef Name) {
27+
Writer.EmitRecord(bitc::BLOCKINFO_CODE_SETBID,
28+
SmallVector<unsigned, 1>{ID});
29+
Writer.EmitRecord(bitc::BLOCKINFO_CODE_BLOCKNAME,
30+
llvm::arrayRefFromStringRef(Name));
31+
};
32+
SmallVector<uint64_t, 16> Data;
33+
auto DescribeRecord = [&](unsigned RecordID, StringRef Name) {
34+
Data.clear();
35+
Data.push_back(RecordID);
36+
llvm::append_range(Data, Name);
37+
Writer.EmitRecord(bitc::BLOCKINFO_CODE_SETRECORDNAME, Data);
38+
};
39+
DescribeBlock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID, "Metadata");
40+
DescribeRecord(PGOCtxProfileRecords::Version, "Version");
41+
DescribeBlock(PGOCtxProfileBlockIDs::ContextNodeBlockID, "Context");
42+
DescribeRecord(PGOCtxProfileRecords::Guid, "GUID");
43+
DescribeRecord(PGOCtxProfileRecords::CalleeIndex, "CalleeIndex");
44+
DescribeRecord(PGOCtxProfileRecords::Counters, "Counters");
45+
}
46+
Writer.ExitBlock();
47+
Writer.EnterSubblock(PGOCtxProfileBlockIDs::ProfileMetadataBlockID, CodeLen);
48+
const auto Version = VersionOverride ? *VersionOverride : CurrentVersion;
49+
Writer.EmitRecord(PGOCtxProfileRecords::Version,
50+
SmallVector<unsigned, 1>({Version}));
51+
}
52+
1953
void PGOCtxProfileWriter::writeCounters(const ContextNode &Node) {
2054
Writer.EmitCode(bitc::UNABBREV_RECORD);
2155
Writer.EmitVBR(PGOCtxProfileRecords::Counters, VBREncodingBits);

llvm/unittests/ProfileData/PGOCtxProfReaderWriterTest.cpp

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "llvm/Bitstream/BitstreamReader.h"
9+
#include "llvm/Bitcode/BitcodeAnalyzer.h"
1010
#include "llvm/ProfileData/CtxInstrContextNode.h"
1111
#include "llvm/ProfileData/PGOCtxProfReader.h"
1212
#include "llvm/ProfileData/PGOCtxProfWriter.h"
@@ -106,8 +106,20 @@ TEST_F(PGOCtxProfRWTest, RoundTrip) {
106106
MemoryBuffer::getFile(ProfileFile.path());
107107
ASSERT_TRUE(!!MB);
108108
ASSERT_NE(*MB, nullptr);
109-
BitstreamCursor Cursor((*MB)->getBuffer());
110-
PGOCtxProfileReader Reader(Cursor);
109+
110+
// Check it's analyzable by the BCAnalyzer
111+
BitcodeAnalyzer BA((*MB)->getBuffer());
112+
std::string AnalyzerDump;
113+
raw_string_ostream OS(AnalyzerDump);
114+
BCDumpOptions Opts(OS);
115+
116+
// As in, expect no error.
117+
EXPECT_FALSE(BA.analyze(Opts));
118+
EXPECT_TRUE(AnalyzerDump.find("<Metadata BlockID") != std::string::npos);
119+
EXPECT_TRUE(AnalyzerDump.find("<Context BlockID") != std::string::npos);
120+
EXPECT_TRUE(AnalyzerDump.find("<CalleeIndex codeid") != std::string::npos);
121+
122+
PGOCtxProfileReader Reader((*MB)->getBuffer());
111123
auto Expected = Reader.loadContexts();
112124
ASSERT_TRUE(!!Expected);
113125
auto &Ctxes = *Expected;
@@ -143,25 +155,22 @@ TEST_F(PGOCtxProfRWTest, InvalidCounters) {
143155
auto MB = MemoryBuffer::getFile(ProfileFile.path());
144156
ASSERT_TRUE(!!MB);
145157
ASSERT_NE(*MB, nullptr);
146-
BitstreamCursor Cursor((*MB)->getBuffer());
147-
PGOCtxProfileReader Reader(Cursor);
158+
PGOCtxProfileReader Reader((*MB)->getBuffer());
148159
auto Expected = Reader.loadContexts();
149160
EXPECT_FALSE(Expected);
150161
consumeError(Expected.takeError());
151162
}
152163
}
153164

154165
TEST_F(PGOCtxProfRWTest, Empty) {
155-
BitstreamCursor Cursor("");
156-
PGOCtxProfileReader Reader(Cursor);
166+
PGOCtxProfileReader Reader("");
157167
auto Expected = Reader.loadContexts();
158168
EXPECT_FALSE(Expected);
159169
consumeError(Expected.takeError());
160170
}
161171

162172
TEST_F(PGOCtxProfRWTest, Invalid) {
163-
BitstreamCursor Cursor("Surely this is not valid");
164-
PGOCtxProfileReader Reader(Cursor);
173+
PGOCtxProfileReader Reader("Surely this is not valid");
165174
auto Expected = Reader.loadContexts();
166175
EXPECT_FALSE(Expected);
167176
consumeError(Expected.takeError());
@@ -182,8 +191,8 @@ TEST_F(PGOCtxProfRWTest, ValidButEmpty) {
182191
auto MB = MemoryBuffer::getFile(ProfileFile.path());
183192
ASSERT_TRUE(!!MB);
184193
ASSERT_NE(*MB, nullptr);
185-
BitstreamCursor Cursor((*MB)->getBuffer());
186-
PGOCtxProfileReader Reader(Cursor);
194+
195+
PGOCtxProfileReader Reader((*MB)->getBuffer());
187196
auto Expected = Reader.loadContexts();
188197
EXPECT_TRUE(!!Expected);
189198
EXPECT_TRUE(Expected->empty());
@@ -204,8 +213,8 @@ TEST_F(PGOCtxProfRWTest, WrongVersion) {
204213
auto MB = MemoryBuffer::getFile(ProfileFile.path());
205214
ASSERT_TRUE(!!MB);
206215
ASSERT_NE(*MB, nullptr);
207-
BitstreamCursor Cursor((*MB)->getBuffer());
208-
PGOCtxProfileReader Reader(Cursor);
216+
217+
PGOCtxProfileReader Reader((*MB)->getBuffer());
209218
auto Expected = Reader.loadContexts();
210219
EXPECT_FALSE(Expected);
211220
consumeError(Expected.takeError());
@@ -228,8 +237,7 @@ TEST_F(PGOCtxProfRWTest, DuplicateRoots) {
228237
auto MB = MemoryBuffer::getFile(ProfileFile.path());
229238
ASSERT_TRUE(!!MB);
230239
ASSERT_NE(*MB, nullptr);
231-
BitstreamCursor Cursor((*MB)->getBuffer());
232-
PGOCtxProfileReader Reader(Cursor);
240+
PGOCtxProfileReader Reader((*MB)->getBuffer());
233241
auto Expected = Reader.loadContexts();
234242
EXPECT_FALSE(Expected);
235243
consumeError(Expected.takeError());
@@ -255,8 +263,7 @@ TEST_F(PGOCtxProfRWTest, DuplicateTargets) {
255263
auto MB = MemoryBuffer::getFile(ProfileFile.path());
256264
ASSERT_TRUE(!!MB);
257265
ASSERT_NE(*MB, nullptr);
258-
BitstreamCursor Cursor((*MB)->getBuffer());
259-
PGOCtxProfileReader Reader(Cursor);
266+
PGOCtxProfileReader Reader((*MB)->getBuffer());
260267
auto Expected = Reader.loadContexts();
261268
EXPECT_FALSE(Expected);
262269
consumeError(Expected.takeError());

0 commit comments

Comments
 (0)