Skip to content

Commit 1388ded

Browse files
committed
rewrite pgo-branch-weights (1/2)
1 parent 3cb0030 commit 1388ded

File tree

5 files changed

+166
-52
lines changed

5 files changed

+166
-52
lines changed

src/tools/run-make-support/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
pub mod cc;
77
pub mod clang;
88
pub mod diff;
9-
pub mod llvm_readobj;
9+
pub mod llvm;
1010
pub mod run;
1111
pub mod rustc;
1212
pub mod rustdoc;
@@ -23,7 +23,7 @@ pub use wasmparser;
2323
pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
2424
pub use clang::{clang, Clang};
2525
pub use diff::{diff, Diff};
26-
pub use llvm_readobj::{llvm_readobj, LlvmReadobj};
26+
pub use llvm::{llvm_profdata, llvm_readobj, LlvmProfdata, LlvmReadobj};
2727
pub use run::{run, run_fail};
2828
pub use rustc::{aux_build, rustc, Rustc};
2929
pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
use std::env;
2+
use std::path::{Path, PathBuf};
3+
use std::process::Command;
4+
5+
use crate::handle_failed_output;
6+
7+
/// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
8+
/// at `$LLVM_BIN_DIR/llvm-readobj`.
9+
pub fn llvm_readobj() -> LlvmReadobj {
10+
LlvmReadobj::new()
11+
}
12+
13+
/// Construct a new `llvm-profdata` invocation. This assumes that `llvm-profdata` is available
14+
/// at `$LLVM_BIN_DIR/llvm-profdata`.
15+
pub fn llvm_profdata() -> LlvmProfdata {
16+
LlvmProfdata::new()
17+
}
18+
19+
/// A `llvm-readobj` invocation builder.
20+
#[derive(Debug)]
21+
pub struct LlvmReadobj {
22+
cmd: Command,
23+
}
24+
25+
/// A `llvm-profdata` invocation builder.
26+
#[derive(Debug)]
27+
pub struct LlvmProfdata {
28+
cmd: Command,
29+
}
30+
31+
crate::impl_common_helpers!(LlvmReadobj);
32+
33+
/// Generate the path to the bin directory of LLVM.
34+
pub fn llvm_bin_dir() -> PathBuf {
35+
let llvm_bin_dir = env::var("LLVM_BIN_DIR")
36+
.expect("`LLVM_BIN_DIR` not specified, but this is required to find `llvm-readobj`");
37+
PathBuf::from(llvm_bin_dir);
38+
}
39+
40+
impl LlvmReadobj {
41+
/// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
42+
/// at `$LLVM_BIN_DIR/llvm-readobj`.
43+
pub fn new() -> Self {
44+
let llvm_readobj = llvm_bin_dir().join("llvm-readobj");
45+
let cmd = Command::new(llvm_readobj);
46+
Self { cmd }
47+
}
48+
49+
/// Provide an input file.
50+
pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
51+
self.cmd.arg(path.as_ref());
52+
self
53+
}
54+
55+
/// Pass `--file-header` to display file headers.
56+
pub fn file_header(&mut self) -> &mut Self {
57+
self.cmd.arg("--file-header");
58+
self
59+
}
60+
61+
/// Get the [`Output`][::std::process::Output] of the finished process.
62+
#[track_caller]
63+
pub fn command_output(&mut self) -> ::std::process::Output {
64+
self.cmd.output().expect("failed to get output of finished process")
65+
}
66+
}
67+
68+
impl LlvmProfdata {
69+
/// Construct a new `llvm-profdata` invocation. This assumes that `llvm-profdata` is available
70+
/// at `$LLVM_BIN_DIR/llvm-profdata`.
71+
pub fn new() -> Self {
72+
let llvm_profdata = llvm_bin_dir().join("llvm-profdata");
73+
let cmd = Command::new(llvm_profdata);
74+
Self { cmd }
75+
}
76+
77+
/// Provide an input file.
78+
pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
79+
self.cmd.arg("-o");
80+
self.cmd.arg(path.as_ref());
81+
self
82+
}
83+
84+
/// Specify the output file path.
85+
pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
86+
self.cmd.arg(path.as_ref());
87+
self
88+
}
89+
90+
/// Take several profile data files generated by PGO instrumentation and merge them
91+
/// together into a single indexed profile data file.
92+
pub fn merge(&mut self) -> &mut Self {
93+
self.cmd.arg("merge");
94+
self
95+
}
96+
97+
/// Get the [`Output`][::std::process::Output] of the finished process.
98+
#[track_caller]
99+
pub fn command_output(&mut self) -> ::std::process::Output {
100+
self.cmd.output().expect("failed to get output of finished process")
101+
}
102+
}

src/tools/run-make-support/src/llvm_readobj.rs

Lines changed: 0 additions & 50 deletions
This file was deleted.

src/tools/run-make-support/src/rustc.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,24 @@ impl Rustc {
125125
self
126126
}
127127

128+
/// Specify directory path used for profile generation
129+
pub fn profile_generate<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
130+
let mut arg = OsString::new();
131+
arg.push("-Cprofile-generate=");
132+
arg.push(path.as_ref());
133+
self.cmd.arg(&arg);
134+
self
135+
}
136+
137+
/// Specify directory path used for profile usage
138+
pub fn profile_use<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
139+
let mut arg = OsString::new();
140+
arg.push("-Cprofile-use=");
141+
arg.push(path.as_ref());
142+
self.cmd.arg(&arg);
143+
self
144+
}
145+
128146
/// Specify error format to use
129147
pub fn error_format(&mut self, format: &str) -> &mut Self {
130148
self.cmd.arg(format!("--error-format={format}"));
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// This test generates an instrumented binary - a program which
2+
// will keep track of how many times it calls each function, a useful
3+
// feature for optimization. Then, an argument (aaaaaaaaaaaa2bbbbbbbbbbbb2bbbbbbbbbbbbbbbbcc)
4+
// is passed into the instrumented binary, which should react with a number of function calls
5+
// fully known in advance. (For example, the letter 'a' results in calling f1())
6+
7+
// If the test passes, the expected function call count was added to the use-phase LLVM-IR.
8+
// See https://github.com/rust-lang/rust/pull/66631
9+
10+
use run_make_support::{run, rustc, tmp_dir};
11+
12+
fn main() {
13+
let common_flags = if env::consts::OS == "linux" && env::var("TARGET").unwrap_or_default().contains("x86") {
14+
"-Clink-args=-fuse-ld=gold" // FIXME, Why was there a comma at the start?
15+
} else {
16+
""
17+
};
18+
let path_prof_data_dir = tmp_dir().join("prof_data_dir");
19+
let path_merged_profdata = path_prof_data_dir.clone().join("merged.profdata");
20+
rustc().arg(common_flags).input("opaque.rs").run();
21+
fs::create_dir_all(&path_prof_data_dir);
22+
rustc().arg(common_flags)
23+
.input("interesting.rs")
24+
.profile_generate(&path_prof_data_dir)
25+
.opt()
26+
.codegen_units(1)
27+
.run();
28+
rustc().arg(common_flags)
29+
.input("main.rs")
30+
.profile_generate(&path_prof_data_dir)
31+
.opt()
32+
.run();
33+
run("main aaaaaaaaaaaa2bbbbbbbbbbbb2bbbbbbbbbbbbbbbbcc"); // FIXME, with an arg? How to pass it?
34+
llvm_profdata().merge().output(&path_merged_profdata).input(path_prof_data_dir).command_output();
35+
rustc().arg(common_flags)
36+
.input("interesting.rs")
37+
.profile_use(path_merged_profdata)
38+
.opt()
39+
.codegen_units(1)
40+
.emit("llvm-ir")
41+
.run();
42+
// FIXME, implement cat
43+
}
44+

0 commit comments

Comments
 (0)