]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/bolt.rs
Add a linker argument back to boostrap.py
[rust.git] / src / bootstrap / bolt.rs
1 use std::path::Path;
2 use std::process::Command;
3
4 /// Uses the `llvm-bolt` binary to instrument the binary/library at the given `path` with BOLT.
5 /// When the instrumented artifact is executed, it will generate BOLT profiles into
6 /// `/tmp/prof.fdata.<pid>.fdata`.
7 pub fn instrument_with_bolt_inplace(path: &Path) {
8     let dir = std::env::temp_dir();
9     let instrumented_path = dir.join("instrumented.so");
10
11     let status = Command::new("llvm-bolt")
12         .arg("-instrument")
13         .arg(&path)
14         // Make sure that each process will write its profiles into a separate file
15         .arg("--instrumentation-file-append-pid")
16         .arg("-o")
17         .arg(&instrumented_path)
18         .status()
19         .expect("Could not instrument artifact using BOLT");
20
21     if !status.success() {
22         panic!("Could not instrument {} with BOLT, exit code {:?}", path.display(), status.code());
23     }
24
25     std::fs::copy(&instrumented_path, path).expect("Cannot copy instrumented artifact");
26     std::fs::remove_file(instrumented_path).expect("Cannot delete instrumented artifact");
27 }
28
29 /// Uses the `llvm-bolt` binary to optimize the binary/library at the given `path` with BOLT,
30 /// using merged profiles from `profile_path`.
31 ///
32 /// The recorded profiles have to be merged using the `merge-fdata` tool from LLVM and the merged
33 /// profile path should be then passed to this function.
34 pub fn optimize_library_with_bolt_inplace(path: &Path, profile_path: &Path) {
35     let dir = std::env::temp_dir();
36     let optimized_path = dir.join("optimized.so");
37
38     let status = Command::new("llvm-bolt")
39         .arg(&path)
40         .arg("-data")
41         .arg(&profile_path)
42         .arg("-o")
43         .arg(&optimized_path)
44         // Reorder basic blocks within functions
45         .arg("-reorder-blocks=ext-tsp")
46         // Reorder functions within the binary
47         .arg("-reorder-functions=hfsort+")
48         // Split function code into hot and code regions
49         .arg("-split-functions=2")
50         // Split as many basic blocks as possible
51         .arg("-split-all-cold")
52         // Move jump tables to a separate section
53         .arg("-jump-tables=move")
54         // Use GNU_STACK program header for new segment (workaround for issues with strip/objcopy)
55         .arg("-use-gnu-stack")
56         // Fold functions with identical code
57         .arg("-icf=1")
58         // Update DWARF debug info in the final binary
59         .arg("-update-debug-sections")
60         // Print optimization statistics
61         .arg("-dyno-stats")
62         .status()
63         .expect("Could not optimize artifact using BOLT");
64
65     if !status.success() {
66         panic!("Could not optimize {} with BOLT, exit code {:?}", path.display(), status.code());
67     }
68
69     std::fs::copy(&optimized_path, path).expect("Cannot copy optimized artifact");
70     std::fs::remove_file(optimized_path).expect("Cannot delete optimized artifact");
71 }