|
19 | 19 | #include "llvm/ProfileData/InstrProf.h" |
20 | 20 | #include "llvm/ProfileData/MemProf.h" |
21 | 21 | #include "llvm/ProfileData/ProfileCommon.h" |
| 22 | +#include "llvm/Support/CommandLine.h" |
22 | 23 | #include "llvm/Support/Compression.h" |
23 | 24 | #include "llvm/Support/Endian.h" |
24 | 25 | #include "llvm/Support/EndianStream.h" |
|
36 | 37 |
|
37 | 38 | using namespace llvm; |
38 | 39 |
|
| 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 | + |
39 | 48 | // A struct to define how the data stream should be patched. For Indexed |
40 | 49 | // profiling, only uint64_t data type is needed. |
41 | 50 | struct PatchItem { |
@@ -190,7 +199,16 @@ InstrProfWriter::InstrProfWriter( |
190 | 199 | InfoObj(new InstrProfRecordWriterTrait()), |
191 | 200 | WritePrevVersion(WritePrevVersion), |
192 | 201 | 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 | +} |
194 | 212 |
|
195 | 213 | InstrProfWriter::~InstrProfWriter() { delete InfoObj; } |
196 | 214 |
|
@@ -273,13 +291,37 @@ void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash, |
273 | 291 |
|
274 | 292 | void InstrProfWriter::addMemProfRecord( |
275 | 293 | 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}); |
277 | 319 | // If we inserted a new record then we are done. |
278 | 320 | if (Inserted) { |
279 | 321 | return; |
280 | 322 | } |
281 | 323 | memprof::IndexedMemProfRecord &Existing = Iter->second; |
282 | | - Existing.merge(Record); |
| 324 | + Existing.merge(NewRecord); |
283 | 325 | } |
284 | 326 |
|
285 | 327 | bool InstrProfWriter::addMemProfFrame(const memprof::FrameId Id, |
|
0 commit comments