Skip to content

Commit 8fb3161

Browse files
committed
Use CS PGO for LLVM
1 parent e86fd62 commit 8fb3161

File tree

2 files changed

+70
-7
lines changed

2 files changed

+70
-7
lines changed

src/bootstrap/llvm.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -331,15 +331,24 @@ impl Step for Llvm {
331331
// This flag makes sure `FileCheck` is copied in the final binaries directory.
332332
cfg.define("LLVM_INSTALL_UTILS", "ON");
333333

334+
let mut cxxflags = vec![];
334335
if builder.config.llvm_profile_generate {
335-
cfg.define("LLVM_BUILD_INSTRUMENTED", "IR");
336-
if let Ok(llvm_profile_dir) = std::env::var("LLVM_PROFILE_DIR") {
337-
cfg.define("LLVM_PROFILE_DATA_DIR", llvm_profile_dir);
336+
if std::env::var("LLVM_USE_CS_PGO").is_ok() {
337+
cfg.define("LLVM_BUILD_INSTRUMENTED", "CSIR");
338+
if let Ok(llvm_profile_dir) = std::env::var("LLVM_PROFILE_DIR") {
339+
cfg.define("LLVM_CSPROFILE_DATA_DIR", llvm_profile_dir);
340+
}
341+
} else {
342+
cfg.define("LLVM_BUILD_INSTRUMENTED", "IR");
343+
if let Ok(llvm_profile_dir) = std::env::var("LLVM_PROFILE_DIR") {
344+
cfg.define("LLVM_PROFILE_DATA_DIR", llvm_profile_dir);
345+
}
338346
}
339347
cfg.define("LLVM_BUILD_RUNTIME", "No");
340348
}
341349
if let Some(path) = builder.config.llvm_profile_use.as_ref() {
342-
cfg.define("LLVM_PROFDATA_FILE", &path);
350+
// cfg.define("LLVM_PROFDATA_FILE", &path);
351+
cxxflags.push(&format!("-fprofile-use={path}"));
343352
}
344353
if builder.config.llvm_bolt_profile_generate
345354
|| builder.config.llvm_bolt_profile_use.is_some()

src/ci/stage-build.py

+57-3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848

4949
LLVM_BOLT_CRATES = LLVM_PGO_CRATES
5050

51+
5152
class Pipeline:
5253
# Paths
5354
def checkout_path(self) -> Path:
@@ -86,6 +87,9 @@ def opt_artifacts(self) -> Path:
8687
def llvm_profile_dir_root(self) -> Path:
8788
return self.opt_artifacts() / "llvm-pgo"
8889

90+
def llvm_profile_merged_file_intermediate(self) -> Path:
91+
return self.opt_artifacts() / "llvm-pgo-intermediate.profdata"
92+
8993
def llvm_profile_merged_file(self) -> Path:
9094
return self.opt_artifacts() / "llvm-pgo.profdata"
9195

@@ -450,6 +454,7 @@ def cmd(
450454
)
451455
return subprocess.run(args, env=environment, check=True)
452456

457+
453458
class BenchmarkRunner:
454459
def run_rustc(self, pipeline: Pipeline):
455460
raise NotImplementedError
@@ -460,6 +465,7 @@ def run_llvm(self, pipeline: Pipeline):
460465
def run_bolt(self, pipeline: Pipeline):
461466
raise NotImplementedError
462467

468+
463469
class DefaultBenchmarkRunner(BenchmarkRunner):
464470
def run_rustc(self, pipeline: Pipeline):
465471
# Here we're profiling the `rustc` frontend, so we also include `Check`.
@@ -473,6 +479,7 @@ def run_rustc(self, pipeline: Pipeline):
473479
LLVM_PROFILE_FILE=str(pipeline.rustc_profile_template_path())
474480
)
475481
)
482+
476483
def run_llvm(self, pipeline: Pipeline):
477484
run_compiler_benchmarks(
478485
pipeline,
@@ -489,6 +496,7 @@ def run_bolt(self, pipeline: Pipeline):
489496
crates=LLVM_BOLT_CRATES
490497
)
491498

499+
492500
def run_compiler_benchmarks(
493501
pipeline: Pipeline,
494502
profiles: List[str],
@@ -622,7 +630,7 @@ def gather_llvm_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
622630

623631
runner.run_llvm(pipeline)
624632

625-
profile_path = pipeline.llvm_profile_merged_file()
633+
profile_path = pipeline.llvm_profile_merged_file_intermediate()
626634
LOGGER.info(f"Merging LLVM PGO profiles to {profile_path}")
627635
cmd([
628636
pipeline.downloaded_llvm_dir() / "bin" / "llvm-profdata",
@@ -642,13 +650,37 @@ def gather_llvm_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
642650
delete_directory(pipeline.llvm_profile_dir_root())
643651

644652

653+
def gather_llvm_cs_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
654+
LOGGER.info("Running benchmarks with CS PGO instrumented LLVM")
655+
656+
runner.run_llvm(pipeline)
657+
658+
profile_path = pipeline.llvm_profile_merged_file()
659+
LOGGER.info(f"Merging LLVM CS PGO profiles to {profile_path}")
660+
cmd([
661+
pipeline.downloaded_llvm_dir() / "bin" / "llvm-profdata",
662+
"merge",
663+
"-o", profile_path,
664+
pipeline.llvm_profile_dir_root(),
665+
pipeline.llvm_profile_merged_file_intermediate()
666+
])
667+
668+
LOGGER.info("LLVM CS PGO statistics")
669+
LOGGER.info(f"{profile_path}: {format_bytes(get_path_size(profile_path))}")
670+
LOGGER.info(
671+
f"{pipeline.llvm_profile_dir_root()}: {format_bytes(get_path_size(pipeline.llvm_profile_dir_root()))}")
672+
LOGGER.info(f"Profile file count: {count_files(pipeline.llvm_profile_dir_root())}")
673+
674+
# We don't need the individual .profraw files now that they have been merged
675+
# into a final .profdata
676+
delete_directory(pipeline.llvm_profile_dir_root())
677+
678+
645679
def gather_rustc_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
646680
LOGGER.info("Running benchmarks with PGO instrumented rustc")
647681

648-
649682
runner.run_rustc(pipeline)
650683

651-
652684
profile_path = pipeline.rustc_profile_merged_file()
653685
LOGGER.info(f"Merging Rustc PGO profiles to {profile_path}")
654686
cmd([
@@ -787,6 +819,27 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, runner: BenchmarkRu
787819
print_free_disk_space(pipeline)
788820

789821
clear_llvm_files(pipeline)
822+
823+
# Stage 1b: Build rustc + CS PGO instrumented LLVM
824+
with timer.section("Stage 1b (LLVM CS PGO)") as stage1b:
825+
with stage1.section("Build rustc and LLVM") as rustc_build:
826+
build_rustc(pipeline, args=[
827+
"--llvm-profile-generate",
828+
"--llvm-profile-use",
829+
pipeline.llvm_profile_merged_file_intermediate()
830+
], env=dict(
831+
LLVM_USE_CS_PGO="1",
832+
LLVM_PROFILE_DIR=str(pipeline.llvm_profile_dir_root() / "prof-%p"),
833+
834+
))
835+
record_metrics(pipeline, rustc_build)
836+
837+
with stage1b.section("Gather profiles"):
838+
gather_llvm_cs_profiles(pipeline, runner)
839+
print_free_disk_space(pipeline)
840+
841+
clear_llvm_files(pipeline)
842+
790843
final_build_args += [
791844
"--llvm-profile-use",
792845
pipeline.llvm_profile_merged_file()
@@ -865,6 +918,7 @@ def run(runner: BenchmarkRunner):
865918

866919
print_binary_sizes(pipeline)
867920

921+
868922
if __name__ == "__main__":
869923
runner = DefaultBenchmarkRunner()
870924
run(runner)

0 commit comments

Comments
 (0)