Apply BOLT optimizations without rebuilding LLVM
This commit is contained in:
parent
276b75a843
commit
c5d65aa580
@ -1,12 +1,13 @@
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
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) {
|
||||
/// Returns a path to the instrumented artifact, created in a temporary directory.
|
||||
pub fn instrument_with_bolt(path: &Path) -> PathBuf {
|
||||
let dir = std::env::temp_dir();
|
||||
let instrumented_path = dir.join("instrumented.so");
|
||||
let instrumented_path = dir.join(path.file_name().unwrap());
|
||||
|
||||
let status = Command::new("llvm-bolt")
|
||||
.arg("-instrument")
|
||||
@ -21,9 +22,7 @@ pub fn instrument_with_bolt_inplace(path: &Path) {
|
||||
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");
|
||||
instrumented_path
|
||||
}
|
||||
|
||||
/// Uses the `llvm-bolt` binary to optimize the binary/library at the given `path` with BOLT,
|
||||
@ -31,9 +30,11 @@ pub fn instrument_with_bolt_inplace(path: &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) {
|
||||
///
|
||||
/// Returns a path to the optimized artifact, created in a temporary directory.
|
||||
pub fn optimize_with_bolt(path: &Path, profile_path: &Path) -> PathBuf {
|
||||
let dir = std::env::temp_dir();
|
||||
let optimized_path = dir.join("optimized.so");
|
||||
let optimized_path = dir.join(path.file_name().unwrap());
|
||||
|
||||
let status = Command::new("llvm-bolt")
|
||||
.arg(&path)
|
||||
@ -65,7 +66,5 @@ pub fn optimize_library_with_bolt_inplace(path: &Path, profile_path: &Path) {
|
||||
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");
|
||||
optimized_path
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ use std::process::Command;
|
||||
use object::read::archive::ArchiveFile;
|
||||
use object::BinaryFormat;
|
||||
|
||||
use crate::bolt::{instrument_with_bolt, optimize_with_bolt};
|
||||
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
|
||||
use crate::cache::{Interned, INTERNER};
|
||||
use crate::channel;
|
||||
@ -1904,6 +1905,26 @@ fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
|
||||
}
|
||||
}
|
||||
|
||||
fn install_llvm_file(builder: &Builder<'_>, source: &Path, destination: &Path) {
|
||||
if source.as_os_str().is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// After LLVM is built, we modify (instrument or optimize) the libLLVM.so library file.
|
||||
// This is not done in-place so that the built LLVM files are not "tainted" with BOLT.
|
||||
// We perform the instrumentation/optimization here, on the fly, just before they are being
|
||||
// packaged into some destination directory.
|
||||
let postprocessed = if builder.config.llvm_bolt_profile_generate {
|
||||
instrument_with_bolt(source)
|
||||
} else if let Some(path) = &builder.config.llvm_bolt_profile_use {
|
||||
optimize_with_bolt(source, &Path::new(&path))
|
||||
} else {
|
||||
source.to_path_buf()
|
||||
};
|
||||
|
||||
builder.install(&postprocessed, destination, 0o644);
|
||||
}
|
||||
|
||||
/// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking.
|
||||
///
|
||||
/// Returns whether the files were actually copied.
|
||||
@ -1955,7 +1976,7 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir
|
||||
} else {
|
||||
PathBuf::from(file)
|
||||
};
|
||||
builder.install(&file, dst_libdir, 0o644);
|
||||
install_llvm_file(builder, &file, dst_libdir);
|
||||
}
|
||||
!builder.config.dry_run()
|
||||
} else {
|
||||
|
@ -16,7 +16,6 @@ use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use crate::bolt::{instrument_with_bolt_inplace, optimize_library_with_bolt_inplace};
|
||||
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
|
||||
use crate::channel;
|
||||
use crate::config::{Config, TargetSelection};
|
||||
@ -523,34 +522,12 @@ impl Step for Llvm {
|
||||
}
|
||||
}
|
||||
|
||||
// After LLVM is built, we modify (instrument or optimize) the libLLVM.so library file
|
||||
// in place. This is fine, because currently we do not support incrementally rebuilding
|
||||
// LLVM after a configuration change, so to rebuild it the build files have to be removed,
|
||||
// which will also remove these modified files.
|
||||
if builder.config.llvm_bolt_profile_generate {
|
||||
instrument_with_bolt_inplace(&get_built_llvm_lib_path(&res.llvm_config));
|
||||
}
|
||||
if let Some(path) = &builder.config.llvm_bolt_profile_use {
|
||||
optimize_library_with_bolt_inplace(
|
||||
&get_built_llvm_lib_path(&res.llvm_config),
|
||||
&Path::new(path),
|
||||
);
|
||||
}
|
||||
|
||||
t!(stamp.write());
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns path to a built LLVM library (libLLVM.so).
|
||||
/// Assumes that we have built LLVM into a single library file.
|
||||
fn get_built_llvm_lib_path(llvm_config_path: &Path) -> PathBuf {
|
||||
let mut cmd = Command::new(llvm_config_path);
|
||||
cmd.arg("--libfiles");
|
||||
PathBuf::from(output(&mut cmd).trim())
|
||||
}
|
||||
|
||||
fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
|
||||
if !builder.config.llvm_version_check {
|
||||
return;
|
||||
|
@ -805,7 +805,6 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
|
||||
gather_llvm_bolt_profiles(pipeline)
|
||||
|
||||
print_free_disk_space(pipeline)
|
||||
clear_llvm_files(pipeline)
|
||||
final_build_args += [
|
||||
"--llvm-bolt-profile-use",
|
||||
pipeline.llvm_bolt_profile_merged_file()
|
||||
|
Loading…
x
Reference in New Issue
Block a user