Skip to content

Commit 2f0cd0c

Browse files
[NFCI] Move ProfOStream from InstrProfWriter.cpp to InstrProf.h/cpp (llvm#136791)
ProfOStream is a wrapper class for output stream, and used by InstrProfWriter.cpp to serialize various profiles, like PGO profiles and MemProf. This change proposes to move it into InstrProf.h/cpp. After this is in, InstrProfWriter can dispatch serialization of various formats into methods like `obj->serialize()`, and the serialization code could be move out of InstrProfWriter.cpp into individual classes (each in a smaller cpp file). One example is that we can gradually move writeMemprof [1] into llvm/*/ProfileData/MemProf.h/cpp, where a couple of classes already have `serialize/deserialize` methods. [1] https://github.com/llvm/llvm-project/blob/85b35a90770b6053f91d79ca685cdfa4bf6499a4/llvm/lib/ProfileData/InstrProfWriter.cpp#L774-L791
1 parent 24c8605 commit 2f0cd0c

File tree

3 files changed

+73
-60
lines changed

3 files changed

+73
-60
lines changed

llvm/include/llvm/ProfileData/InstrProf.h

+32
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "llvm/Support/BalancedPartitioning.h"
2929
#include "llvm/Support/CommandLine.h"
3030
#include "llvm/Support/Compiler.h"
31+
#include "llvm/Support/EndianStream.h"
3132
#include "llvm/Support/Error.h"
3233
#include "llvm/Support/ErrorHandling.h"
3334
#include "llvm/Support/MD5.h"
@@ -57,6 +58,37 @@ class Instruction;
5758
class MDNode;
5859
class Module;
5960

61+
// A struct to define how the data stream should be patched. For Indexed
62+
// profiling, only uint64_t data type is needed.
63+
struct PatchItem {
64+
uint64_t Pos; // Where to patch.
65+
ArrayRef<uint64_t> D; // An array of source data.
66+
};
67+
68+
// A wrapper class to abstract writer stream with support of bytes
69+
// back patching.
70+
class ProfOStream {
71+
public:
72+
ProfOStream(raw_fd_ostream &FD);
73+
ProfOStream(raw_string_ostream &STR);
74+
75+
[[nodiscard]] uint64_t tell() const;
76+
void write(uint64_t V);
77+
void write32(uint32_t V);
78+
void writeByte(uint8_t V);
79+
80+
// \c patch can only be called when all data is written and flushed.
81+
// For raw_string_ostream, the patch is done on the target string
82+
// directly and it won't be reflected in the stream's internal buffer.
83+
void patch(ArrayRef<PatchItem> P);
84+
85+
// If \c OS is an instance of \c raw_fd_ostream, this field will be
86+
// true. Otherwise, \c OS will be an raw_string_ostream.
87+
bool IsFDOStream;
88+
raw_ostream &OS;
89+
support::endian::Writer LE;
90+
};
91+
6092
enum InstrProfSectKind {
6193
#define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) Kind,
6294
#include "llvm/ProfileData/InstrProfData.inc"

llvm/lib/ProfileData/InstrProf.cpp

+41
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "llvm/Support/Path.h"
4343
#include "llvm/Support/SwapByteOrder.h"
4444
#include "llvm/Support/VirtualFileSystem.h"
45+
#include "llvm/Support/raw_ostream.h"
4546
#include "llvm/TargetParser/Triple.h"
4647
#include <algorithm>
4748
#include <cassert>
@@ -258,6 +259,46 @@ std::string InstrProfError::message() const {
258259

259260
char InstrProfError::ID = 0;
260261

262+
ProfOStream::ProfOStream(raw_fd_ostream &FD)
263+
: IsFDOStream(true), OS(FD), LE(FD, llvm::endianness::little) {}
264+
265+
ProfOStream::ProfOStream(raw_string_ostream &STR)
266+
: IsFDOStream(false), OS(STR), LE(STR, llvm::endianness::little) {}
267+
268+
uint64_t ProfOStream::tell() const { return OS.tell(); }
269+
void ProfOStream::write(uint64_t V) { LE.write<uint64_t>(V); }
270+
void ProfOStream::write32(uint32_t V) { LE.write<uint32_t>(V); }
271+
void ProfOStream::writeByte(uint8_t V) { LE.write<uint8_t>(V); }
272+
273+
void ProfOStream::patch(ArrayRef<PatchItem> P) {
274+
using namespace support;
275+
276+
if (IsFDOStream) {
277+
raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS);
278+
const uint64_t LastPos = FDOStream.tell();
279+
for (const auto &K : P) {
280+
FDOStream.seek(K.Pos);
281+
for (uint64_t Elem : K.D)
282+
write(Elem);
283+
}
284+
// Reset the stream to the last position after patching so that users
285+
// don't accidentally overwrite data. This makes it consistent with
286+
// the string stream below which replaces the data directly.
287+
FDOStream.seek(LastPos);
288+
} else {
289+
raw_string_ostream &SOStream = static_cast<raw_string_ostream &>(OS);
290+
std::string &Data = SOStream.str(); // with flush
291+
for (const auto &K : P) {
292+
for (int I = 0, E = K.D.size(); I != E; I++) {
293+
uint64_t Bytes =
294+
endian::byte_swap<uint64_t, llvm::endianness::little>(K.D[I]);
295+
Data.replace(K.Pos + I * sizeof(uint64_t), sizeof(uint64_t),
296+
(const char *)&Bytes, sizeof(uint64_t));
297+
}
298+
}
299+
}
300+
}
301+
261302
std::string getPGOFuncName(StringRef Name, GlobalValue::LinkageTypes Linkage,
262303
StringRef FileName,
263304
uint64_t Version LLVM_ATTRIBUTE_UNUSED) {

llvm/lib/ProfileData/InstrProfWriter.cpp

-60
Original file line numberDiff line numberDiff line change
@@ -37,68 +37,8 @@
3737

3838
using namespace llvm;
3939

40-
// A struct to define how the data stream should be patched. For Indexed
41-
// profiling, only uint64_t data type is needed.
42-
struct PatchItem {
43-
uint64_t Pos; // Where to patch.
44-
ArrayRef<uint64_t> D; // An array of source data.
45-
};
46-
4740
namespace llvm {
4841

49-
// A wrapper class to abstract writer stream with support of bytes
50-
// back patching.
51-
class ProfOStream {
52-
public:
53-
ProfOStream(raw_fd_ostream &FD)
54-
: IsFDOStream(true), OS(FD), LE(FD, llvm::endianness::little) {}
55-
ProfOStream(raw_string_ostream &STR)
56-
: IsFDOStream(false), OS(STR), LE(STR, llvm::endianness::little) {}
57-
58-
[[nodiscard]] uint64_t tell() const { return OS.tell(); }
59-
void write(uint64_t V) { LE.write<uint64_t>(V); }
60-
void write32(uint32_t V) { LE.write<uint32_t>(V); }
61-
void writeByte(uint8_t V) { LE.write<uint8_t>(V); }
62-
63-
// \c patch can only be called when all data is written and flushed.
64-
// For raw_string_ostream, the patch is done on the target string
65-
// directly and it won't be reflected in the stream's internal buffer.
66-
void patch(ArrayRef<PatchItem> P) {
67-
using namespace support;
68-
69-
if (IsFDOStream) {
70-
raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS);
71-
const uint64_t LastPos = FDOStream.tell();
72-
for (const auto &K : P) {
73-
FDOStream.seek(K.Pos);
74-
for (uint64_t Elem : K.D)
75-
write(Elem);
76-
}
77-
// Reset the stream to the last position after patching so that users
78-
// don't accidentally overwrite data. This makes it consistent with
79-
// the string stream below which replaces the data directly.
80-
FDOStream.seek(LastPos);
81-
} else {
82-
raw_string_ostream &SOStream = static_cast<raw_string_ostream &>(OS);
83-
std::string &Data = SOStream.str(); // with flush
84-
for (const auto &K : P) {
85-
for (int I = 0, E = K.D.size(); I != E; I++) {
86-
uint64_t Bytes =
87-
endian::byte_swap<uint64_t, llvm::endianness::little>(K.D[I]);
88-
Data.replace(K.Pos + I * sizeof(uint64_t), sizeof(uint64_t),
89-
(const char *)&Bytes, sizeof(uint64_t));
90-
}
91-
}
92-
}
93-
}
94-
95-
// If \c OS is an instance of \c raw_fd_ostream, this field will be
96-
// true. Otherwise, \c OS will be an raw_string_ostream.
97-
bool IsFDOStream;
98-
raw_ostream &OS;
99-
support::endian::Writer LE;
100-
};
101-
10242
class InstrProfRecordWriterTrait {
10343
public:
10444
using key_type = StringRef;

0 commit comments

Comments
 (0)