about summary refs log tree commit diff
diff options
context:
space:
mode:
authorZalathar <Zalathar@users.noreply.github.com>2023-09-25 23:09:27 +1000
committerZalathar <Zalathar@users.noreply.github.com>2023-09-26 20:18:43 +1000
commit64df5a851e1cb8c2ae539aa5331d48b8f3646bf4 (patch)
tree1475cd8374d8051cfdc3b8e20159bfae12b5ed9c
parentd23062b5be6bbf5be15226c7f497c89cf7d3d6e1 (diff)
downloadrust-64df5a851e1cb8c2ae539aa5331d48b8f3646bf4.tar.gz
rust-64df5a851e1cb8c2ae539aa5331d48b8f3646bf4.zip
Skip MIR pass `UnreachablePropagation` when coverage is enabled
When coverage instrumentation and MIR opts are both enabled, coverage relies on
two assumptions:

- MIR opts that would delete `StatementKind::Coverage` statements instead move
  them into bb0 and change them to `CoverageKind::Unreachable`.

- MIR opts won't delete all `CoverageKind::Counter` statements from an
  instrumented function.

Most MIR opts naturally satisfy the second assumption, because they won't
remove coverage statements from bb0, but `UnreachablePropagation` can do so if
it finds that bb0 is unreachable. If this happens, LLVM thinks the function
isn't instrumented, and it vanishes from coverage reports.

A proper solution won't be possible until after per-function coverage info
lands in #116046, but for now we can avoid the problem by turning off this
particular pass when coverage instrumentation is enabled.
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_prop.rs6
1 files changed, 5 insertions, 1 deletions
diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs
index bd1724bf842..0b9311a20ef 100644
--- a/compiler/rustc_mir_transform/src/unreachable_prop.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs
@@ -13,7 +13,11 @@ pub struct UnreachablePropagation;
 impl MirPass<'_> for UnreachablePropagation {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
         // Enable only under -Zmir-opt-level=2 as this can make programs less debuggable.
-        sess.mir_opt_level() >= 2
+
+        // FIXME(#116171) Coverage gets confused by MIR passes that can remove all
+        // coverage statements from an instrumented function. This pass can be
+        // re-enabled when coverage codegen is robust against that happening.
+        sess.mir_opt_level() >= 2 && !sess.instrument_coverage()
     }
 
     fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {