[llvm] [NFCI] Move ProfOStream from InstrProfWriter.cpp to InstrProf.h/cpp (PR #136791)
Mingming Liu via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 22 17:30:16 PDT 2025
https://github.com/mingmingl-llvm created https://github.com/llvm/llvm-project/pull/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 `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
>From e1fc5cc8b8aaeb59a79a3ecedaffd2e4d699c65f Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Tue, 22 Apr 2025 17:12:47 -0700
Subject: [PATCH] Move PProfOStream from InstrProfWriter.cpp to InstrProf.h/cpp
---
llvm/include/llvm/ProfileData/InstrProf.h | 32 ++++++++++++
llvm/lib/ProfileData/InstrProf.cpp | 41 ++++++++++++++++
llvm/lib/ProfileData/InstrProfWriter.cpp | 60 -----------------------
3 files changed, 73 insertions(+), 60 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index 7133c0c6a302c..2d011c89f27cb 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -28,6 +28,7 @@
#include "llvm/Support/BalancedPartitioning.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/EndianStream.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MD5.h"
@@ -57,6 +58,37 @@ class Instruction;
class MDNode;
class Module;
+// A struct to define how the data stream should be patched. For Indexed
+// profiling, only uint64_t data type is needed.
+struct PatchItem {
+ uint64_t Pos; // Where to patch.
+ ArrayRef<uint64_t> D; // An array of source data.
+};
+
+// A wrapper class to abstract writer stream with support of bytes
+// back patching.
+class ProfOStream {
+public:
+ ProfOStream(raw_fd_ostream &FD);
+ ProfOStream(raw_string_ostream &STR);
+
+ [[nodiscard]] uint64_t tell() const;
+ void write(uint64_t V);
+ void write32(uint32_t V);
+ void writeByte(uint8_t V);
+
+ // \c patch can only be called when all data is written and flushed.
+ // For raw_string_ostream, the patch is done on the target string
+ // directly and it won't be reflected in the stream's internal buffer.
+ void patch(ArrayRef<PatchItem> P);
+
+ // If \c OS is an instance of \c raw_fd_ostream, this field will be
+ // true. Otherwise, \c OS will be an raw_string_ostream.
+ bool IsFDOStream;
+ raw_ostream &OS;
+ support::endian::Writer LE;
+};
+
enum InstrProfSectKind {
#define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) Kind,
#include "llvm/ProfileData/InstrProfData.inc"
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index 1e427ca63c5cf..88621787c1dd9 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -42,6 +42,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/SwapByteOrder.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <cassert>
@@ -258,6 +259,46 @@ std::string InstrProfError::message() const {
char InstrProfError::ID = 0;
+ProfOStream::ProfOStream(raw_fd_ostream &FD)
+ : IsFDOStream(true), OS(FD), LE(FD, llvm::endianness::little) {}
+
+ProfOStream::ProfOStream(raw_string_ostream &STR)
+ : IsFDOStream(false), OS(STR), LE(STR, llvm::endianness::little) {}
+
+uint64_t ProfOStream::tell() const { return OS.tell(); }
+void ProfOStream::write(uint64_t V) { LE.write<uint64_t>(V); }
+void ProfOStream::write32(uint32_t V) { LE.write<uint32_t>(V); }
+void ProfOStream::writeByte(uint8_t V) { LE.write<uint8_t>(V); }
+
+void ProfOStream::patch(ArrayRef<PatchItem> P) {
+ using namespace support;
+
+ if (IsFDOStream) {
+ raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS);
+ const uint64_t LastPos = FDOStream.tell();
+ for (const auto &K : P) {
+ FDOStream.seek(K.Pos);
+ for (uint64_t Elem : K.D)
+ write(Elem);
+ }
+ // Reset the stream to the last position after patching so that users
+ // don't accidentally overwrite data. This makes it consistent with
+ // the string stream below which replaces the data directly.
+ FDOStream.seek(LastPos);
+ } else {
+ raw_string_ostream &SOStream = static_cast<raw_string_ostream &>(OS);
+ std::string &Data = SOStream.str(); // with flush
+ for (const auto &K : P) {
+ for (int I = 0, E = K.D.size(); I != E; I++) {
+ uint64_t Bytes =
+ endian::byte_swap<uint64_t, llvm::endianness::little>(K.D[I]);
+ Data.replace(K.Pos + I * sizeof(uint64_t), sizeof(uint64_t),
+ (const char *)&Bytes, sizeof(uint64_t));
+ }
+ }
+ }
+}
+
std::string getPGOFuncName(StringRef Name, GlobalValue::LinkageTypes Linkage,
StringRef FileName,
uint64_t Version LLVM_ATTRIBUTE_UNUSED) {
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index 18aa76c865bc8..f1882dc3628cc 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -37,68 +37,8 @@
using namespace llvm;
-// A struct to define how the data stream should be patched. For Indexed
-// profiling, only uint64_t data type is needed.
-struct PatchItem {
- uint64_t Pos; // Where to patch.
- ArrayRef<uint64_t> D; // An array of source data.
-};
-
namespace llvm {
-// A wrapper class to abstract writer stream with support of bytes
-// back patching.
-class ProfOStream {
-public:
- ProfOStream(raw_fd_ostream &FD)
- : IsFDOStream(true), OS(FD), LE(FD, llvm::endianness::little) {}
- ProfOStream(raw_string_ostream &STR)
- : IsFDOStream(false), OS(STR), LE(STR, llvm::endianness::little) {}
-
- [[nodiscard]] uint64_t tell() const { return OS.tell(); }
- void write(uint64_t V) { LE.write<uint64_t>(V); }
- void write32(uint32_t V) { LE.write<uint32_t>(V); }
- void writeByte(uint8_t V) { LE.write<uint8_t>(V); }
-
- // \c patch can only be called when all data is written and flushed.
- // For raw_string_ostream, the patch is done on the target string
- // directly and it won't be reflected in the stream's internal buffer.
- void patch(ArrayRef<PatchItem> P) {
- using namespace support;
-
- if (IsFDOStream) {
- raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS);
- const uint64_t LastPos = FDOStream.tell();
- for (const auto &K : P) {
- FDOStream.seek(K.Pos);
- for (uint64_t Elem : K.D)
- write(Elem);
- }
- // Reset the stream to the last position after patching so that users
- // don't accidentally overwrite data. This makes it consistent with
- // the string stream below which replaces the data directly.
- FDOStream.seek(LastPos);
- } else {
- raw_string_ostream &SOStream = static_cast<raw_string_ostream &>(OS);
- std::string &Data = SOStream.str(); // with flush
- for (const auto &K : P) {
- for (int I = 0, E = K.D.size(); I != E; I++) {
- uint64_t Bytes =
- endian::byte_swap<uint64_t, llvm::endianness::little>(K.D[I]);
- Data.replace(K.Pos + I * sizeof(uint64_t), sizeof(uint64_t),
- (const char *)&Bytes, sizeof(uint64_t));
- }
- }
- }
- }
-
- // If \c OS is an instance of \c raw_fd_ostream, this field will be
- // true. Otherwise, \c OS will be an raw_string_ostream.
- bool IsFDOStream;
- raw_ostream &OS;
- support::endian::Writer LE;
-};
-
class InstrProfRecordWriterTrait {
public:
using key_type = StringRef;
More information about the llvm-commits
mailing list