Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions llvm/include/llvm/ProfileData/MemProf.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,15 @@ struct PortableMemInfoBlock {
return Name; \
}
#include "llvm/ProfileData/MIBEntryDef.inc"
#undef MIBEntryDef

// Define setters for each type which can be called by the writer.
#define MIBEntryDef(NameTag, Name, Type) \
void set##Name(Type NewVal) { \
assert(Schema[llvm::to_underlying(Meta::Name)]); \
Name = NewVal; \
}
#include "llvm/ProfileData/MIBEntryDef.inc"
#undef MIBEntryDef

void clear() { *this = PortableMemInfoBlock(); }
Expand Down
48 changes: 45 additions & 3 deletions llvm/lib/ProfileData/InstrProfWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/ProfileData/MemProf.h"
#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
Expand All @@ -36,6 +37,14 @@

using namespace llvm;

static cl::opt<bool>
MemprofGenerateRandomHotness("memprof-random-hotness", cl::init(false),
cl::Hidden,
cl::desc("Generate random hotness values"));
static cl::opt<unsigned> MemprofGenerateRandomHotnessSeed(
"memprof-random-hotness-seed", cl::init(0), cl::Hidden,
cl::desc("Random hotness seed to use (0 to generate new seed)"));

// A struct to define how the data stream should be patched. For Indexed
// profiling, only uint64_t data type is needed.
struct PatchItem {
Expand Down Expand Up @@ -190,7 +199,16 @@ InstrProfWriter::InstrProfWriter(
InfoObj(new InstrProfRecordWriterTrait()),
WritePrevVersion(WritePrevVersion),
MemProfVersionRequested(MemProfVersionRequested),
MemProfFullSchema(MemProfFullSchema) {}
MemProfFullSchema(MemProfFullSchema) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For internal tooling it will be cleaner if we plumb it through as a parameter instead of setting the cl::opt.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// Set up the random number seed if requested.
if (MemprofGenerateRandomHotness) {
unsigned seed = MemprofGenerateRandomHotnessSeed
? MemprofGenerateRandomHotnessSeed
: std::time(nullptr);
errs() << "random hotness seed = " << seed << "\n";
std::srand(seed);
}
}

InstrProfWriter::~InstrProfWriter() { delete InfoObj; }

Expand Down Expand Up @@ -273,13 +291,37 @@ void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,

void InstrProfWriter::addMemProfRecord(
const Function::GUID Id, const memprof::IndexedMemProfRecord &Record) {
auto [Iter, Inserted] = MemProfData.Records.insert({Id, Record});
auto NewRecord = Record;
// Provoke random hotness values if requested. We specify the lifetime access
// density and lifetime length that will result in a cold or not cold hotness.
// See the logic in getAllocType() in Analysis/MemoryProfileInfo.cpp.
if (MemprofGenerateRandomHotness) {
for (auto &Alloc : NewRecord.AllocSites) {
uint64_t NewTLAD = 0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you initialize NewTLAD to NewTLAD = std::numeric_limits<uint64_t>::max(); here instead then you can skip the else below. Also hoist the comment out of the else block.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

uint64_t NewTL = 0;
bool IsCold = std::rand() % 2;
if (IsCold) {
// To get a cold context, set the lifetime access density to 0 and the
// lifetime to the maximum value.
NewTLAD = 0;
NewTL = std::numeric_limits<uint64_t>::max();
} else {
// To get a not cold context, set the lifetime access density to the
// maximum value and the lifetime to 0.
NewTLAD = std::numeric_limits<uint64_t>::max();
NewTL = 0;
}
Alloc.Info.setTotalLifetimeAccessDensity(NewTLAD);
Alloc.Info.setTotalLifetime(NewTL);
}
}
auto [Iter, Inserted] = MemProfData.Records.insert({Id, NewRecord});
// If we inserted a new record then we are done.
if (Inserted) {
return;
}
memprof::IndexedMemProfRecord &Existing = Iter->second;
Existing.merge(Record);
Existing.merge(NewRecord);
}

bool InstrProfWriter::addMemProfFrame(const memprof::FrameId Id,
Expand Down
19 changes: 19 additions & 0 deletions llvm/test/Transforms/PGOProfile/memprof.ll
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@
;; Check that the total sizes are reported if requested.
; RUN: opt < %s -passes='memprof-use<profile-filename=%t.memprofdata>' -pgo-warn-missing-function -S -memprof-report-hinted-sizes 2>&1 | FileCheck %s --check-prefixes=TOTALSIZES

;; Make sure we emit a random hotness seed if requested.
; RUN: llvm-profdata merge -memprof-random-hotness %S/Inputs/memprof.memprofraw --profiled-binary %S/Inputs/memprof.exe -o %t.memprofdatarand 2>&1 | FileCheck %s --check-prefix=RAND
; RAND: random hotness seed =
;; Can't check the exact values, but make sure applying the random profile
;; succeeds with the same stats
; RUN: opt < %s -passes='memprof-use<profile-filename=%t.memprofdatarand>' -pgo-warn-missing-function -S -stats 2>&1 | FileCheck %s --check-prefixes=ALL,MEMPROFONLY,MEMPROFSTATS

;; Make sure we use a specific random hotness seed if requested.
; RUN: llvm-profdata merge -memprof-random-hotness -memprof-random-hotness-seed=1730170724 %S/Inputs/memprof.memprofraw --profiled-binary %S/Inputs/memprof.exe -o %t.memprofdatarand2 2>&1 | FileCheck %s --check-prefix=RAND2
; RAND2: random hotness seed = 1730170724
; RUN: opt < %s -passes='memprof-use<profile-filename=%t.memprofdatarand2>' -pgo-warn-missing-function -S -stats 2>&1 | FileCheck %s --check-prefixes=MEMPROFRAND2,ALL,MEMPROFONLY,MEMPROFSTATS

; MEMPROFMATCHINFO: MemProf notcold context with id 1093248920606587996 has total profiled size 10 is matched
; MEMPROFMATCHINFO: MemProf notcold context with id 5725971306423925017 has total profiled size 10 is matched
; MEMPROFMATCHINFO: MemProf notcold context with id 6792096022461663180 has total profiled size 10 is matched
Expand Down Expand Up @@ -372,6 +384,13 @@ for.end: ; preds = %for.cond
; MEMPROFNOCOLINFO: ![[C10]] = !{i64 -4535090212904553409}
; MEMPROFNOCOLINFO: ![[C11]] = !{i64 3577763375057267810}

;; For the specific random seed, this is the expected order of hotness
; MEMPROFRAND2: !"cold"
; MEMPROFRAND2: !"cold"
; MEMPROFRAND2: !"cold"
; MEMPROFRAND2: !"hot"
; MEMPROFRAND2: !"hot"

; MEMPROFSTATS: 8 memprof - Number of alloc contexts in memory profile.
; MEMPROFSTATS: 10 memprof - Number of callsites in memory profile.
; MEMPROFSTATS: 6 memprof - Number of functions having valid memory profile.
Expand Down
Loading