diff options
Diffstat (limited to 'src/bootstrap/bolt.rs')
-rw-r--r-- | src/bootstrap/bolt.rs | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/bootstrap/bolt.rs b/src/bootstrap/bolt.rs new file mode 100644 index 000000000..ea37cd470 --- /dev/null +++ b/src/bootstrap/bolt.rs @@ -0,0 +1,71 @@ +use std::path::Path; +use std::process::Command; + +/// Uses the `llvm-bolt` binary to instrument the binary/library at the given `path` with BOLT. +/// When the instrumented artifact is executed, it will generate BOLT profiles into +/// `/tmp/prof.fdata.<pid>.fdata`. +pub fn instrument_with_bolt_inplace(path: &Path) { + let dir = std::env::temp_dir(); + let instrumented_path = dir.join("instrumented.so"); + + let status = Command::new("llvm-bolt") + .arg("-instrument") + .arg(&path) + // Make sure that each process will write its profiles into a separate file + .arg("--instrumentation-file-append-pid") + .arg("-o") + .arg(&instrumented_path) + .status() + .expect("Could not instrument artifact using BOLT"); + + if !status.success() { + panic!("Could not instrument {} with BOLT, exit code {:?}", path.display(), status.code()); + } + + std::fs::copy(&instrumented_path, path).expect("Cannot copy instrumented artifact"); + std::fs::remove_file(instrumented_path).expect("Cannot delete instrumented artifact"); +} + +/// Uses the `llvm-bolt` binary to optimize the binary/library at the given `path` with BOLT, +/// using merged profiles from `profile_path`. +/// +/// The recorded profiles have to be merged using the `merge-fdata` tool from LLVM and the merged +/// profile path should be then passed to this function. +pub fn optimize_library_with_bolt_inplace(path: &Path, profile_path: &Path) { + let dir = std::env::temp_dir(); + let optimized_path = dir.join("optimized.so"); + + let status = Command::new("llvm-bolt") + .arg(&path) + .arg("-data") + .arg(&profile_path) + .arg("-o") + .arg(&optimized_path) + // Reorder basic blocks within functions + .arg("-reorder-blocks=ext-tsp") + // Reorder functions within the binary + .arg("-reorder-functions=hfsort+") + // Split function code into hot and code regions + .arg("-split-functions=2") + // Split as many basic blocks as possible + .arg("-split-all-cold") + // Move jump tables to a separate section + .arg("-jump-tables=move") + // Use GNU_STACK program header for new segment (workaround for issues with strip/objcopy) + .arg("-use-gnu-stack") + // Fold functions with identical code + .arg("-icf=1") + // Update DWARF debug info in the final binary + .arg("-update-debug-sections") + // Print optimization statistics + .arg("-dyno-stats") + .status() + .expect("Could not optimize artifact using BOLT"); + + if !status.success() { + panic!("Could not optimize {} with BOLT, exit code {:?}", path.display(), status.code()); + } + + std::fs::copy(&optimized_path, path).expect("Cannot copy optimized artifact"); + std::fs::remove_file(optimized_path).expect("Cannot delete optimized artifact"); +} |