Auto merge of #51230 - nikic:no-verify-lto, r=pnkfelix

Disable LLVM verification by default

Currently -Z no-verify only controls IR verification prior to LLVM codegen, while verification is performed unconditionally both before and after linking with (Thin)LTO.

Also wondering what the sentiment is on disabling verification by default (and e.g. only enabling it on ALT builds with assertions). This does not seem terribly useful outside of rustc development and it does seem to show up in profiles (at something like 3%).

**EDIT:** A table showing the various configurations and what is enabled when.

| Configuration | Dynamic verification performed | LLVM static assertions compiled in |
| --- | --- | --- |
| alt builds | | yes |
| nightly builds | | no |
| stable builds | | no |
| CI builds | | |
| dev builds in a checkout | | |
This commit is contained in:
bors 2018-07-11 12:12:13 +00:00
commit 11432ba980
8 changed files with 34 additions and 15 deletions

View file

@ -360,6 +360,9 @@
# Print backtrace on internal compiler errors during bootstrap # Print backtrace on internal compiler errors during bootstrap
#backtrace-on-ice = false #backtrace-on-ice = false
# Whether to verify generated LLVM IR
#verify-llvm-ir = false
# ============================================================================= # =============================================================================
# Options for specific targets # Options for specific targets
# #

View file

@ -283,6 +283,10 @@ fn main() {
cmd.arg("--cfg").arg("parallel_queries"); cmd.arg("--cfg").arg("parallel_queries");
} }
if env::var_os("RUSTC_VERIFY_LLVM_IR").is_some() {
cmd.arg("-Z").arg("verify-llvm-ir");
}
let color = match env::var("RUSTC_COLOR") { let color = match env::var("RUSTC_COLOR") {
Ok(s) => usize::from_str(&s).expect("RUSTC_COLOR should be an integer"), Ok(s) => usize::from_str(&s).expect("RUSTC_COLOR should be an integer"),
Err(_) => 0, Err(_) => 0,

View file

@ -922,6 +922,10 @@ impl<'a> Builder<'a> {
cargo.env("RUSTC_BACKTRACE_ON_ICE", "1"); cargo.env("RUSTC_BACKTRACE_ON_ICE", "1");
} }
if self.config.rust_verify_llvm_ir {
cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
}
cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity)); cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity));
// in std, we want to avoid denying warnings for stage 0 as that makes cfg's painful. // in std, we want to avoid denying warnings for stage 0 as that makes cfg's painful.

View file

@ -105,6 +105,7 @@ pub struct Config {
pub rust_dist_src: bool, pub rust_dist_src: bool,
pub rust_codegen_backends: Vec<Interned<String>>, pub rust_codegen_backends: Vec<Interned<String>>,
pub rust_codegen_backends_dir: String, pub rust_codegen_backends_dir: String,
pub rust_verify_llvm_ir: bool,
pub build: Interned<String>, pub build: Interned<String>,
pub hosts: Vec<Interned<String>>, pub hosts: Vec<Interned<String>>,
@ -312,6 +313,7 @@ struct Rust {
llvm_tools: Option<bool>, llvm_tools: Option<bool>,
deny_warnings: Option<bool>, deny_warnings: Option<bool>,
backtrace_on_ice: Option<bool>, backtrace_on_ice: Option<bool>,
verify_llvm_ir: Option<bool>,
} }
/// TOML representation of how each build target is configured. /// TOML representation of how each build target is configured.
@ -543,6 +545,7 @@ impl Config {
config.save_toolstates = rust.save_toolstates.clone().map(PathBuf::from); config.save_toolstates = rust.save_toolstates.clone().map(PathBuf::from);
set(&mut config.deny_warnings, rust.deny_warnings.or(flags.warnings)); set(&mut config.deny_warnings, rust.deny_warnings.or(flags.warnings));
set(&mut config.backtrace_on_ice, rust.backtrace_on_ice); set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
if let Some(ref backends) = rust.codegen_backends { if let Some(ref backends) = rust.codegen_backends {
config.rust_codegen_backends = backends.iter() config.rust_codegen_backends = backends.iter()

View file

@ -1151,8 +1151,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"gather codegen statistics"), "gather codegen statistics"),
asm_comments: bool = (false, parse_bool, [TRACKED], asm_comments: bool = (false, parse_bool, [TRACKED],
"generate comments into the assembly (may change behavior)"), "generate comments into the assembly (may change behavior)"),
no_verify: bool = (false, parse_bool, [TRACKED], verify_llvm_ir: bool = (false, parse_bool, [TRACKED],
"skip LLVM verification"), "verify LLVM IR"),
borrowck_stats: bool = (false, parse_bool, [UNTRACKED], borrowck_stats: bool = (false, parse_bool, [UNTRACKED],
"gather borrowck statistics"), "gather borrowck statistics"),
no_landing_pads: bool = (false, parse_bool, [TRACKED], no_landing_pads: bool = (false, parse_bool, [TRACKED],
@ -3114,7 +3114,7 @@ mod tests {
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone(); opts = reference.clone();
opts.debugging_opts.no_verify = true; opts.debugging_opts.verify_llvm_ir = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone(); opts = reference.clone();

View file

@ -516,8 +516,8 @@ impl Session {
pub fn asm_comments(&self) -> bool { pub fn asm_comments(&self) -> bool {
self.opts.debugging_opts.asm_comments self.opts.debugging_opts.asm_comments
} }
pub fn no_verify(&self) -> bool { pub fn verify_llvm_ir(&self) -> bool {
self.opts.debugging_opts.no_verify self.opts.debugging_opts.verify_llvm_ir
} }
pub fn borrowck_stats(&self) -> bool { pub fn borrowck_stats(&self) -> bool {
self.opts.debugging_opts.borrowck_stats self.opts.debugging_opts.borrowck_stats

View file

@ -461,9 +461,12 @@ fn run_pass_manager(cgcx: &CodegenContext,
unsafe { unsafe {
let pm = llvm::LLVMCreatePassManager(); let pm = llvm::LLVMCreatePassManager();
llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod); llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
assert!(!pass.is_null()); if config.verify_llvm_ir {
llvm::LLVMRustAddPass(pm, pass); let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
assert!(!pass.is_null());
llvm::LLVMRustAddPass(pm, pass);
}
// When optimizing for LTO we don't actually pass in `-O0`, but we force // When optimizing for LTO we don't actually pass in `-O0`, but we force
// it to always happen at least with `-O1`. // it to always happen at least with `-O1`.
@ -494,9 +497,11 @@ fn run_pass_manager(cgcx: &CodegenContext,
} }
}); });
let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _); if config.verify_llvm_ir {
assert!(!pass.is_null()); let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
llvm::LLVMRustAddPass(pm, pass); assert!(!pass.is_null());
llvm::LLVMRustAddPass(pm, pass);
}
time_ext(cgcx.time_passes, None, "LTO passes", || time_ext(cgcx.time_passes, None, "LTO passes", ||
llvm::LLVMRunPassManager(pm, llmod)); llvm::LLVMRunPassManager(pm, llmod));

View file

@ -232,7 +232,7 @@ pub struct ModuleConfig {
emit_obj: bool, emit_obj: bool,
// Miscellaneous flags. These are mostly copied from command-line // Miscellaneous flags. These are mostly copied from command-line
// options. // options.
no_verify: bool, pub verify_llvm_ir: bool,
no_prepopulate_passes: bool, no_prepopulate_passes: bool,
no_builtins: bool, no_builtins: bool,
time_passes: bool, time_passes: bool,
@ -271,7 +271,7 @@ impl ModuleConfig {
embed_bitcode_marker: false, embed_bitcode_marker: false,
no_integrated_as: false, no_integrated_as: false,
no_verify: false, verify_llvm_ir: false,
no_prepopulate_passes: false, no_prepopulate_passes: false,
no_builtins: false, no_builtins: false,
time_passes: false, time_passes: false,
@ -283,7 +283,7 @@ impl ModuleConfig {
} }
fn set_flags(&mut self, sess: &Session, no_builtins: bool) { fn set_flags(&mut self, sess: &Session, no_builtins: bool) {
self.no_verify = sess.no_verify(); self.verify_llvm_ir = sess.verify_llvm_ir();
self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes; self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes;
self.no_builtins = no_builtins || sess.target.target.options.no_builtins; self.no_builtins = no_builtins || sess.target.target.options.no_builtins;
self.time_passes = sess.time_passes(); self.time_passes = sess.time_passes();
@ -542,7 +542,7 @@ unsafe fn optimize(cgcx: &CodegenContext,
true true
}; };
if !config.no_verify { assert!(addpass("verify")); } if config.verify_llvm_ir { assert!(addpass("verify")); }
if !config.no_prepopulate_passes { if !config.no_prepopulate_passes {
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);