diff options
Diffstat (limited to 'llvm/lib/ProfileData/MemProf.cpp')
-rw-r--r-- | llvm/lib/ProfileData/MemProf.cpp | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/llvm/lib/ProfileData/MemProf.cpp b/llvm/lib/ProfileData/MemProf.cpp new file mode 100644 index 000000000000..3d44cf0b4c37 --- /dev/null +++ b/llvm/lib/ProfileData/MemProf.cpp @@ -0,0 +1,110 @@ +#include "llvm/ProfileData/MemProf.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Function.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/EndianStream.h" + +namespace llvm { +namespace memprof { + +void IndexedMemProfRecord::serialize(const MemProfSchema &Schema, + raw_ostream &OS) { + using namespace support; + + endian::Writer LE(OS, little); + + LE.write<uint64_t>(AllocSites.size()); + for (const IndexedAllocationInfo &N : AllocSites) { + LE.write<uint64_t>(N.CallStack.size()); + for (const FrameId &Id : N.CallStack) + LE.write<FrameId>(Id); + N.Info.serialize(Schema, OS); + } + + // Related contexts. + LE.write<uint64_t>(CallSites.size()); + for (const auto &Frames : CallSites) { + LE.write<uint64_t>(Frames.size()); + for (const FrameId &Id : Frames) + LE.write<FrameId>(Id); + } +} + +IndexedMemProfRecord +IndexedMemProfRecord::deserialize(const MemProfSchema &Schema, + const unsigned char *Ptr) { + using namespace support; + + IndexedMemProfRecord Record; + + // Read the meminfo nodes. + const uint64_t NumNodes = endian::readNext<uint64_t, little, unaligned>(Ptr); + for (uint64_t I = 0; I < NumNodes; I++) { + IndexedAllocationInfo Node; + const uint64_t NumFrames = + endian::readNext<uint64_t, little, unaligned>(Ptr); + for (uint64_t J = 0; J < NumFrames; J++) { + const FrameId Id = endian::readNext<FrameId, little, unaligned>(Ptr); + Node.CallStack.push_back(Id); + } + Node.Info.deserialize(Schema, Ptr); + Ptr += PortableMemInfoBlock::serializedSize(); + Record.AllocSites.push_back(Node); + } + + // Read the callsite information. + const uint64_t NumCtxs = endian::readNext<uint64_t, little, unaligned>(Ptr); + for (uint64_t J = 0; J < NumCtxs; J++) { + const uint64_t NumFrames = + endian::readNext<uint64_t, little, unaligned>(Ptr); + llvm::SmallVector<FrameId> Frames; + Frames.reserve(NumFrames); + for (uint64_t K = 0; K < NumFrames; K++) { + const FrameId Id = endian::readNext<FrameId, little, unaligned>(Ptr); + Frames.push_back(Id); + } + Record.CallSites.push_back(Frames); + } + + return Record; +} + +GlobalValue::GUID IndexedMemProfRecord::getGUID(const StringRef FunctionName) { + const auto Pos = FunctionName.find(".llvm."); + + // We use the function guid which we expect to be a uint64_t. At + // this time, it is the lower 64 bits of the md5 of the function + // name. Any suffix with .llvm. is trimmed since these are added by + // thinLTO global promotion. At the time the profile is consumed, + // these suffixes will not be present. + return Function::getGUID(FunctionName.take_front(Pos)); +} + +Expected<MemProfSchema> readMemProfSchema(const unsigned char *&Buffer) { + using namespace support; + + const unsigned char *Ptr = Buffer; + const uint64_t NumSchemaIds = + endian::readNext<uint64_t, little, unaligned>(Ptr); + if (NumSchemaIds > static_cast<uint64_t>(Meta::Size)) { + return make_error<InstrProfError>(instrprof_error::malformed, + "memprof schema invalid"); + } + + MemProfSchema Result; + for (size_t I = 0; I < NumSchemaIds; I++) { + const uint64_t Tag = endian::readNext<uint64_t, little, unaligned>(Ptr); + if (Tag >= static_cast<uint64_t>(Meta::Size)) { + return make_error<InstrProfError>(instrprof_error::malformed, + "memprof schema invalid"); + } + Result.push_back(static_cast<Meta>(Tag)); + } + // Advace the buffer to one past the schema if we succeeded. + Buffer = Ptr; + return Result; +} + +} // namespace memprof +} // namespace llvm |