[llvm] [memprof] Move YAML support to MemProfYAML.h (NFC) (PR #119515)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 10 23:05:05 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-pgo
Author: Kazu Hirata (kazutakahirata)
<details>
<summary>Changes</summary>
The YAML support is increasing in size, so this patch moves it to a
separate file.
---
Full diff: https://github.com/llvm/llvm-project/pull/119515.diff
6 Files Affected:
- (modified) llvm/include/llvm/ProfileData/InstrProfReader.h (+1)
- (modified) llvm/include/llvm/ProfileData/MemProf.h (-144)
- (added) llvm/include/llvm/ProfileData/MemProfYAML.h (+154)
- (modified) llvm/lib/ProfileData/MemProfReader.cpp (+1)
- (modified) llvm/tools/llvm-profdata/llvm-profdata.cpp (+1)
- (modified) llvm/unittests/ProfileData/MemProfTest.cpp (+1)
``````````diff
diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
index 25e13f575296dd..f1010b312ee569 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -21,6 +21,7 @@
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/ProfileData/InstrProfCorrelator.h"
#include "llvm/ProfileData/MemProf.h"
+#include "llvm/ProfileData/MemProfYAML.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/LineIterator.h"
diff --git a/llvm/include/llvm/ProfileData/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h
index ace3c044d8c277..ef96b74c9d400c 100644
--- a/llvm/include/llvm/ProfileData/MemProf.h
+++ b/llvm/include/llvm/ProfileData/MemProf.h
@@ -11,9 +11,7 @@
#include "llvm/Support/BLAKE3.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
-#include "llvm/Support/Format.h"
#include "llvm/Support/HashBuilder.h"
-#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include <bitset>
@@ -492,23 +490,6 @@ struct MemProfRecord {
}
};
-// A "typedef" for GUID. See ScalarTraits<memprof::GUIDHex64> for how a GUID is
-// serialized and deserialized in YAML.
-LLVM_YAML_STRONG_TYPEDEF(uint64_t, GUIDHex64)
-
-// Helper struct for AllMemProfData. In YAML, we treat the GUID and the fields
-// within MemProfRecord at the same level as if the GUID were part of
-// MemProfRecord.
-struct GUIDMemProfRecordPair {
- GUIDHex64 GUID;
- MemProfRecord Record;
-};
-
-// The top-level data structure, only used with YAML for now.
-struct AllMemProfData {
- std::vector<GUIDMemProfRecordPair> HeapProfileRecords;
-};
-
// Reads a memprof schema from a buffer. All entries in the buffer are
// interpreted as uint64_t. The first entry in the buffer denotes the number of
// ids in the schema. Subsequent entries are integers which map to memprof::Meta
@@ -1169,131 +1150,6 @@ template <typename FrameIdTy> class CallStackRadixTreeBuilder {
}
};
} // namespace memprof
-
-namespace yaml {
-template <> struct ScalarTraits<memprof::GUIDHex64> {
- static void output(const memprof::GUIDHex64 &Val, void *, raw_ostream &Out) {
- // Print GUID as a 16-digit hexadecimal number.
- Out << format("0x%016" PRIx64, (uint64_t)Val);
- }
- static StringRef input(StringRef Scalar, void *, memprof::GUIDHex64 &Val) {
- // Reject decimal GUIDs.
- if (all_of(Scalar, [](char C) { return std::isdigit(C); }))
- return "use a hexadecimal GUID or a function instead";
-
- uint64_t Num;
- if (Scalar.starts_with_insensitive("0x")) {
- // Accept hexadecimal numbers starting with 0x or 0X.
- if (Scalar.getAsInteger(0, Num))
- return "invalid hex64 number";
- Val = Num;
- } else {
- // Otherwise, treat the input as a string containing a function name.
- Val = memprof::IndexedMemProfRecord::getGUID(Scalar);
- }
- return StringRef();
- }
- static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-template <> struct MappingTraits<memprof::Frame> {
- static void mapping(IO &Io, memprof::Frame &F) {
- Io.mapRequired("Function", F.Function);
- Io.mapRequired("LineOffset", F.LineOffset);
- Io.mapRequired("Column", F.Column);
- Io.mapRequired("IsInlineFrame", F.IsInlineFrame);
-
- // Assert that the definition of Frame matches what we expect. The
- // structured bindings below detect changes to the number of fields.
- // static_assert checks the type of each field.
- const auto &[Function, SymbolName, LineOffset, Column, IsInlineFrame] = F;
- static_assert(
- std::is_same_v<remove_cvref_t<decltype(Function)>, GlobalValue::GUID>);
- static_assert(std::is_same_v<remove_cvref_t<decltype(SymbolName)>,
- std::unique_ptr<std::string>>);
- static_assert(
- std::is_same_v<remove_cvref_t<decltype(LineOffset)>, uint32_t>);
- static_assert(std::is_same_v<remove_cvref_t<decltype(Column)>, uint32_t>);
- static_assert(
- std::is_same_v<remove_cvref_t<decltype(IsInlineFrame)>, bool>);
-
- // MSVC issues unused variable warnings despite the uses in static_assert
- // above.
- (void)Function;
- (void)SymbolName;
- (void)LineOffset;
- (void)Column;
- (void)IsInlineFrame;
- }
-
- // Request the inline notation for brevity:
- // { Function: 123, LineOffset: 11, Column: 10; IsInlineFrame: true }
- static const bool flow = true;
-};
-
-template <> struct CustomMappingTraits<memprof::PortableMemInfoBlock> {
- static void inputOne(IO &Io, StringRef KeyStr,
- memprof::PortableMemInfoBlock &MIB) {
- // PortableMemInfoBlock keeps track of the set of fields that actually have
- // values. We update the set here as we receive a key-value pair from the
- // YAML document.
- //
- // We set MIB.Name via a temporary variable because ScalarTraits<uintptr_t>
- // isn't available on macOS.
-#define MIBEntryDef(NameTag, Name, Type) \
- if (KeyStr == #Name) { \
- uint64_t Value; \
- Io.mapRequired(KeyStr.str().c_str(), Value); \
- MIB.Name = static_cast<Type>(Value); \
- MIB.Schema.set(llvm::to_underlying(memprof::Meta::Name)); \
- return; \
- }
-#include "llvm/ProfileData/MIBEntryDef.inc"
-#undef MIBEntryDef
- Io.setError("Key is not a valid validation event");
- }
-
- static void output(IO &Io, memprof::PortableMemInfoBlock &MIB) {
- auto Schema = MIB.getSchema();
-#define MIBEntryDef(NameTag, Name, Type) \
- if (Schema.test(llvm::to_underlying(memprof::Meta::Name))) { \
- uint64_t Value = MIB.Name; \
- Io.mapRequired(#Name, Value); \
- }
-#include "llvm/ProfileData/MIBEntryDef.inc"
-#undef MIBEntryDef
- }
-};
-
-template <> struct MappingTraits<memprof::AllocationInfo> {
- static void mapping(IO &Io, memprof::AllocationInfo &AI) {
- Io.mapRequired("Callstack", AI.CallStack);
- Io.mapRequired("MemInfoBlock", AI.Info);
- }
-};
-
-// In YAML, we use GUIDMemProfRecordPair instead of MemProfRecord so that we can
-// treat the GUID and the fields within MemProfRecord at the same level as if
-// the GUID were part of MemProfRecord.
-template <> struct MappingTraits<memprof::GUIDMemProfRecordPair> {
- static void mapping(IO &Io, memprof::GUIDMemProfRecordPair &Pair) {
- Io.mapRequired("GUID", Pair.GUID);
- Io.mapRequired("AllocSites", Pair.Record.AllocSites);
- Io.mapRequired("CallSites", Pair.Record.CallSites);
- }
-};
-
-template <> struct MappingTraits<memprof::AllMemProfData> {
- static void mapping(IO &Io, memprof::AllMemProfData &Data) {
- Io.mapRequired("HeapProfileRecords", Data.HeapProfileRecords);
- }
-};
-} // namespace yaml
} // namespace llvm
-LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::Frame)
-LLVM_YAML_IS_SEQUENCE_VECTOR(std::vector<memprof::Frame>)
-LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::AllocationInfo)
-LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::GUIDMemProfRecordPair)
-
#endif // LLVM_PROFILEDATA_MEMPROF_H_
diff --git a/llvm/include/llvm/ProfileData/MemProfYAML.h b/llvm/include/llvm/ProfileData/MemProfYAML.h
new file mode 100644
index 00000000000000..4568385fc6f71f
--- /dev/null
+++ b/llvm/include/llvm/ProfileData/MemProfYAML.h
@@ -0,0 +1,154 @@
+#ifndef LLVM_PROFILEDATA_MEMPROFYAML_H_
+#define LLVM_PROFILEDATA_MEMPROFYAML_H_
+
+#include "llvm/ProfileData/MemProf.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/YAMLTraits.h"
+
+namespace llvm {
+namespace memprof {
+// A "typedef" for GUID. See ScalarTraits<memprof::GUIDHex64> for how a GUID is
+// serialized and deserialized in YAML.
+LLVM_YAML_STRONG_TYPEDEF(uint64_t, GUIDHex64)
+
+// Helper struct for AllMemProfData. In YAML, we treat the GUID and the fields
+// within MemProfRecord at the same level as if the GUID were part of
+// MemProfRecord.
+struct GUIDMemProfRecordPair {
+ GUIDHex64 GUID;
+ MemProfRecord Record;
+};
+
+// The top-level data structure, only used with YAML for now.
+struct AllMemProfData {
+ std::vector<GUIDMemProfRecordPair> HeapProfileRecords;
+};
+} // namespace memprof
+
+namespace yaml {
+template <> struct ScalarTraits<memprof::GUIDHex64> {
+ static void output(const memprof::GUIDHex64 &Val, void *, raw_ostream &Out) {
+ // Print GUID as a 16-digit hexadecimal number.
+ Out << format("0x%016" PRIx64, (uint64_t)Val);
+ }
+ static StringRef input(StringRef Scalar, void *, memprof::GUIDHex64 &Val) {
+ // Reject decimal GUIDs.
+ if (all_of(Scalar, [](char C) { return std::isdigit(C); }))
+ return "use a hexadecimal GUID or a function instead";
+
+ uint64_t Num;
+ if (Scalar.starts_with_insensitive("0x")) {
+ // Accept hexadecimal numbers starting with 0x or 0X.
+ if (Scalar.getAsInteger(0, Num))
+ return "invalid hex64 number";
+ Val = Num;
+ } else {
+ // Otherwise, treat the input as a string containing a function name.
+ Val = memprof::IndexedMemProfRecord::getGUID(Scalar);
+ }
+ return StringRef();
+ }
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template <> struct MappingTraits<memprof::Frame> {
+ static void mapping(IO &Io, memprof::Frame &F) {
+ Io.mapRequired("Function", F.Function);
+ Io.mapRequired("LineOffset", F.LineOffset);
+ Io.mapRequired("Column", F.Column);
+ Io.mapRequired("IsInlineFrame", F.IsInlineFrame);
+
+ // Assert that the definition of Frame matches what we expect. The
+ // structured bindings below detect changes to the number of fields.
+ // static_assert checks the type of each field.
+ const auto &[Function, SymbolName, LineOffset, Column, IsInlineFrame] = F;
+ static_assert(
+ std::is_same_v<remove_cvref_t<decltype(Function)>, GlobalValue::GUID>);
+ static_assert(std::is_same_v<remove_cvref_t<decltype(SymbolName)>,
+ std::unique_ptr<std::string>>);
+ static_assert(
+ std::is_same_v<remove_cvref_t<decltype(LineOffset)>, uint32_t>);
+ static_assert(std::is_same_v<remove_cvref_t<decltype(Column)>, uint32_t>);
+ static_assert(
+ std::is_same_v<remove_cvref_t<decltype(IsInlineFrame)>, bool>);
+
+ // MSVC issues unused variable warnings despite the uses in static_assert
+ // above.
+ (void)Function;
+ (void)SymbolName;
+ (void)LineOffset;
+ (void)Column;
+ (void)IsInlineFrame;
+ }
+
+ // Request the inline notation for brevity:
+ // { Function: 123, LineOffset: 11, Column: 10; IsInlineFrame: true }
+ static const bool flow = true;
+};
+
+template <> struct CustomMappingTraits<memprof::PortableMemInfoBlock> {
+ static void inputOne(IO &Io, StringRef KeyStr,
+ memprof::PortableMemInfoBlock &MIB) {
+ // PortableMemInfoBlock keeps track of the set of fields that actually have
+ // values. We update the set here as we receive a key-value pair from the
+ // YAML document.
+ //
+ // We set MIB.Name via a temporary variable because ScalarTraits<uintptr_t>
+ // isn't available on macOS.
+#define MIBEntryDef(NameTag, Name, Type) \
+ if (KeyStr == #Name) { \
+ uint64_t Value; \
+ Io.mapRequired(KeyStr.str().c_str(), Value); \
+ MIB.Name = static_cast<Type>(Value); \
+ MIB.Schema.set(llvm::to_underlying(memprof::Meta::Name)); \
+ return; \
+ }
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+ Io.setError("Key is not a valid validation event");
+ }
+
+ static void output(IO &Io, memprof::PortableMemInfoBlock &MIB) {
+ auto Schema = MIB.getSchema();
+#define MIBEntryDef(NameTag, Name, Type) \
+ if (Schema.test(llvm::to_underlying(memprof::Meta::Name))) { \
+ uint64_t Value = MIB.Name; \
+ Io.mapRequired(#Name, Value); \
+ }
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+ }
+};
+
+template <> struct MappingTraits<memprof::AllocationInfo> {
+ static void mapping(IO &Io, memprof::AllocationInfo &AI) {
+ Io.mapRequired("Callstack", AI.CallStack);
+ Io.mapRequired("MemInfoBlock", AI.Info);
+ }
+};
+
+// In YAML, we use GUIDMemProfRecordPair instead of MemProfRecord so that we can
+// treat the GUID and the fields within MemProfRecord at the same level as if
+// the GUID were part of MemProfRecord.
+template <> struct MappingTraits<memprof::GUIDMemProfRecordPair> {
+ static void mapping(IO &Io, memprof::GUIDMemProfRecordPair &Pair) {
+ Io.mapRequired("GUID", Pair.GUID);
+ Io.mapRequired("AllocSites", Pair.Record.AllocSites);
+ Io.mapRequired("CallSites", Pair.Record.CallSites);
+ }
+};
+
+template <> struct MappingTraits<memprof::AllMemProfData> {
+ static void mapping(IO &Io, memprof::AllMemProfData &Data) {
+ Io.mapRequired("HeapProfileRecords", Data.HeapProfileRecords);
+ }
+};
+} // namespace yaml
+} // namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::Frame)
+LLVM_YAML_IS_SEQUENCE_VECTOR(std::vector<memprof::Frame>)
+LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::AllocationInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::GUIDMemProfRecordPair)
+
+#endif // LLVM_PROFILEDATA_MEMPROFYAML_H_
diff --git a/llvm/lib/ProfileData/MemProfReader.cpp b/llvm/lib/ProfileData/MemProfReader.cpp
index 19ae9a79ea519e..9dd43d34f2a0bb 100644
--- a/llvm/lib/ProfileData/MemProfReader.cpp
+++ b/llvm/lib/ProfileData/MemProfReader.cpp
@@ -32,6 +32,7 @@
#include "llvm/ProfileData/MemProf.h"
#include "llvm/ProfileData/MemProfData.inc"
#include "llvm/ProfileData/MemProfReader.h"
+#include "llvm/ProfileData/MemProfYAML.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index f34d99e10f3163..6b9e2349899a44 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -21,6 +21,7 @@
#include "llvm/ProfileData/InstrProfWriter.h"
#include "llvm/ProfileData/MemProf.h"
#include "llvm/ProfileData/MemProfReader.h"
+#include "llvm/ProfileData/MemProfYAML.h"
#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/ProfileData/SampleProfReader.h"
#include "llvm/ProfileData/SampleProfWriter.h"
diff --git a/llvm/unittests/ProfileData/MemProfTest.cpp b/llvm/unittests/ProfileData/MemProfTest.cpp
index 5886d3e2bcf842..db2cf1b4c23658 100644
--- a/llvm/unittests/ProfileData/MemProfTest.cpp
+++ b/llvm/unittests/ProfileData/MemProfTest.cpp
@@ -16,6 +16,7 @@
#include "llvm/Object/ObjectFile.h"
#include "llvm/ProfileData/MemProfData.inc"
#include "llvm/ProfileData/MemProfReader.h"
+#include "llvm/ProfileData/MemProfYAML.h"
#include "llvm/Support/raw_ostream.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
``````````
</details>
https://github.com/llvm/llvm-project/pull/119515
More information about the llvm-commits
mailing list