Skip to content

Commit 2bd4d3b

Browse files
committed
[MemProf] Support for random hotness when writing profile
Add support for generating random hotness in the memprof profile writer, to be used for testing. The random seed is printed to stderr, and an additional option enables providing a specific seed in order to reproduce a particular random profile.
1 parent 8e6856e commit 2bd4d3b

File tree

3 files changed

+73
-3
lines changed

3 files changed

+73
-3
lines changed

llvm/include/llvm/ProfileData/MemProf.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,15 @@ struct PortableMemInfoBlock {
147147
return Name; \
148148
}
149149
#include "llvm/ProfileData/MIBEntryDef.inc"
150+
#undef MIBEntryDef
151+
152+
// Define setters for each type which can be called by the writer.
153+
#define MIBEntryDef(NameTag, Name, Type) \
154+
void set##Name(Type NewVal) { \
155+
assert(Schema[llvm::to_underlying(Meta::Name)]); \
156+
Name = NewVal; \
157+
}
158+
#include "llvm/ProfileData/MIBEntryDef.inc"
150159
#undef MIBEntryDef
151160

152161
void clear() { *this = PortableMemInfoBlock(); }

llvm/lib/ProfileData/InstrProfWriter.cpp

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/ProfileData/InstrProf.h"
2020
#include "llvm/ProfileData/MemProf.h"
2121
#include "llvm/ProfileData/ProfileCommon.h"
22+
#include "llvm/Support/CommandLine.h"
2223
#include "llvm/Support/Compression.h"
2324
#include "llvm/Support/Endian.h"
2425
#include "llvm/Support/EndianStream.h"
@@ -36,6 +37,14 @@
3637

3738
using namespace llvm;
3839

40+
static cl::opt<bool>
41+
MemprofGenerateRandomHotness("memprof-random-hotness", cl::init(false),
42+
cl::Hidden,
43+
cl::desc("Generate random hotness values"));
44+
static cl::opt<unsigned> MemprofGenerateRandomHotnessSeed(
45+
"memprof-random-hotness-seed", cl::init(0), cl::Hidden,
46+
cl::desc("Random hotness seed to use (0 to generate new seed)"));
47+
3948
// A struct to define how the data stream should be patched. For Indexed
4049
// profiling, only uint64_t data type is needed.
4150
struct PatchItem {
@@ -190,7 +199,16 @@ InstrProfWriter::InstrProfWriter(
190199
InfoObj(new InstrProfRecordWriterTrait()),
191200
WritePrevVersion(WritePrevVersion),
192201
MemProfVersionRequested(MemProfVersionRequested),
193-
MemProfFullSchema(MemProfFullSchema) {}
202+
MemProfFullSchema(MemProfFullSchema) {
203+
// Set up the random number seed if requested.
204+
if (MemprofGenerateRandomHotness) {
205+
unsigned seed = MemprofGenerateRandomHotnessSeed
206+
? MemprofGenerateRandomHotnessSeed
207+
: std::time(nullptr);
208+
errs() << "random hotness seed = " << seed << "\n";
209+
std::srand(seed);
210+
}
211+
}
194212

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

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

274292
void InstrProfWriter::addMemProfRecord(
275293
const Function::GUID Id, const memprof::IndexedMemProfRecord &Record) {
276-
auto [Iter, Inserted] = MemProfData.Records.insert({Id, Record});
294+
auto NewRecord = Record;
295+
// Provoke random hotness values if requested. We specify the lifetime access
296+
// density and lifetime length that will result in a cold or not cold hotness.
297+
// See the logic in getAllocType() in Analysis/MemoryProfileInfo.cpp.
298+
if (MemprofGenerateRandomHotness) {
299+
for (auto &Alloc : NewRecord.AllocSites) {
300+
uint64_t NewTLAD = 0;
301+
uint64_t NewTL = 0;
302+
bool IsCold = std::rand() % 2;
303+
if (IsCold) {
304+
// To get a cold context, set the lifetime access density to 0 and the
305+
// lifetime to the maximum value.
306+
NewTLAD = 0;
307+
NewTL = std::numeric_limits<uint64_t>::max();
308+
} else {
309+
// To get a not cold context, set the lifetime access density to the
310+
// maximum value and the lifetime to 0.
311+
NewTLAD = std::numeric_limits<uint64_t>::max();
312+
NewTL = 0;
313+
}
314+
Alloc.Info.setTotalLifetimeAccessDensity(NewTLAD);
315+
Alloc.Info.setTotalLifetime(NewTL);
316+
}
317+
}
318+
auto [Iter, Inserted] = MemProfData.Records.insert({Id, NewRecord});
277319
// If we inserted a new record then we are done.
278320
if (Inserted) {
279321
return;
280322
}
281323
memprof::IndexedMemProfRecord &Existing = Iter->second;
282-
Existing.merge(Record);
324+
Existing.merge(NewRecord);
283325
}
284326

285327
bool InstrProfWriter::addMemProfFrame(const memprof::FrameId Id,

llvm/test/Transforms/PGOProfile/memprof.ll

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,18 @@
6666
;; Check that the total sizes are reported if requested.
6767
; 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
6868

69+
;; Make sure we emit a random hotness seed if requested.
70+
; 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
71+
; RAND: random hotness seed =
72+
;; Can't check the exact values, but make sure applying the random profile
73+
;; succeeds with the same stats
74+
; 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
75+
76+
;; Make sure we use a specific random hotness seed if requested.
77+
; 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
78+
; RAND2: random hotness seed = 1730170724
79+
; 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
80+
6981
; MEMPROFMATCHINFO: MemProf notcold context with id 1093248920606587996 has total profiled size 10 is matched
7082
; MEMPROFMATCHINFO: MemProf notcold context with id 5725971306423925017 has total profiled size 10 is matched
7183
; MEMPROFMATCHINFO: MemProf notcold context with id 6792096022461663180 has total profiled size 10 is matched
@@ -372,6 +384,13 @@ for.end: ; preds = %for.cond
372384
; MEMPROFNOCOLINFO: ![[C10]] = !{i64 -4535090212904553409}
373385
; MEMPROFNOCOLINFO: ![[C11]] = !{i64 3577763375057267810}
374386

387+
;; For the specific random seed, this is the expected order of hotness
388+
; MEMPROFRAND2: !"cold"
389+
; MEMPROFRAND2: !"cold"
390+
; MEMPROFRAND2: !"cold"
391+
; MEMPROFRAND2: !"hot"
392+
; MEMPROFRAND2: !"hot"
393+
375394
; MEMPROFSTATS: 8 memprof - Number of alloc contexts in memory profile.
376395
; MEMPROFSTATS: 10 memprof - Number of callsites in memory profile.
377396
; MEMPROFSTATS: 6 memprof - Number of functions having valid memory profile.

0 commit comments

Comments
 (0)