Name program modules by the entry's file name so profiles match in every checkout (#2462)

This commit is contained in:
Chris Tate
2026-10-28 06:43:48 -05:00
committed by GitHub
3 changed files with 22 additions and 3 deletions
+1 -1
View File
@@ -266,7 +266,7 @@ $ scriptc merge-profiles -o app.profdata profiles/*.profraw
$ scriptc build app.ts --optimization=speed --profile-use app.profdata
```
Train on workloads like the ones the program will run: code the training never reached is optimized as without a profile. The profile can be committed and reused as the program changes. Functions whose control flow changed since the profile was collected lose their profile, and the rest keep theirs, so regenerate it when much of the program has changed. [Build parallelism](/docs/how-it-works#build-parallelism) describes what a profile adds to build time.
Train on workloads like the ones the program will run: code the training never reached is optimized as without a profile. The profile can be committed and reused as the program changes, and in other checkouts and on other machines: it names functions by the entry's file name, not its directory. Functions whose control flow changed since the profile was collected lose their profile, and the rest keep theirs, so regenerate it when much of the program has changed. [Build parallelism](/docs/how-it-works#build-parallelism) describes what a profile adds to build time.
`scriptc build --profile-use` prints one line on stderr with how the profile matched the program's functions:
+11 -2
View File
@@ -44,6 +44,7 @@
#include "llvm/Support/Caching.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SHA256.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/ThreadPool.h"
@@ -465,6 +466,14 @@ std::optional<EmitFailure> writeRecordedBlocks(const EmitOptions &Options) {
return std::nullopt;
}
// The source file name a program's modules carry: the entry's file name,
// without its directory. Profiles name a module's local functions after it
// ("<name>;<function>"), so a profile collected in one checkout matches the
// builds of every other one.
std::string moduleSourceName(StringRef SourcePath) {
return sys::path::filename(SourcePath).str();
}
// Owns the analysis managers a pipeline needs for one module.
struct Pipeline {
PassInstrumentationCallbacks Callbacks;
@@ -796,7 +805,7 @@ Expected<std::unique_ptr<Module>> loadPartition(const EmitOptions &Options,
return createStringError(inconvertibleErrorCode(), Stream.str());
}
if (!Options.SourcePath.empty())
Mod->setSourceFileName(Options.SourcePath);
Mod->setSourceFileName(moduleSourceName(Options.SourcePath));
Mod->setTargetTriple(Triple(Options.Target));
Mod->setDataLayout(Machine.createDataLayout());
if (std::optional<EmitFailure> Failure = verify(*Mod, "verification_failed"))
@@ -1669,7 +1678,7 @@ int emit(const EmitOptions &Options) {
return reportError("invalid_ir", Stream.str(), Options.DiagnosticFormat);
}
if (!Options.SourcePath.empty())
Mod->setSourceFileName(Options.SourcePath);
Mod->setSourceFileName(moduleSourceName(Options.SourcePath));
std::string LookupError;
std::unique_ptr<TargetMachine> Machine =
@@ -376,6 +376,16 @@ describe.runIf(helper !== null)("LLVM profile-guided optimization", () => {
});
describe.runIf(profileLinker !== null)("with the profile runtime", () => {
test("profiles name local functions after the entry's file name, not its directory", async () => {
const dir = await mkdtemp(join(tmpdir(), "scriptc-profile-names-"));
dirs.push(dir);
const { profile } = await collect(dir, program(), 1, "names");
const { stdout } = await execFileAsync(helper!, ["profile-functions", "--input", profile]);
const { functions } = JSON.parse(stdout) as { functions: string[] };
expect(functions.filter((name) => name.startsWith("program.ts;")).length).toBeGreaterThan(0);
expect(functions.filter((name) => name.includes("/"))).toEqual([]);
});
for (const outputs of [1, 4]) {
test(`${outputs === 1 ? "one module" : "partitions"}: the merged profile guides emission`, async () => {
const dir = await mkdtemp(join(tmpdir(), "scriptc-profile-use-"));