Run LLVM coverage instrumentation passes before optimization passes
This matches the behavior of Clang and allows us to remove several hacks which were needed to ensure functions weren't optimized away before reaching the instrumentation pass.
This commit is contained in:
parent
3debe9acb8
commit
26d260bfa4
9 changed files with 91 additions and 138 deletions
|
|
@ -548,6 +548,11 @@ pub(crate) unsafe fn optimize(
|
|||
llvm::LLVMRustAddPass(fpm, find_pass("lint").unwrap());
|
||||
continue;
|
||||
}
|
||||
if pass_name == "insert-gcov-profiling" || pass_name == "instrprof" {
|
||||
// Instrumentation should be inserted before optimization.
|
||||
llvm::LLVMRustAddPass(mpm, find_pass(pass_name).unwrap());
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(pass) = find_pass(pass_name) {
|
||||
extra_passes.push(pass);
|
||||
|
|
|
|||
|
|
@ -84,14 +84,7 @@ impl<'tcx> MonoItem<'tcx> {
|
|||
.debugging_opts
|
||||
.inline_in_all_cgus
|
||||
.unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No)
|
||||
&& !tcx.sess.link_dead_code()
|
||||
&& !tcx.sess.instrument_coverage();
|
||||
// Disabled for `-Z instrument-coverage` because some LLVM optimizations can sometimes
|
||||
// break coverage results. A test that failed at certain optimization levels is now
|
||||
// validated at that optimization level (via `compile-flags` directive):
|
||||
// * `src/test/run-make-fulldeps/coverage/closure.rs` broke with `-C opt-level=2`, and
|
||||
// also required disabling `internalize_symbols` in
|
||||
// `rustc_mir/monomorphize/partitioning/mod.rs`
|
||||
&& !tcx.sess.link_dead_code();
|
||||
|
||||
match *self {
|
||||
MonoItem::Fn(ref instance) => {
|
||||
|
|
|
|||
|
|
@ -196,13 +196,7 @@ pub fn partition<'tcx>(
|
|||
|
||||
// Next we try to make as many symbols "internal" as possible, so LLVM has
|
||||
// more freedom to optimize.
|
||||
if !tcx.sess.link_dead_code() && !tcx.sess.instrument_coverage() {
|
||||
// Disabled for `-Z instrument-coverage` because some LLVM optimizations can sometimes
|
||||
// break coverage results. Tests that failed at certain optimization levels are now
|
||||
// validated at those optimization levels (via `compile-flags` directive); for example:
|
||||
// * `src/test/run-make-fulldeps/coverage/async.rs` broke with `-C opt-level=1`
|
||||
// * `src/test/run-make-fulldeps/coverage/closure.rs` broke with `-C opt-level=2`, and
|
||||
// also required disabling `generate_gcu_internal_copies` in `rustc_middle/mir/mono.rs`
|
||||
if !tcx.sess.link_dead_code() {
|
||||
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
|
||||
partitioner.internalize_symbols(cx, &mut post_inlining);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2889,17 +2889,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
|||
.emit();
|
||||
InlineAttr::None
|
||||
} else if list_contains_name(&items[..], sym::always) {
|
||||
if tcx.sess.instrument_coverage() {
|
||||
// Fixes Issue #82875. Forced inlining allows LLVM to discard functions
|
||||
// marked with `#[inline(always)]`, which can break coverage reporting if
|
||||
// that function was referenced from a coverage map.
|
||||
//
|
||||
// FIXME(#83429): Is there a better place, e.g., in codegen, to check and
|
||||
// convert `Always` to `Hint`?
|
||||
InlineAttr::Hint
|
||||
} else {
|
||||
InlineAttr::Always
|
||||
}
|
||||
InlineAttr::Always
|
||||
} else if list_contains_name(&items[..], sym::never) {
|
||||
InlineAttr::Never
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue