[compiler-rt] 5071346 - Reland "[memprof] Introduce a wrapper around MemInfoBlock."
Snehasish Kumar via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 14 19:19:50 PST 2022
Author: Snehasish Kumar
Date: 2022-02-14T19:04:36-08:00
New Revision: 50713461d45eea2fd5521b665d213d72c796d7fc
URL: https://github.com/llvm/llvm-project/commit/50713461d45eea2fd5521b665d213d72c796d7fc
DIFF: https://github.com/llvm/llvm-project/commit/50713461d45eea2fd5521b665d213d72c796d7fc.diff
LOG: Reland "[memprof] Introduce a wrapper around MemInfoBlock."
This reverts commit e6999040f5758f89a64b6232119b775b7bd1c85b.
Update test to fix signed int comparison warning, fix whitespace in
compiler-rt MIBEntryDef.inc file.
Differential Revision: https://reviews.llvm.org/D117256
Added:
Modified:
compiler-rt/include/profile/MIBEntryDef.inc
llvm/include/llvm/ProfileData/MemProf.h
llvm/lib/ProfileData/RawMemProfReader.cpp
llvm/test/tools/llvm-profdata/memprof-basic.test
llvm/unittests/ProfileData/MemProfTest.cpp
Removed:
################################################################################
diff --git a/compiler-rt/include/profile/MIBEntryDef.inc b/compiler-rt/include/profile/MIBEntryDef.inc
index db4dbf4fd52f8..f5c6f0e4924b2 100644
--- a/compiler-rt/include/profile/MIBEntryDef.inc
+++ b/compiler-rt/include/profile/MIBEntryDef.inc
@@ -22,7 +22,6 @@
* synced up.
*
\*===----------------------------------------------------------------------===*/
-
#ifndef MIBEntryDef
#define MIBEntryDef(NameTag, Name, Type)
#endif
@@ -46,6 +45,3 @@ MIBEntryDef(NumLifetimeOverlaps = 16, NumLifetimeOverlaps, uint32_t)
MIBEntryDef(NumSameAllocCpu = 17, NumSameAllocCpu, uint32_t)
MIBEntryDef(NumSameDeallocCpu = 18, NumSameDeallocCpu, uint32_t)
MIBEntryDef(DataTypeId = 19, DataTypeId, uint64_t)
-
-
-
diff --git a/llvm/include/llvm/ProfileData/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h
index 1c92ec5d8892e..2fa577a626bbe 100644
--- a/llvm/include/llvm/ProfileData/MemProf.h
+++ b/llvm/include/llvm/ProfileData/MemProf.h
@@ -5,12 +5,134 @@
#include <string>
#include <vector>
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ProfileData/MemProfData.inc"
+#include "llvm/ProfileData/ProfileCommon.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/EndianStream.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
namespace memprof {
+enum class Meta : uint64_t {
+ Start = 0,
+#define MIBEntryDef(NameTag, Name, Type) NameTag,
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+ Size
+};
+
+using MemProfSchema = llvm::SmallVector<Meta, static_cast<int>(Meta::Size)>;
+
+// Holds the actual MemInfoBlock data with all fields. Contents may be read or
+// written partially by providing an appropriate schema to the serialize and
+// deserialize methods.
+struct PortableMemInfoBlock {
+ PortableMemInfoBlock() = default;
+ explicit PortableMemInfoBlock(const MemInfoBlock &Block) {
+#define MIBEntryDef(NameTag, Name, Type) Name = Block.Name;
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+ }
+
+ PortableMemInfoBlock(const MemProfSchema &Schema, const unsigned char *Ptr) {
+ deserialize(Schema, Ptr);
+ }
+
+ // Read the contents of \p Ptr based on the \p Schema to populate the
+ // MemInfoBlock member.
+ void deserialize(const MemProfSchema &Schema, const unsigned char *Ptr) {
+ using namespace support;
+
+ for (const Meta Id : Schema) {
+ switch (Id) {
+#define MIBEntryDef(NameTag, Name, Type) \
+ case Meta::Name: { \
+ Name = endian::readNext<Type, little, unaligned>(Ptr); \
+ } break;
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+ default:
+ llvm_unreachable("Unknown meta type id, is the profile collected from "
+ "a newer version of the runtime?");
+ }
+ }
+ }
+
+ // Write the contents of the MemInfoBlock based on the \p Schema provided to
+ // the raw_ostream \p OS.
+ void serialize(const MemProfSchema &Schema, raw_ostream &OS) const {
+ using namespace support;
+
+ endian::Writer LE(OS, little);
+ for (const Meta Id : Schema) {
+ switch (Id) {
+#define MIBEntryDef(NameTag, Name, Type) \
+ case Meta::Name: { \
+ LE.write<Type>(Name); \
+ } break;
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+ default:
+ llvm_unreachable("Unknown meta type id, invalid input?");
+ }
+ }
+ }
+
+ // Print out the contents of the MemInfoBlock in YAML format.
+ void printYAML(raw_ostream &OS) const {
+ OS << " MemInfoBlock:\n";
+#define MIBEntryDef(NameTag, Name, Type) \
+ OS << " " << #Name << ": " << Name << "\n";
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+ }
+
+ // Define getters for each type which can be called by analyses.
+#define MIBEntryDef(NameTag, Name, Type) \
+ Type get##Name() const { return Name; }
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+
+ void clear() { *this = PortableMemInfoBlock(); }
+
+ // Returns the full schema currently in use.
+ static MemProfSchema getSchema() {
+ MemProfSchema List;
+#define MIBEntryDef(NameTag, Name, Type) List.push_back(Meta::Name);
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+ return List;
+ }
+
+ bool operator==(const PortableMemInfoBlock &Other) const {
+#define MIBEntryDef(NameTag, Name, Type) \
+ if (Other.get##Name() != get##Name()) \
+ return false;
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+ return true;
+ }
+
+ bool operator!=(const PortableMemInfoBlock &Other) const {
+ return !operator==(Other);
+ }
+
+ static constexpr size_t serializedSize() {
+ size_t Result = 0;
+#define MIBEntryDef(NameTag, Name, Type) Result += sizeof(Type);
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+ return Result;
+ }
+
+private:
+#define MIBEntryDef(NameTag, Name, Type) Type Name = Type();
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+};
+
struct MemProfRecord {
struct Frame {
std::string Function;
@@ -24,14 +146,11 @@ struct MemProfRecord {
};
std::vector<Frame> CallStack;
- // TODO: Replace this with the entry format described in the RFC so
- // that the InstrProfRecord reader and writer do not have to be concerned
- // about backwards compat.
- MemInfoBlock Info;
+ PortableMemInfoBlock Info;
void clear() {
CallStack.clear();
- Info = MemInfoBlock();
+ Info.clear();
}
// Prints out the contents of the memprof record in YAML.
@@ -47,45 +166,7 @@ struct MemProfRecord {
<< " Inline: " << Frame.IsInlineFrame << "\n";
}
- OS << " MemInfoBlock:\n";
-
- // TODO: Replace this once the format is updated to be version agnostic.
- OS << " "
- << "AllocCount: " << Info.AllocCount << "\n";
- OS << " "
- << "TotalAccessCount: " << Info.TotalAccessCount << "\n";
- OS << " "
- << "MinAccessCount: " << Info.MinAccessCount << "\n";
- OS << " "
- << "MaxAccessCount: " << Info.MaxAccessCount << "\n";
- OS << " "
- << "TotalSize: " << Info.TotalSize << "\n";
- OS << " "
- << "MinSize: " << Info.MinSize << "\n";
- OS << " "
- << "MaxSize: " << Info.MaxSize << "\n";
- OS << " "
- << "AllocTimestamp: " << Info.AllocTimestamp << "\n";
- OS << " "
- << "DeallocTimestamp: " << Info.DeallocTimestamp << "\n";
- OS << " "
- << "TotalLifetime: " << Info.TotalLifetime << "\n";
- OS << " "
- << "MinLifetime: " << Info.MinLifetime << "\n";
- OS << " "
- << "MaxLifetime: " << Info.MaxLifetime << "\n";
- OS << " "
- << "AllocCpuId: " << Info.AllocCpuId << "\n";
- OS << " "
- << "DeallocCpuId: " << Info.DeallocCpuId << "\n";
- OS << " "
- << "NumMigratedCpu: " << Info.NumMigratedCpu << "\n";
- OS << " "
- << "NumLifetimeOverlaps: " << Info.NumLifetimeOverlaps << "\n";
- OS << " "
- << "NumSameAllocCpu: " << Info.NumSameAllocCpu << "\n";
- OS << " "
- << "NumSameDeallocCpu: " << Info.NumSameDeallocCpu << "\n";
+ Info.printYAML(OS);
}
};
diff --git a/llvm/lib/ProfileData/RawMemProfReader.cpp b/llvm/lib/ProfileData/RawMemProfReader.cpp
index 335ec04bc0980..43ef7c947366a 100644
--- a/llvm/lib/ProfileData/RawMemProfReader.cpp
+++ b/llvm/lib/ProfileData/RawMemProfReader.cpp
@@ -368,7 +368,7 @@ Error RawMemProfReader::fillRecord(const uint64_t Id, const MemInfoBlock &MIB,
I != 0);
}
}
- Record.Info = MIB;
+ Record.Info = PortableMemInfoBlock(MIB);
return Error::success();
}
diff --git a/llvm/test/tools/llvm-profdata/memprof-basic.test b/llvm/test/tools/llvm-profdata/memprof-basic.test
index 23c35c28ae96d..ccb5b4a438796 100644
--- a/llvm/test/tools/llvm-profdata/memprof-basic.test
+++ b/llvm/test/tools/llvm-profdata/memprof-basic.test
@@ -76,6 +76,7 @@ CHECK-NEXT: NumMigratedCpu: 1
CHECK-NEXT: NumLifetimeOverlaps: 0
CHECK-NEXT: NumSameAllocCpu: 0
CHECK-NEXT: NumSameDeallocCpu: 0
+CHECK-NEXT: DataTypeId: {{[0-9]+}}
CHECK-NEXT: -
CHECK-NEXT: Callstack:
CHECK-NEXT: -
@@ -112,6 +113,7 @@ CHECK-NEXT: NumMigratedCpu: 0
CHECK-NEXT: NumLifetimeOverlaps: 0
CHECK-NEXT: NumSameAllocCpu: 0
CHECK-NEXT: NumSameDeallocCpu: 0
+CHECK-NEXT: DataTypeId: {{[0-9]+}}
CHECK-NEXT: -
CHECK-NEXT: Callstack:
CHECK-NEXT: -
@@ -148,3 +150,4 @@ CHECK-NEXT: NumMigratedCpu: 0
CHECK-NEXT: NumLifetimeOverlaps: 0
CHECK-NEXT: NumSameAllocCpu: 0
CHECK-NEXT: NumSameDeallocCpu: 0
+CHECK-NEXT: DataTypeId: {{[0-9]+}}
diff --git a/llvm/unittests/ProfileData/MemProfTest.cpp b/llvm/unittests/ProfileData/MemProfTest.cpp
index 09ffe8fd634f2..f744b85d784c0 100644
--- a/llvm/unittests/ProfileData/MemProfTest.cpp
+++ b/llvm/unittests/ProfileData/MemProfTest.cpp
@@ -9,6 +9,7 @@
#include "llvm/ProfileData/RawMemProfReader.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MD5.h"
+#include "llvm/Support/raw_ostream.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -24,6 +25,9 @@ using ::llvm::DILocal;
using ::llvm::memprof::CallStackMap;
using ::llvm::memprof::MemInfoBlock;
using ::llvm::memprof::MemProfRecord;
+using ::llvm::memprof::MemProfSchema;
+using ::llvm::memprof::Meta;
+using ::llvm::memprof::PortableMemInfoBlock;
using ::llvm::memprof::RawMemProfReader;
using ::llvm::memprof::SegmentEntry;
using ::llvm::object::SectionedAddress;
@@ -99,6 +103,14 @@ MATCHER_P4(FrameContains, Function, LineOffset, Column, Inline, "") {
return false;
}
+MemProfSchema getFullSchema() {
+ MemProfSchema Schema;
+#define MIBEntryDef(NameTag, Name, Type) Schema.push_back(Meta::Name);
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+ return Schema;
+}
+
TEST(MemProf, FillsValue) {
std::unique_ptr<MockSymbolizer> Symbolizer(new MockSymbolizer());
@@ -136,8 +148,8 @@ TEST(MemProf, FillsValue) {
}
EXPECT_EQ(Records.size(), 2U);
- EXPECT_EQ(Records[0].Info.AllocCount, 1U);
- EXPECT_EQ(Records[1].Info.AllocCount, 2U);
+ EXPECT_EQ(Records[0].Info.getAllocCount(), 1U);
+ EXPECT_EQ(Records[1].Info.getAllocCount(), 2U);
EXPECT_THAT(Records[0].CallStack[0], FrameContains("foo", 5U, 30U, false));
EXPECT_THAT(Records[0].CallStack[1], FrameContains("bar", 51U, 20U, true));
@@ -147,4 +159,29 @@ TEST(MemProf, FillsValue) {
EXPECT_THAT(Records[1].CallStack[3], FrameContains("bar", 51U, 20U, true));
}
+TEST(MemProf, PortableWrapper) {
+ MemInfoBlock Info(/*size=*/16, /*access_count=*/7, /*alloc_timestamp=*/1000,
+ /*dealloc_timestamp=*/2000, /*alloc_cpu=*/3,
+ /*dealloc_cpu=*/4);
+
+ const auto Schema = getFullSchema();
+ PortableMemInfoBlock WriteBlock(Info);
+
+ std::string Buffer;
+ llvm::raw_string_ostream OS(Buffer);
+ WriteBlock.serialize(Schema, OS);
+ OS.flush();
+
+ PortableMemInfoBlock ReadBlock(
+ Schema, reinterpret_cast<const unsigned char *>(Buffer.data()));
+
+ EXPECT_EQ(ReadBlock, WriteBlock);
+ // Here we compare directly with the actual counts instead of MemInfoBlock
+ // members. Since the MemInfoBlock struct is packed and the EXPECT_EQ macros
+ // take a reference to the params, this results in unaligned accesses.
+ EXPECT_EQ(1UL, ReadBlock.getAllocCount());
+ EXPECT_EQ(7ULL, ReadBlock.getTotalAccessCount());
+ EXPECT_EQ(3UL, ReadBlock.getAllocCpuId());
+}
+
} // namespace
More information about the llvm-commits
mailing list