Skip to content
Permalink
Browse files

Stabilize profile-guided optimization.

  • Loading branch information...
michaelwoerister committed May 28, 2019
1 parent 314194e commit b7fe2ca5e09b8edab393073198f8f55e1a78079f
@@ -1221,7 +1221,11 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
linker_plugin_lto: LinkerPluginLto = (LinkerPluginLto::Disabled,
parse_linker_plugin_lto, [TRACKED],
"generate build artifacts that are compatible with linker-based LTO."),

profile_generate: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
parse_switch_with_opt_path, [TRACKED],
"compile the program with profiling instrumentation"),
profile_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"use the given `.profdata` file for profile-guided optimization"),
}

options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
@@ -1395,11 +1399,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"extra arguments to prepend to the linker invocation (space separated)"),
profile: bool = (false, parse_bool, [TRACKED],
"insert profiling code"),
pgo_gen: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
parse_switch_with_opt_path, [TRACKED],
"Generate PGO profile data, to a given file, or to the default location if it's empty."),
pgo_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"Use PGO profile data from the given profile file."),
disable_instrumentation_preinliner: bool = (false, parse_bool, [TRACKED],
"Disable the instrumentation pre-inliner, useful for profiling / PGO."),
relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
@@ -2052,13 +2051,6 @@ pub fn build_session_options_and_crate_config(
}
}

if debugging_opts.pgo_gen.enabled() && debugging_opts.pgo_use.is_some() {
early_error(
error_format,
"options `-Z pgo-gen` and `-Z pgo-use` are exclusive",
);
}

let mut output_types = BTreeMap::new();
if !debugging_opts.parse_only {
for list in matches.opt_strs("emit") {
@@ -2170,6 +2162,13 @@ pub fn build_session_options_and_crate_config(
);
}

if cg.profile_generate.enabled() && cg.profile_use.is_some() {
early_error(
error_format,
"options `-C profile-generate` and `-C profile-use` are exclusive",
);
}

let mut prints = Vec::<PrintRequest>::new();
if cg.target_cpu.as_ref().map_or(false, |s| s == "help") {
prints.push(PrintRequest::TargetCPUs);
@@ -519,11 +519,11 @@ fn test_codegen_options_tracking_hash() {
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());

opts = reference.clone();
opts.debugging_opts.pgo_gen = SwitchWithOptPath::Enabled(None);
opts.cg.profile_generate = SwitchWithOptPath::Enabled(None);
assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());

opts = reference.clone();
opts.debugging_opts.pgo_use = Some(PathBuf::from("abc"));
opts.cg.profile_use = Some(PathBuf::from("abc"));
assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());

opts = reference.clone();
@@ -1290,9 +1290,9 @@ fn validate_commandline_args_with_session_available(sess: &Session) {

// Make sure that any given profiling data actually exists so LLVM can't
// decide to silently skip PGO.
if let Some(ref path) = sess.opts.debugging_opts.pgo_use {
if let Some(ref path) = sess.opts.cg.profile_use {
if !path.exists() {
sess.err(&format!("File `{}` passed to `-Zpgo-use` does not exist.",
sess.err(&format!("File `{}` passed to `-C profile-use` does not exist.",
path.display()));
}
}
@@ -1301,7 +1301,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
// an error to combine the two for now. It always runs into an assertions
// if LLVM is built with assertions, but without assertions it sometimes
// does not crash and will probably generate a corrupted binary.
if sess.opts.debugging_opts.pgo_gen.enabled() &&
if sess.opts.cg.profile_generate.enabled() &&
sess.target.target.options.is_like_msvc &&
sess.panic_strategy() == PanicStrategy::Unwind {
sess.err("Profile-guided optimization does not yet work in conjunction \
@@ -102,8 +102,8 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
return
}

// probestack doesn't play nice either with pgo-gen.
if cx.sess().opts.debugging_opts.pgo_gen.enabled() {
// probestack doesn't play nice either with `-C profile-generate`.
if cx.sess().opts.cg.profile_generate.enabled() {
return;
}

@@ -1156,7 +1156,7 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
cmd.build_static_executable();
}

if sess.opts.debugging_opts.pgo_gen.enabled() {
if sess.opts.cg.profile_generate.enabled() {
cmd.pgo_gen();
}

@@ -203,7 +203,7 @@ fn exported_symbols_provider_local<'tcx>(
}
}

if tcx.sess.opts.debugging_opts.pgo_gen.enabled() {
if tcx.sess.opts.cg.profile_generate.enabled() {
// These are weak symbols that point to the profile version and the
// profile name, which need to be treated as exported so LTO doesn't nix
// them.
@@ -423,8 +423,8 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
modules_config.passes.push("insert-gcov-profiling".to_owned())
}

modules_config.pgo_gen = sess.opts.debugging_opts.pgo_gen.clone();
modules_config.pgo_use = sess.opts.debugging_opts.pgo_use.clone();
modules_config.pgo_gen = sess.opts.cg.profile_generate.clone();
modules_config.pgo_use = sess.opts.cg.profile_use.clone();

modules_config.opt_level = Some(sess.opts.optimize);
modules_config.opt_size = Some(sess.opts.optimize);
@@ -868,7 +868,7 @@ impl<'a> CrateLoader<'a> {

fn inject_profiler_runtime(&mut self) {
if self.sess.opts.debugging_opts.profile ||
self.sess.opts.debugging_opts.pgo_gen.enabled()
self.sess.opts.cg.profile_generate.enabled()
{
info!("loading profiler");

@@ -1,8 +1,8 @@
// Test that `-Zpgo-gen` creates expected instrumentation artifacts in LLVM IR.
// Test that `-Cprofile-generate` creates expected instrumentation artifacts in LLVM IR.
// Compiling with `-Cpanic=abort` because PGO+unwinding isn't supported on all platforms.

// needs-profiler-support
// compile-flags: -Z pgo-gen -Ccodegen-units=1 -Cpanic=abort
// compile-flags: -Cprofile-generate -Ccodegen-units=1 -Cpanic=abort

// CHECK: @__llvm_profile_raw_version =
// CHECK: @__profc_{{.*}}pgo_instrumentation{{.*}}some_function{{.*}} = private global
@@ -21,7 +21,7 @@ all: cpp-executable rust-executable

cpp-executable:
$(RUSTC) -Clinker-plugin-lto=on \
-Zpgo-gen="$(TMPDIR)"/cpp-profdata \
-Cprofile-generate="$(TMPDIR)"/cpp-profdata \
-o "$(TMPDIR)"/librustlib-xlto.a \
$(COMMON_FLAGS) \
./rustlib.rs
@@ -39,7 +39,7 @@ cpp-executable:
-o "$(TMPDIR)"/cpp-profdata/merged.profdata \
"$(TMPDIR)"/cpp-profdata/default_*.profraw
$(RUSTC) -Clinker-plugin-lto=on \
-Zpgo-use="$(TMPDIR)"/cpp-profdata/merged.profdata \
-Cprofile-use="$(TMPDIR)"/cpp-profdata/merged.profdata \
-o "$(TMPDIR)"/librustlib-xlto.a \
$(COMMON_FLAGS) \
./rustlib.rs
@@ -57,7 +57,7 @@ rust-executable:
$(CLANG) ./clib.c -fprofile-generate="$(TMPDIR)"/rs-profdata -flto=thin -c -o $(TMPDIR)/clib.o -O3
(cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o)
$(RUSTC) -Clinker-plugin-lto=on \
-Zpgo-gen="$(TMPDIR)"/rs-profdata \
-Cprofile-generate="$(TMPDIR)"/rs-profdata \
-L$(TMPDIR) \
$(COMMON_FLAGS) \
-Clinker=$(CLANG) \
@@ -78,7 +78,7 @@ rust-executable:
rm "$(TMPDIR)"/libxyz.a
(cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o)
$(RUSTC) -Clinker-plugin-lto=on \
-Zpgo-use="$(TMPDIR)"/rs-profdata/merged.profdata \
-Cprofile-use="$(TMPDIR)"/rs-profdata/merged.profdata \
-L$(TMPDIR) \
$(COMMON_FLAGS) \
-Clinker=$(CLANG) \
@@ -2,7 +2,7 @@

-include ../tools.mk

COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)"
COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Cprofile-generate="$(TMPDIR)"

# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
# https://github.com/rust-lang/rust/issues/61002
@@ -2,7 +2,7 @@

-include ../tools.mk

COMPILE_FLAGS=-O -Ccodegen-units=1 -Z pgo-gen="$(TMPDIR)"
COMPILE_FLAGS=-O -Ccodegen-units=1 -Cprofile-generate="$(TMPDIR)"

# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
# https://github.com/rust-lang/rust/issues/61002
@@ -2,7 +2,7 @@

-include ../tools.mk

COMPILE_FLAGS=-g -Z pgo-gen="$(TMPDIR)"
COMPILE_FLAGS=-g -Cprofile-generate="$(TMPDIR)"

# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
# https://github.com/rust-lang/rust/issues/61002
@@ -33,15 +33,15 @@ endif

all:
# Compile the test program with instrumentation
$(RUSTC) $(COMMON_FLAGS) -Z pgo-gen="$(TMPDIR)" main.rs
$(RUSTC) $(COMMON_FLAGS) -Cprofile-generate="$(TMPDIR)" main.rs
# Run it in order to generate some profiling data
$(call RUN,main some-argument) || exit 1
# Postprocess the profiling data so it can be used by the compiler
"$(LLVM_BIN_DIR)"/llvm-profdata merge \
-o "$(TMPDIR)"/merged.profdata \
"$(TMPDIR)"/default_*.profraw
# Compile the test program again, making use of the profiling data
$(RUSTC) $(COMMON_FLAGS) -Z pgo-use="$(TMPDIR)"/merged.profdata --emit=llvm-ir main.rs
$(RUSTC) $(COMMON_FLAGS) -Cprofile-use="$(TMPDIR)"/merged.profdata --emit=llvm-ir main.rs
# Check that the generate IR contains some things that we expect
#
# We feed the file into LLVM FileCheck tool *in reverse* so that we see the

0 comments on commit b7fe2ca

Please sign in to comment.
You can’t perform that action at this time.