https://github.com/ellishg created https://github.com/llvm/llvm-project/pull/217083
There are two places `llvm-profdata` uses randomness. 1. To generate random hotness values in MemProf, created in https://github.com/llvm/llvm-project/pull/113998 2. To sample a set of traces here https://github.com/llvm/llvm-project/blob/bc2e50bf7baf1c52370f8d8cdfee4bba2180d27a/llvm/lib/ProfileData/InstrProfWriter.cpp#L383-L391 Prior to this PR, these used two different implementations. Apparently the implementation of `std::rand()` depends on the platform, causing the test in https://github.com/llvm/llvm-project/pull/216878 to fail on windows. Switching to `std::mt19937` should solve this problem, which is already used to sample traces. While I'm here, also create the `-random-seed` flag to replace `-memprof-random-hotness-seed`, which can be used by both uses in `llvm-profdata`. This does change some details of the MemProf use case. 1. We no longer print `random hotness seed =` to stderr 2. `-random-seed=0` now uses the default seed rather than `std::time()`. This allows these commands to be deterministic by default. >From 310e3f80e5a0a08838ed25039af6f342f48d2c4b Mon Sep 17 00:00:00 2001 From: Ellis Hoag <[email protected]> Date: Tue, 18 Aug 2026 09:44:42 -0700 Subject: [PATCH] [InstrProf] Rename --memprof-random-hotness-seed to --random-seed --- .../llvm/ProfileData/InstrProfWriter.h | 6 +- llvm/lib/ProfileData/InstrProfWriter.cpp | 18 ++---- llvm/test/Transforms/PGOProfile/memprof.ll | 14 ++--- .../llvm-profdata/merge-traces-seed.proftext | 57 +++++++++++++++++++ llvm/tools/llvm-profdata/llvm-profdata.cpp | 15 +++-- 5 files changed, 79 insertions(+), 31 deletions(-) create mode 100644 llvm/test/tools/llvm-profdata/merge-traces-seed.proftext diff --git a/llvm/include/llvm/ProfileData/InstrProfWriter.h b/llvm/include/llvm/ProfileData/InstrProfWriter.h index d551cf5307fb0..73fb9432597cf 100644 --- a/llvm/include/llvm/ProfileData/InstrProfWriter.h +++ b/llvm/include/llvm/ProfileData/InstrProfWriter.h @@ -92,9 +92,7 @@ class InstrProfWriter { public: // For memprof testing, random hotness can be assigned to the contexts if - // MemprofGenerateRandomHotness is enabled. The random seed can be either - // provided by MemprofGenerateRandomHotnessSeed, or if that is 0, one will be - // generated in the writer using the current time. + // MemprofGenerateRandomHotness is enabled. LLVM_ABI InstrProfWriter(bool Sparse = false, uint64_t TemporalProfTraceReservoirSize = 0, uint64_t MaxTemporalProfTraceLength = 0, @@ -104,7 +102,7 @@ class InstrProfWriter { memprof::MinimumSupportedVersion), bool MemProfFullSchema = false, bool MemprofGenerateRandomHotness = false, - unsigned MemprofGenerateRandomHotnessSeed = 0); + unsigned RandomSeed = 0); LLVM_ABI ~InstrProfWriter(); StringMap<ProfilingData> &getProfileData() { return FunctionData; } diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index 3dbbcc69ba9e2..52b575ad948a9 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -26,7 +26,6 @@ #include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/raw_ostream.h" #include <cstdint> -#include <ctime> #include <memory> #include <string> #include <tuple> @@ -154,8 +153,7 @@ InstrProfWriter::InstrProfWriter( bool Sparse, uint64_t TemporalProfTraceReservoirSize, uint64_t MaxTemporalProfTraceLength, bool WritePrevVersion, memprof::IndexedVersion MemProfVersionRequested, bool MemProfFullSchema, - bool MemprofGenerateRandomHotness, - unsigned MemprofGenerateRandomHotnessSeed) + bool MemprofGenerateRandomHotness, unsigned RandomSeed) : Sparse(Sparse), MaxTemporalProfTraceLength(MaxTemporalProfTraceLength), TemporalProfTraceReservoirSize(TemporalProfTraceReservoirSize), InfoObj(new InstrProfRecordWriterTrait()), @@ -163,14 +161,8 @@ InstrProfWriter::InstrProfWriter( MemProfVersionRequested(MemProfVersionRequested), MemProfFullSchema(MemProfFullSchema), MemprofGenerateRandomHotness(MemprofGenerateRandomHotness) { - // 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); - } + if (RandomSeed) + RNG.seed(RandomSeed); } InstrProfWriter::~InstrProfWriter() { delete InfoObj; } @@ -259,8 +251,8 @@ void InstrProfWriter::addMemProfRecord( // maximum value and the lifetime to 0. uint64_t NewTLAD = std::numeric_limits<uint64_t>::max(); uint64_t NewTL = 0; - bool IsCold = std::rand() % 2; - if (IsCold) { + std::bernoulli_distribution IsCold; + if (IsCold(RNG)) { // To get a cold context, set the lifetime access density to 0 and the // lifetime to the maximum value. NewTLAD = 0; diff --git a/llvm/test/Transforms/PGOProfile/memprof.ll b/llvm/test/Transforms/PGOProfile/memprof.ll index 015eea2e4a678..83cde3431b41a 100644 --- a/llvm/test/Transforms/PGOProfile/memprof.ll +++ b/llvm/test/Transforms/PGOProfile/memprof.ll @@ -1,8 +1,6 @@ ;; Tests memprof profile matching (with and without instrumentation profiles). ; RUN: rm -rf %t && split-file %s %t -;; MEMPROFRAND2 checks fail on different platforms, possibly due to different rand implementations -; REQUIRES: x86_64-linux ;; -stats requires asserts ; REQUIRES: asserts @@ -83,16 +81,14 @@ ;; the size metadata to be generated for the LTO link. ; RUN: opt < %t/a.ll -passes='memprof-use<profile-filename=%t/a.memprofdata>' -pgo-warn-missing-function -S -memprof-cloning-cold-threshold=80 -memprof-keep-all-not-cold-contexts 2>&1 | FileCheck %s --check-prefixes=TOTALSIZES,TOTALSIZESKEEPALL -;; Make sure we emit a random hotness seed if requested. -; RUN: llvm-profdata merge -memprof-random-hotness %t/a.yaml -o %t/a.memprofdatarand 2>&1 | FileCheck %s --check-prefix=RAND -; RAND: random hotness seed = +;; Make sure applying a random hotness profile succeeds. +; RUN: llvm-profdata merge -memprof-random-hotness %t/a.yaml -o %t/a.memprofdatarand ;; Can't check the exact values, but make sure applying the random profile ;; succeeds with the same stats ; RUN: opt < %t/a.ll -passes='memprof-use<profile-filename=%t/a.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 %t/a.yaml -o %t/a.memprofdatarand2 2>&1 | FileCheck %s --check-prefix=RAND2 -; RAND2: random hotness seed = 1730170724 +;; Make sure we use a specific random seed if requested. +; RUN: llvm-profdata merge -memprof-random-hotness -random-seed=1730170724 %t/a.yaml -o %t/a.memprofdatarand2 ; RUN: opt < %t/a.ll -passes='memprof-use<profile-filename=%t/a.memprofdatarand2>' -pgo-warn-missing-function -S -stats 2>&1 | FileCheck %s --check-prefixes=MEMPROFRAND2,ALL,MEMPROFONLY,MEMPROFSTATS ;; With the hot access density threshold set to 0, and hot hints enabled, @@ -463,8 +459,8 @@ for.end: ; preds = %for.cond ;; For the specific random seed, this is the expected order of hotness ; MEMPROFRAND2: !"cold" ; MEMPROFRAND2: !"cold" -; MEMPROFRAND2: !"cold" ; MEMPROFRAND2: !"notcold" +; MEMPROFRAND2: !"cold" ; MEMPROFSTATS: 8 memprof - Number of alloc contexts in memory profile. ; MEMPROFSTATS: 10 memprof - Number of callsites in memory profile. diff --git a/llvm/test/tools/llvm-profdata/merge-traces-seed.proftext b/llvm/test/tools/llvm-profdata/merge-traces-seed.proftext new file mode 100644 index 0000000000000..7fd347c24fef4 --- /dev/null +++ b/llvm/test/tools/llvm-profdata/merge-traces-seed.proftext @@ -0,0 +1,57 @@ +# RUN: llvm-profdata merge --random-seed=1234 --temporal-profile-trace-reservoir-size=2 %s --text | FileCheck %s + +# RUN: llvm-profdata merge --random-seed=5678 --temporal-profile-trace-reservoir-size=2 %s --text -o %t-1.profdata +# RUN: llvm-profdata merge --random-seed=5678 --temporal-profile-trace-reservoir-size=2 %s --text -o %t-2.profdata +# RUN: diff %t-1.profdata %t-2.profdata + +# CHECK: :temporal_prof_traces +# CHECK: # Num Temporal Profile Traces: +# CHECK-NEXT: 2 +# CHECK: # Temporal Profile Trace Stream Size: +# CHECK-NEXT: 4 +# CHECK: a, +# CHECK: d, + +# Header +:ir +:temporal_prof_traces +# Num Traces +4 +# Trace Stream Size: +4 +# Weight +1 +a +# Weight +1 +b +# Weight +1 +c +# Weight +1 +d + + +a +# Func Hash: +0x1234 +# Num Counters: +1 +# Counter Values: +101 + +b +0x5678 +1 +202 + +c +0xabcd +1 +303 + +d +0xbeef +1 +404 diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index d3c83457a5d81..1e10a070081a6 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -350,10 +350,15 @@ static cl::opt<bool> MemprofGenerateRandomHotness("memprof-random-hotness", cl::init(false), cl::Hidden, cl::sub(MergeSubcommand), cl::desc("Generate random hotness values")); -static cl::opt<unsigned> MemprofGenerateRandomHotnessSeed( - "memprof-random-hotness-seed", cl::init(0), cl::Hidden, - cl::sub(MergeSubcommand), - cl::desc("Random hotness seed to use (0 to generate new seed)")); +static cl::opt<unsigned> + RandomSeed("random-seed", cl::init(0), cl::Hidden, cl::sub(MergeSubcommand), + cl::desc("Seed for the random number generator used by " + "-memprof-random-hotness and temporal profile " + "reservoir sampling")); +static cl::alias + MemprofGenerateRandomHotnessSeed("memprof-random-hotness-seed", cl::Hidden, + cl::desc("Alias for -random-seed"), + cl::aliasopt(RandomSeed)); // Options specific to overlap subcommand. static cl::opt<std::string> BaseFilename(cl::Positional, cl::Required, @@ -659,7 +664,7 @@ struct WriterContext { uint64_t ReservoirSize = 0, uint64_t MaxTraceLength = 0) : Writer(IsSparse, ReservoirSize, MaxTraceLength, DoWritePrevVersion, MemProfVersionRequested, MemProfFullSchema, - MemprofGenerateRandomHotness, MemprofGenerateRandomHotnessSeed), + MemprofGenerateRandomHotness, RandomSeed), ErrLock(ErrLock), WriterErrorCodes(WriterErrorCodes) {} }; _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
