about summary refs log tree commit diff
path: root/tests/run-coverage
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-06-29 16:36:31 +0200
committerGitHub <noreply@github.com>2023-06-29 16:36:31 +0200
commitf00db43e97dc9a4138686e5fca0fdb0be0775eed (patch)
treea143c85fcfcc7d7af6f4882abc7586ee8c80dfe7 /tests/run-coverage
parent93a97c7a2a7d6ddcc40254331ce81f2fc1fe0790 (diff)
parent7b4e75b98965f45dd35a31968d388c7deca997a2 (diff)
Rollup merge of #112300 - Zalathar:run-coverage, r=wesleywiser
Convert `run-make/coverage-reports` tests to use a custom compiletest mode

I was frustrated by the fact that most of the coverage tests are glued together with makefiles and shell scripts, so I tried my hand at converting most of them over to a newly-implemented `run-coverage` mode/suite in compiletest.

This ~~*mostly*~~ resolves #85009, ~~though I've left a small number of the existing tests as-is because they would require more work to fix/support~~.

---

I had time to go back and add support for the more troublesome tests that I had initially skipped over, so this PR now manages to completely get rid of `run-make/coverage-reports`.

---

The patches are arranged as follows:

- Declare the new mode/suite in bootstrap
- Small changes to compiletest that will be used by the new mode
- Implement the new mode in compiletest
- Migrate most of the tests over
- Add more code to bootstrap and compiletest to support the remaining tests
- Migrate the remaining tests (with some temporary hacks to avoid re-blessing them)
- Remove the temporary hacks and re-bless the migrated tests
- Remove the unused remnants of `run-make/coverage-reports`
Diffstat (limited to 'tests/run-coverage')
-rw-r--r--tests/run-coverage/abort.coverage69
-rw-r--r--tests/run-coverage/abort.rs66
-rw-r--r--tests/run-coverage/assert.coverage34
-rw-r--r--tests/run-coverage/assert.rs32
-rw-r--r--tests/run-coverage/async.coverage139
-rw-r--r--tests/run-coverage/async.rs128
-rw-r--r--tests/run-coverage/async2.coverage116
-rw-r--r--tests/run-coverage/async2.rs69
-rw-r--r--tests/run-coverage/auxiliary/inline_always_with_dead_code.rs22
-rw-r--r--tests/run-coverage/auxiliary/unused_mod_helper.rs3
-rw-r--r--tests/run-coverage/auxiliary/used_crate.rs100
-rw-r--r--tests/run-coverage/auxiliary/used_inline_crate.rs90
-rw-r--r--tests/run-coverage/closure.coverage222
-rw-r--r--tests/run-coverage/closure.rs215
-rw-r--r--tests/run-coverage/closure_macro.coverage42
-rw-r--r--tests/run-coverage/closure_macro.rs40
-rw-r--r--tests/run-coverage/closure_macro_async.coverage83
-rw-r--r--tests/run-coverage/closure_macro_async.rs81
-rw-r--r--tests/run-coverage/conditions.coverage94
-rw-r--r--tests/run-coverage/conditions.rs87
-rw-r--r--tests/run-coverage/continue.coverage70
-rw-r--r--tests/run-coverage/continue.rs69
-rw-r--r--tests/run-coverage/dead_code.coverage39
-rw-r--r--tests/run-coverage/dead_code.rs37
-rw-r--r--tests/run-coverage/drop_trait.coverage34
-rw-r--r--tests/run-coverage/drop_trait.rs33
-rw-r--r--tests/run-coverage/generator.coverage32
-rw-r--r--tests/run-coverage/generator.rs30
-rw-r--r--tests/run-coverage/generics.coverage71
-rw-r--r--tests/run-coverage/generics.rs48
-rw-r--r--tests/run-coverage/if.coverage30
-rw-r--r--tests/run-coverage/if.rs28
-rw-r--r--tests/run-coverage/if_else.coverage41
-rw-r--r--tests/run-coverage/if_else.rs40
-rw-r--r--tests/run-coverage/inline-dead.coverage28
-rw-r--r--tests/run-coverage/inline-dead.rs27
-rw-r--r--tests/run-coverage/inline.coverage54
-rw-r--r--tests/run-coverage/inline.rs51
-rw-r--r--tests/run-coverage/inner_items.coverage60
-rw-r--r--tests/run-coverage/inner_items.rs57
-rw-r--r--tests/run-coverage/issue-83601.coverage16
-rw-r--r--tests/run-coverage/issue-83601.rs14
-rw-r--r--tests/run-coverage/issue-84561.coverage189
-rw-r--r--tests/run-coverage/issue-84561.rs182
-rw-r--r--tests/run-coverage/issue-85461.coverage36
-rw-r--r--tests/run-coverage/issue-85461.rs10
-rw-r--r--tests/run-coverage/issue-93054.coverage29
-rw-r--r--tests/run-coverage/issue-93054.rs28
-rw-r--r--tests/run-coverage/lazy_boolean.coverage64
-rw-r--r--tests/run-coverage/lazy_boolean.rs61
-rw-r--r--tests/run-coverage/loop_break_value.coverage14
-rw-r--r--tests/run-coverage/loop_break_value.rs13
-rw-r--r--tests/run-coverage/loops_branches.coverage68
-rw-r--r--tests/run-coverage/loops_branches.rs61
-rw-r--r--tests/run-coverage/match_or_pattern.coverage50
-rw-r--r--tests/run-coverage/match_or_pattern.rs45
-rw-r--r--tests/run-coverage/nested_loops.coverage26
-rw-r--r--tests/run-coverage/nested_loops.rs25
-rw-r--r--tests/run-coverage/no_cov_crate.coverage87
-rw-r--r--tests/run-coverage/no_cov_crate.rs86
-rw-r--r--tests/run-coverage/overflow.coverage64
-rw-r--r--tests/run-coverage/overflow.rs63
-rw-r--r--tests/run-coverage/panic_unwind.coverage32
-rw-r--r--tests/run-coverage/panic_unwind.rs31
-rw-r--r--tests/run-coverage/partial_eq.coverage48
-rw-r--r--tests/run-coverage/partial_eq.rs46
-rw-r--r--tests/run-coverage/simple_loop.coverage37
-rw-r--r--tests/run-coverage/simple_loop.rs35
-rw-r--r--tests/run-coverage/simple_match.coverage45
-rw-r--r--tests/run-coverage/simple_match.rs43
-rw-r--r--tests/run-coverage/sort_groups.coverage49
-rw-r--r--tests/run-coverage/sort_groups.rs23
-rw-r--r--tests/run-coverage/test_harness.coverage11
-rw-r--r--tests/run-coverage/test_harness.rs10
-rw-r--r--tests/run-coverage/tight_inf_loop.coverage6
-rw-r--r--tests/run-coverage/tight_inf_loop.rs5
-rw-r--r--tests/run-coverage/try_error_result.coverage125
-rw-r--r--tests/run-coverage/try_error_result.rs118
-rw-r--r--tests/run-coverage/unused.coverage62
-rw-r--r--tests/run-coverage/unused.rs39
-rw-r--r--tests/run-coverage/unused_mod.coverage13
-rw-r--r--tests/run-coverage/unused_mod.rs6
-rw-r--r--tests/run-coverage/uses_crate.coverage170
-rw-r--r--tests/run-coverage/uses_crate.rs19
-rw-r--r--tests/run-coverage/uses_inline_crate.coverage164
-rw-r--r--tests/run-coverage/uses_inline_crate.rs22
-rw-r--r--tests/run-coverage/while.coverage6
-rw-r--r--tests/run-coverage/while.rs5
-rw-r--r--tests/run-coverage/while_early_ret.coverage43
-rw-r--r--tests/run-coverage/while_early_ret.rs42
-rw-r--r--tests/run-coverage/yield.coverage38
-rw-r--r--tests/run-coverage/yield.rs37
92 files changed, 5172 insertions, 0 deletions
diff --git a/tests/run-coverage/abort.coverage b/tests/run-coverage/abort.coverage
new file mode 100644
index 00000000000..a71c58d618d
--- /dev/null
+++ b/tests/run-coverage/abort.coverage
@@ -0,0 +1,69 @@
+    1|       |#![feature(c_unwind)]
+    2|       |#![allow(unused_assignments)]
+    3|       |
+    4|     12|extern "C" fn might_abort(should_abort: bool) {
+    5|     12|    if should_abort {
+    6|      0|        println!("aborting...");
+    7|      0|        panic!("panics and aborts");
+    8|     12|    } else {
+    9|     12|        println!("Don't Panic");
+   10|     12|    }
+   11|     12|}
+   12|       |
+   13|      1|fn main() -> Result<(), u8> {
+   14|      1|    let mut countdown = 10;
+   15|     11|    while countdown > 0 {
+   16|     10|        if countdown < 5 {
+   17|      4|            might_abort(false);
+   18|      6|        }
+   19|       |        // See discussion (below the `Notes` section) on coverage results for the closing brace.
+   20|     10|        if countdown < 5 { might_abort(false); } // Counts for different regions on one line.
+                                       ^4                     ^6
+   21|       |        // For the following example, the closing brace is the last character on the line.
+   22|       |        // This shows the character after the closing brace is highlighted, even if that next
+   23|       |        // character is a newline.
+   24|     10|        if countdown < 5 { might_abort(false); }
+                                       ^4                     ^6
+   25|     10|        countdown -= 1;
+   26|       |    }
+   27|      1|    Ok(())
+   28|      1|}
+   29|       |
+   30|       |// Notes:
+   31|       |//   1. Compare this program and its coverage results to those of the similar tests
+   32|       |//      `panic_unwind.rs` and `try_error_result.rs`.
+   33|       |//   2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`.
+   34|       |//   3. The test does not invoke the abort. By executing to a successful completion, the coverage
+   35|       |//      results show where the program did and did not execute.
+   36|       |//   4. If the program actually aborted, the coverage counters would not be saved (which "works as
+   37|       |//      intended"). Coverage results would show no executed coverage regions.
+   38|       |//   6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status
+   39|       |//      (on Linux at least).
+   40|       |
+   41|       |/*
+   42|       |
+   43|       |Expect the following coverage results:
+   44|       |
+   45|       |```text
+   46|       |    16|     11|    while countdown > 0 {
+   47|       |    17|     10|        if countdown < 5 {
+   48|       |    18|      4|            might_abort(false);
+   49|       |    19|      6|        }
+   50|       |```
+   51|       |
+   52|       |This is actually correct.
+   53|       |
+   54|       |The condition `countdown < 5` executed 10 times (10 loop iterations).
+   55|       |
+   56|       |It evaluated to `true` 4 times, and executed the `might_abort()` call.
+   57|       |
+   58|       |It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit
+   59|       |`else`, the coverage implementation injects a counter, at the character immediately after the `if`s
+   60|       |closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the
+   61|       |non-true condition.
+   62|       |
+   63|       |As another example of why this is important, say the condition was `countdown < 50`, which is always
+   64|       |`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called.
+   65|       |The closing brace would have a count of `0`, highlighting the missed coverage.
+   66|       |*/
+
diff --git a/tests/run-coverage/abort.rs b/tests/run-coverage/abort.rs
new file mode 100644
index 00000000000..98264bdc1af
--- /dev/null
+++ b/tests/run-coverage/abort.rs
@@ -0,0 +1,66 @@
+#![feature(c_unwind)]
+#![allow(unused_assignments)]
+
+extern "C" fn might_abort(should_abort: bool) {
+    if should_abort {
+        println!("aborting...");
+        panic!("panics and aborts");
+    } else {
+        println!("Don't Panic");
+    }
+}
+
+fn main() -> Result<(), u8> {
+    let mut countdown = 10;
+    while countdown > 0 {
+        if countdown < 5 {
+            might_abort(false);
+        }
+        // See discussion (below the `Notes` section) on coverage results for the closing brace.
+        if countdown < 5 { might_abort(false); } // Counts for different regions on one line.
+        // For the following example, the closing brace is the last character on the line.
+        // This shows the character after the closing brace is highlighted, even if that next
+        // character is a newline.
+        if countdown < 5 { might_abort(false); }
+        countdown -= 1;
+    }
+    Ok(())
+}
+
+// Notes:
+//   1. Compare this program and its coverage results to those of the similar tests
+//      `panic_unwind.rs` and `try_error_result.rs`.
+//   2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`.
+//   3. The test does not invoke the abort. By executing to a successful completion, the coverage
+//      results show where the program did and did not execute.
+//   4. If the program actually aborted, the coverage counters would not be saved (which "works as
+//      intended"). Coverage results would show no executed coverage regions.
+//   6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status
+//      (on Linux at least).
+
+/*
+
+Expect the following coverage results:
+
+```text
+    16|     11|    while countdown > 0 {
+    17|     10|        if countdown < 5 {
+    18|      4|            might_abort(false);
+    19|      6|        }
+```
+
+This is actually correct.
+
+The condition `countdown < 5` executed 10 times (10 loop iterations).
+
+It evaluated to `true` 4 times, and executed the `might_abort()` call.
+
+It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit
+`else`, the coverage implementation injects a counter, at the character immediately after the `if`s
+closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the
+non-true condition.
+
+As another example of why this is important, say the condition was `countdown < 50`, which is always
+`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called.
+The closing brace would have a count of `0`, highlighting the missed coverage.
+*/
diff --git a/tests/run-coverage/assert.coverage b/tests/run-coverage/assert.coverage
new file mode 100644
index 00000000000..a7134a149e2
--- /dev/null
+++ b/tests/run-coverage/assert.coverage
@@ -0,0 +1,34 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// failure-status: 101
+    3|       |
+    4|      4|fn might_fail_assert(one_plus_one: u32) {
+    5|      4|    println!("does 1 + 1 = {}?", one_plus_one);
+    6|      4|    assert_eq!(1 + 1, one_plus_one, "the argument was wrong");
+                                                  ^1
+    7|      3|}
+    8|       |
+    9|      1|fn main() -> Result<(),u8> {
+   10|      1|    let mut countdown = 10;
+   11|     11|    while countdown > 0 {
+   12|     11|        if countdown == 1 {
+   13|      1|            might_fail_assert(3);
+   14|     10|        } else if countdown < 5 {
+   15|      3|            might_fail_assert(2);
+   16|      6|        }
+   17|     10|        countdown -= 1;
+   18|       |    }
+   19|      0|    Ok(())
+   20|      0|}
+   21|       |
+   22|       |// Notes:
+   23|       |//   1. Compare this program and its coverage results to those of the very similar test
+   24|       |//      `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`.
+   25|       |//   2. This test confirms the coverage generated when a program passes or fails an `assert!()` or
+   26|       |//      related `assert_*!()` macro.
+   27|       |//   3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce
+   28|       |//      conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to
+   29|       |//      `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails).
+   30|       |//   4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test
+   31|       |//      (and in many other coverage tests). The `Assert` terminator is typically generated by the
+   32|       |//      Rust compiler to check for runtime failures, such as numeric overflows.
+
diff --git a/tests/run-coverage/assert.rs b/tests/run-coverage/assert.rs
new file mode 100644
index 00000000000..d32a37e078e
--- /dev/null
+++ b/tests/run-coverage/assert.rs
@@ -0,0 +1,32 @@
+#![allow(unused_assignments)]
+// failure-status: 101
+
+fn might_fail_assert(one_plus_one: u32) {
+    println!("does 1 + 1 = {}?", one_plus_one);
+    assert_eq!(1 + 1, one_plus_one, "the argument was wrong");
+}
+
+fn main() -> Result<(),u8> {
+    let mut countdown = 10;
+    while countdown > 0 {
+        if countdown == 1 {
+            might_fail_assert(3);
+        } else if countdown < 5 {
+            might_fail_assert(2);
+        }
+        countdown -= 1;
+    }
+    Ok(())
+}
+
+// Notes:
+//   1. Compare this program and its coverage results to those of the very similar test
+//      `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`.
+//   2. This test confirms the coverage generated when a program passes or fails an `assert!()` or
+//      related `assert_*!()` macro.
+//   3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce
+//      conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to
+//      `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails).
+//   4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test
+//      (and in many other coverage tests). The `Assert` terminator is typically generated by the
+//      Rust compiler to check for runtime failures, such as numeric overflows.
diff --git a/tests/run-coverage/async.coverage b/tests/run-coverage/async.coverage
new file mode 100644
index 00000000000..93c1535b06b
--- /dev/null
+++ b/tests/run-coverage/async.coverage
@@ -0,0 +1,139 @@
+    1|       |#![allow(unused_assignments, dead_code)]
+    2|       |
+    3|       |// compile-flags: --edition=2018 -C opt-level=1
+    4|       |
+    5|      1|async fn c(x: u8) -> u8 {
+    6|      1|    if x == 8 {
+    7|      1|        1
+    8|       |    } else {
+    9|      0|        0
+   10|       |    }
+   11|      1|}
+   12|       |
+   13|      0|async fn d() -> u8 { 1 }
+   14|       |
+   15|      0|async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
+   16|       |
+   17|      1|async fn f() -> u8 { 1 }
+   18|       |
+   19|      0|async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
+   20|       |
+   21|      1|pub async fn g(x: u8) {
+   22|      0|    match x {
+   23|      0|        y if e().await == y => (),
+   24|      0|        y if f().await == y => (),
+   25|      0|        _ => (),
+   26|       |    }
+   27|      0|}
+   28|       |
+   29|      1|async fn h(x: usize) { // The function signature is counted when called, but the body is not
+   30|      0|                       // executed (not awaited) so the open brace has a `0` count (at least when
+   31|      0|                       // displayed with `llvm-cov show` in color-mode).
+   32|      0|    match x {
+   33|      0|        y if foo().await[y] => (),
+   34|      0|        _ => (),
+   35|       |    }
+   36|      0|}
+   37|       |
+   38|      1|async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
+   39|      1|                    // (a) the function signature, counted when the function is called; and
+   40|      1|                    // (b) the open brace for the function body, counted once when the body is
+   41|      1|                    // executed asynchronously.
+   42|      1|    match x {
+   43|      1|        y if c(x).await == y + 1 => { d().await; }
+                      ^0        ^0                  ^0  ^0
+   44|      1|        y if f().await == y + 1 => (),
+                      ^0       ^0                ^0
+   45|      1|        _ => (),
+   46|       |    }
+   47|      1|}
+   48|       |
+   49|      1|fn j(x: u8) {
+   50|      1|    // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
+   51|      1|    fn c(x: u8) -> u8 {
+   52|      1|        if x == 8 {
+   53|      1|            1 // This line appears covered, but the 1-character expression span covering the `1`
+                          ^0
+   54|      1|              // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because
+   55|      1|              // `fn j()` executes the open brace for the function body, followed by the function's
+   56|      1|              // first executable statement, `match x`. Inner function declarations are not
+   57|      1|              // "visible" to the MIR for `j()`, so the code region counts all lines between the
+   58|      1|              // open brace and the first statement as executed, which is, in a sense, true.
+   59|      1|              // `llvm-cov show` overcomes this kind of situation by showing the actual counts
+   60|      1|              // of the enclosed coverages, (that is, the `1` expression was not executed, and
+   61|      1|              // accurately displays a `0`).
+   62|      1|        } else {
+   63|      1|            0
+   64|      1|        }
+   65|      1|    }
+   66|      1|    fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
+                  ^0
+   67|      1|    fn f() -> u8 { 1 }
+   68|      1|    match x {
+   69|      1|        y if c(x) == y + 1 => { d(); }
+                      ^0                    ^0
+   70|      1|        y if f() == y + 1 => (),
+                      ^0                   ^0
+   71|      1|        _ => (),
+   72|       |    }
+   73|      1|}
+   74|       |
+   75|      0|fn k(x: u8) { // unused function
+   76|      0|    match x {
+   77|      0|        1 => (),
+   78|      0|        2 => (),
+   79|      0|        _ => (),
+   80|       |    }
+   81|      0|}
+   82|       |
+   83|      1|fn l(x: u8) {
+   84|      1|    match x {
+   85|      0|        1 => (),
+   86|      0|        2 => (),
+   87|      1|        _ => (),
+   88|       |    }
+   89|      1|}
+   90|       |
+   91|      1|async fn m(x: u8) -> u8 { x - 1 }
+                                      ^0
+   92|       |
+   93|      1|fn main() {
+   94|      1|    let _ = g(10);
+   95|      1|    let _ = h(9);
+   96|      1|    let mut future = Box::pin(i(8));
+   97|      1|    j(7);
+   98|      1|    l(6);
+   99|      1|    let _ = m(5);
+  100|      1|    executor::block_on(future.as_mut());
+  101|      1|}
+  102|       |
+  103|       |mod executor {
+  104|       |    use core::{
+  105|       |        future::Future,
+  106|       |        pin::Pin,
+  107|       |        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+  108|       |    };
+  109|       |
+  110|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+  111|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+  112|      1|        use std::hint::unreachable_unchecked;
+  113|      1|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+  114|      1|            |_| unsafe { unreachable_unchecked() }, // clone
+                              ^0
+  115|      1|            |_| unsafe { unreachable_unchecked() }, // wake
+                              ^0
+  116|      1|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+                              ^0
+  117|      1|            |_| (),
+  118|      1|        );
+  119|      1|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+  120|      1|        let mut context = Context::from_waker(&waker);
+  121|       |
+  122|       |        loop {
+  123|      1|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+  124|      1|                break val;
+  125|      0|            }
+  126|       |        }
+  127|      1|    }
+  128|       |}
+
diff --git a/tests/run-coverage/async.rs b/tests/run-coverage/async.rs
new file mode 100644
index 00000000000..efd9e62d64e
--- /dev/null
+++ b/tests/run-coverage/async.rs
@@ -0,0 +1,128 @@
+#![allow(unused_assignments, dead_code)]
+
+// compile-flags: --edition=2018 -C opt-level=1
+
+async fn c(x: u8) -> u8 {
+    if x == 8 {
+        1
+    } else {
+        0
+    }
+}
+
+async fn d() -> u8 { 1 }
+
+async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
+
+async fn f() -> u8 { 1 }
+
+async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
+
+pub async fn g(x: u8) {
+    match x {
+        y if e().await == y => (),
+        y if f().await == y => (),
+        _ => (),
+    }
+}
+
+async fn h(x: usize) { // The function signature is counted when called, but the body is not
+                       // executed (not awaited) so the open brace has a `0` count (at least when
+                       // displayed with `llvm-cov show` in color-mode).
+    match x {
+        y if foo().await[y] => (),
+        _ => (),
+    }
+}
+
+async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
+                    // (a) the function signature, counted when the function is called; and
+                    // (b) the open brace for the function body, counted once when the body is
+                    // executed asynchronously.
+    match x {
+        y if c(x).await == y + 1 => { d().await; }
+        y if f().await == y + 1 => (),
+        _ => (),
+    }
+}
+
+fn j(x: u8) {
+    // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
+    fn c(x: u8) -> u8 {
+        if x == 8 {
+            1 // This line appears covered, but the 1-character expression span covering the `1`
+              // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because
+              // `fn j()` executes the open brace for the function body, followed by the function's
+              // first executable statement, `match x`. Inner function declarations are not
+              // "visible" to the MIR for `j()`, so the code region counts all lines between the
+              // open brace and the first statement as executed, which is, in a sense, true.
+              // `llvm-cov show` overcomes this kind of situation by showing the actual counts
+              // of the enclosed coverages, (that is, the `1` expression was not executed, and
+              // accurately displays a `0`).
+        } else {
+            0
+        }
+    }
+    fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
+    fn f() -> u8 { 1 }
+    match x {
+        y if c(x) == y + 1 => { d(); }
+        y if f() == y + 1 => (),
+        _ => (),
+    }
+}
+
+fn k(x: u8) { // unused function
+    match x {
+        1 => (),
+        2 => (),
+        _ => (),
+    }
+}
+
+fn l(x: u8) {
+    match x {
+        1 => (),
+        2 => (),
+        _ => (),
+    }
+}
+
+async fn m(x: u8) -> u8 { x - 1 }
+
+fn main() {
+    let _ = g(10);
+    let _ = h(9);
+    let mut future = Box::pin(i(8));
+    j(7);
+    l(6);
+    let _ = m(5);
+    executor::block_on(future.as_mut());
+}
+
+mod executor {
+    use core::{
+        future::Future,
+        pin::Pin,
+        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+    };
+
+    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+        use std::hint::unreachable_unchecked;
+        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+            |_| unsafe { unreachable_unchecked() }, // clone
+            |_| unsafe { unreachable_unchecked() }, // wake
+            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+            |_| (),
+        );
+        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+        let mut context = Context::from_waker(&waker);
+
+        loop {
+            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+                break val;
+            }
+        }
+    }
+}
diff --git a/tests/run-coverage/async2.coverage b/tests/run-coverage/async2.coverage
new file mode 100644
index 00000000000..500dde1f269
--- /dev/null
+++ b/tests/run-coverage/async2.coverage
@@ -0,0 +1,116 @@
+    1|       |// compile-flags: --edition=2018
+    2|       |
+    3|       |use core::{
+    4|       |    future::Future,
+    5|       |    marker::Send,
+    6|       |    pin::Pin,
+    7|       |};
+    8|       |
+    9|      1|fn non_async_func() {
+   10|      1|    println!("non_async_func was covered");
+   11|      1|    let b = true;
+   12|      1|    if b {
+   13|      1|        println!("non_async_func println in block");
+   14|      1|    }
+                   ^0
+   15|      1|}
+   16|       |
+   17|       |
+   18|       |
+   19|       |
+   20|      1|async fn async_func() {
+   21|      1|    println!("async_func was covered");
+   22|      1|    let b = true;
+   23|      1|    if b {
+   24|      1|        println!("async_func println in block");
+   25|      1|    }
+                   ^0
+   26|      1|}
+   27|       |
+   28|       |
+   29|       |
+   30|       |
+   31|      1|async fn async_func_just_println() {
+   32|      1|    println!("async_func_just_println was covered");
+   33|      1|}
+   34|       |
+   35|      1|fn main() {
+   36|      1|    println!("codecovsample::main");
+   37|      1|
+   38|      1|    non_async_func();
+   39|      1|
+   40|      1|    executor::block_on(async_func());
+   41|      1|    executor::block_on(async_func_just_println());
+   42|      1|}
+   43|       |
+   44|       |mod executor {
+   45|       |    use core::{
+   46|       |        future::Future,
+   47|       |        pin::Pin,
+   48|       |        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+   49|       |    };
+   50|       |
+   51|      2|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+   52|      2|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+   53|      2|        use std::hint::unreachable_unchecked;
+   54|      2|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+   55|      2|            |_| unsafe { unreachable_unchecked() }, // clone
+                              ^0
+   56|      2|            |_| unsafe { unreachable_unchecked() }, // wake
+                              ^0
+   57|      2|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+                              ^0
+   58|      2|            |_| (),
+   59|      2|        );
+   60|      2|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+   61|      2|        let mut context = Context::from_waker(&waker);
+   62|       |
+   63|       |        loop {
+   64|      2|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+   65|      2|                break val;
+   66|      0|            }
+   67|       |        }
+   68|      2|    }
+  ------------------
+  | async2::executor::block_on::<async2::async_func::{closure#0}>:
+  |   51|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+  |   52|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+  |   53|      1|        use std::hint::unreachable_unchecked;
+  |   54|      1|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+  |   55|      1|            |_| unsafe { unreachable_unchecked() }, // clone
+  |   56|      1|            |_| unsafe { unreachable_unchecked() }, // wake
+  |   57|      1|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+  |   58|      1|            |_| (),
+  |   59|      1|        );
+  |   60|      1|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+  |   61|      1|        let mut context = Context::from_waker(&waker);
+  |   62|       |
+  |   63|       |        loop {
+  |   64|      1|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+  |   65|      1|                break val;
+  |   66|      0|            }
+  |   67|       |        }
+  |   68|      1|    }
+  ------------------
+  | async2::executor::block_on::<async2::async_func_just_println::{closure#0}>:
+  |   51|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+  |   52|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+  |   53|      1|        use std::hint::unreachable_unchecked;
+  |   54|      1|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+  |   55|      1|            |_| unsafe { unreachable_unchecked() }, // clone
+  |   56|      1|            |_| unsafe { unreachable_unchecked() }, // wake
+  |   57|      1|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+  |   58|      1|            |_| (),
+  |   59|      1|        );
+  |   60|      1|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+  |   61|      1|        let mut context = Context::from_waker(&waker);
+  |   62|       |
+  |   63|       |        loop {
+  |   64|      1|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+  |   65|      1|                break val;
+  |   66|      0|            }
+  |   67|       |        }
+  |   68|      1|    }
+  ------------------
+   69|       |}
+
diff --git a/tests/run-coverage/async2.rs b/tests/run-coverage/async2.rs
new file mode 100644
index 00000000000..959d48ce9db
--- /dev/null
+++ b/tests/run-coverage/async2.rs
@@ -0,0 +1,69 @@
+// compile-flags: --edition=2018
+
+use core::{
+    future::Future,
+    marker::Send,
+    pin::Pin,
+};
+
+fn non_async_func() {
+    println!("non_async_func was covered");
+    let b = true;
+    if b {
+        println!("non_async_func println in block");
+    }
+}
+
+
+
+
+async fn async_func() {
+    println!("async_func was covered");
+    let b = true;
+    if b {
+        println!("async_func println in block");
+    }
+}
+
+
+
+
+async fn async_func_just_println() {
+    println!("async_func_just_println was covered");
+}
+
+fn main() {
+    println!("codecovsample::main");
+
+    non_async_func();
+
+    executor::block_on(async_func());
+    executor::block_on(async_func_just_println());
+}
+
+mod executor {
+    use core::{
+        future::Future,
+        pin::Pin,
+        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+    };
+
+    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+        use std::hint::unreachable_unchecked;
+        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+            |_| unsafe { unreachable_unchecked() }, // clone
+            |_| unsafe { unreachable_unchecked() }, // wake
+            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+            |_| (),
+        );
+        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+        let mut context = Context::from_waker(&waker);
+
+        loop {
+            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+                break val;
+            }
+        }
+    }
+}
diff --git a/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs b/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs
new file mode 100644
index 00000000000..2b21dee6ccf
--- /dev/null
+++ b/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0
+
+#![allow(dead_code)]
+
+mod foo {
+    #[inline(always)]
+    pub fn called() { }
+
+    fn uncalled() { }
+}
+
+pub mod bar {
+    pub fn call_me() {
+        super::foo::called();
+    }
+}
+
+pub mod baz {
+    pub fn call_me() {
+        super::foo::called();
+    }
+}
diff --git a/tests/run-coverage/auxiliary/unused_mod_helper.rs b/tests/run-coverage/auxiliary/unused_mod_helper.rs
new file mode 100644
index 00000000000..ae1cc1531ed
--- /dev/null
+++ b/tests/run-coverage/auxiliary/unused_mod_helper.rs
@@ -0,0 +1,3 @@
+pub fn never_called_function() {
+    println!("I am never called");
+}
diff --git a/tests/run-coverage/auxiliary/used_crate.rs b/tests/run-coverage/auxiliary/used_crate.rs
new file mode 100644
index 00000000000..16592d48dda
--- /dev/null
+++ b/tests/run-coverage/auxiliary/used_crate.rs
@@ -0,0 +1,100 @@
+#![allow(unused_assignments, unused_variables)]
+// compile-flags: -C opt-level=3
+use std::fmt::Debug; // ^^ validates coverage now works with optimizations
+
+pub fn used_function() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+    use_this_lib_crate();
+}
+
+pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+}
+// Expect for above function: `Unexecuted instantiation` (see below)
+pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+}
+
+pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+}
+
+pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+}
+
+pub fn unused_generic_function<T: Debug>(arg: T) {
+    println!("unused_generic_function with {:?}", arg);
+}
+
+pub fn unused_function() {
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 2;
+    if !is_true {
+        countdown = 20;
+    }
+}
+
+fn unused_private_function() {
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 2;
+    if !is_true {
+        countdown = 20;
+    }
+}
+
+fn use_this_lib_crate() {
+    used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+    used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+        "used from library used_crate.rs",
+    );
+    let some_vec = vec![5, 6, 7, 8];
+    used_only_from_this_lib_crate_generic_function(some_vec);
+    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+}
+
+// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results,
+// for example:
+//
+// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+//
+// These notices appear when `llvm-cov` shows instantiations. This may be a
+// default option, but it can be suppressed with:
+//
+// ```shell
+// $ `llvm-cov show --show-instantiations=0 ...`
+// ```
+//
+// The notice is triggered because the function is unused by the library itself,
+// and when the library is compiled, a synthetic function is generated, so
+// unused function coverage can be reported. Coverage can be skipped for unused
+// generic functions with:
+//
+// ```shell
+// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...`
+// ```
+//
+// Even though this function is used by `uses_crate.rs` (and
+// counted), with substitutions for `T`, those instantiations are only generated
+// when the generic function is actually used (from the binary, not from this
+// library crate). So the test result shows coverage for all instantiated
+// versions and their generic type substitutions, plus the `Unexecuted
+// instantiation` message for the non-substituted version. This is valid, but
+// unfortunately a little confusing.
+//
+// The library crate has its own coverage map, and the only way to show unused
+// coverage of a generic function is to include the generic function in the
+// coverage map, marked as an "unused function". If the library were used by
+// another binary that never used this generic function, then it would be valid
+// to show the unused generic, with unknown substitution (`_`).
+//
+// The alternative is to exclude all generics from being included in the "unused
+// functions" list, which would then omit coverage results for
+// `unused_generic_function<T>()`, below.
diff --git a/tests/run-coverage/auxiliary/used_inline_crate.rs b/tests/run-coverage/auxiliary/used_inline_crate.rs
new file mode 100644
index 00000000000..8b8e9d5483f
--- /dev/null
+++ b/tests/run-coverage/auxiliary/used_inline_crate.rs
@@ -0,0 +1,90 @@
+#![allow(unused_assignments, unused_variables)]
+
+// compile-flags: -C opt-level=3
+// ^^ validates coverage now works with optimizations
+use std::fmt::Debug;
+
+pub fn used_function() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+    use_this_lib_crate();
+}
+
+#[inline(always)]
+pub fn used_inline_function() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+    use_this_lib_crate();
+}
+
+
+
+
+
+
+
+#[inline(always)]
+pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+}
+// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`)
+
+#[inline(always)]
+pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+}
+
+#[inline(always)]
+pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+}
+
+#[inline(always)]
+pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+}
+
+#[inline(always)]
+pub fn unused_generic_function<T: Debug>(arg: T) {
+    println!("unused_generic_function with {:?}", arg);
+}
+
+#[inline(always)]
+pub fn unused_function() {
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 2;
+    if !is_true {
+        countdown = 20;
+    }
+}
+
+#[inline(always)]
+fn unused_private_function() {
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 2;
+    if !is_true {
+        countdown = 20;
+    }
+}
+
+fn use_this_lib_crate() {
+    used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+    used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+        "used from library used_crate.rs",
+    );
+    let some_vec = vec![5, 6, 7, 8];
+    used_only_from_this_lib_crate_generic_function(some_vec);
+    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+}
diff --git a/tests/run-coverage/closure.coverage b/tests/run-coverage/closure.coverage
new file mode 100644
index 00000000000..45d36b72e3a
--- /dev/null
+++ b/tests/run-coverage/closure.coverage
@@ -0,0 +1,222 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |// compile-flags: -C opt-level=2
+    3|      1|fn main() { // ^^ fix described in rustc_middle/mir/mono.rs
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|    let is_false = ! is_true;
+    9|      1|
+   10|      1|    let mut some_string = Some(String::from("the string content"));
+   11|      1|    println!(
+   12|      1|        "The string or alt: {}"
+   13|      1|        ,
+   14|      1|        some_string
+   15|      1|            .
+   16|      1|            unwrap_or_else
+   17|      1|        (
+   18|      1|            ||
+   19|      0|            {
+   20|      0|                let mut countdown = 0;
+   21|      0|                if is_false {
+   22|      0|                    countdown = 10;
+   23|      0|                }
+   24|      0|                "alt string 1".to_owned()
+   25|      1|            }
+   26|      1|        )
+   27|      1|    );
+   28|      1|
+   29|      1|    some_string = Some(String::from("the string content"));
+   30|      1|    let
+   31|      1|        a
+   32|       |    =
+   33|       |        ||
+   34|      0|    {
+   35|      0|        let mut countdown = 0;
+   36|      0|        if is_false {
+   37|      0|            countdown = 10;
+   38|      0|        }
+   39|      0|        "alt string 2".to_owned()
+   40|      0|    };
+   41|      1|    println!(
+   42|      1|        "The string or alt: {}"
+   43|      1|        ,
+   44|      1|        some_string
+   45|      1|            .
+   46|      1|            unwrap_or_else
+   47|      1|        (
+   48|      1|            a
+   49|      1|        )
+   50|      1|    );
+   51|      1|
+   52|      1|    some_string = None;
+   53|      1|    println!(
+   54|      1|        "The string or alt: {}"
+   55|      1|        ,
+   56|      1|        some_string
+   57|      1|            .
+   58|      1|            unwrap_or_else
+   59|      1|        (
+   60|      1|            ||
+   61|      1|            {
+   62|      1|                let mut countdown = 0;
+   63|      1|                if is_false {
+   64|      0|                    countdown = 10;
+   65|      1|                }
+   66|      1|                "alt string 3".to_owned()
+   67|      1|            }
+   68|      1|        )
+   69|      1|    );
+   70|      1|
+   71|      1|    some_string = None;
+   72|      1|    let
+   73|      1|        a
+   74|      1|    =
+   75|      1|        ||
+   76|      1|    {
+   77|      1|        let mut countdown = 0;
+   78|      1|        if is_false {
+   79|      0|            countdown = 10;
+   80|      1|        }
+   81|      1|        "alt string 4".to_owned()
+   82|      1|    };
+   83|      1|    println!(
+   84|      1|        "The string or alt: {}"
+   85|      1|        ,
+   86|      1|        some_string
+   87|      1|            .
+   88|      1|            unwrap_or_else
+   89|      1|        (
+   90|      1|            a
+   91|      1|        )
+   92|      1|    );
+   93|      1|
+   94|      1|    let
+   95|      1|        quote_closure
+   96|      1|    =
+   97|      1|        |val|
+   98|      5|    {
+   99|      5|        let mut countdown = 0;
+  100|      5|        if is_false {
+  101|      0|            countdown = 10;
+  102|      5|        }
+  103|      5|        format!("'{}'", val)
+  104|      5|    };
+  105|      1|    println!(
+  106|      1|        "Repeated, quoted string: {:?}"
+  107|      1|        ,
+  108|      1|        std::iter::repeat("repeat me")
+  109|      1|            .take(5)
+  110|      1|            .map
+  111|      1|        (
+  112|      1|            quote_closure
+  113|      1|        )
+  114|      1|            .collect::<Vec<_>>()
+  115|      1|    );
+  116|      1|
+  117|      1|    let
+  118|      1|        _unused_closure
+  119|       |    =
+  120|       |        |
+  121|       |            mut countdown
+  122|       |        |
+  123|      0|    {
+  124|      0|        if is_false {
+  125|      0|            countdown = 10;
+  126|      0|        }
+  127|      0|        "closure should be unused".to_owned()
+  128|      0|    };
+  129|       |
+  130|      1|    let mut countdown = 10;
+  131|      1|    let _short_unused_closure = | _unused_arg: u8 | countdown += 1;
+                                                                  ^0
+  132|       |
+  133|       |
+  134|      1|    let short_used_covered_closure_macro = | used_arg: u8 | println!("called");
+  135|      1|    let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called");
+                                                                              ^0
+  136|      1|    let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called");
+                                                                        ^0
+  137|       |
+  138|       |
+  139|       |
+  140|       |
+  141|      1|    let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") };
+                                                                        ^0
+  142|       |
+  143|      1|    let _shortish_unused_closure = | _unused_arg: u8 | {
+  144|      0|        println!("not called")
+  145|      0|    };
+  146|       |
+  147|      1|    let _as_short_unused_closure = |
+  148|       |        _unused_arg: u8
+  149|      0|    | { println!("not called") };
+  150|       |
+  151|      1|    let _almost_as_short_unused_closure = |
+  152|       |        _unused_arg: u8
+  153|      0|    | { println!("not called") }
+  154|       |    ;
+  155|       |
+  156|       |
+  157|       |
+  158|       |
+  159|       |
+  160|      1|    let _short_unused_closure_line_break_no_block = | _unused_arg: u8 |
+  161|      0|println!("not called")
+  162|       |    ;
+  163|       |
+  164|      1|    let _short_unused_closure_line_break_no_block2 =
+  165|       |        | _unused_arg: u8 |
+  166|      0|            println!(
+  167|      0|                "not called"
+  168|      0|            )
+  169|       |    ;
+  170|       |
+  171|      1|    let short_used_not_covered_closure_line_break_no_block_embedded_branch =
+  172|       |        | _unused_arg: u8 |
+  173|      0|            println!(
+  174|      0|                "not called: {}",
+  175|      0|                if is_true { "check" } else { "me" }
+  176|      0|            )
+  177|       |    ;
+  178|       |
+  179|      1|    let short_used_not_covered_closure_line_break_block_embedded_branch =
+  180|      1|        | _unused_arg: u8 |
+  181|      0|        {
+  182|      0|            println!(
+  183|      0|                "not called: {}",
+  184|      0|                if is_true { "check" } else { "me" }
+  185|       |            )
+  186|      0|        }
+  187|       |    ;
+  188|       |
+  189|      1|    let short_used_covered_closure_line_break_no_block_embedded_branch =
+  190|      1|        | _unused_arg: u8 |
+  191|      1|            println!(
+  192|      1|                "not called: {}",
+  193|      1|                if is_true { "check" } else { "me" }
+                                                            ^0
+  194|      1|            )
+  195|       |    ;
+  196|       |
+  197|      1|    let short_used_covered_closure_line_break_block_embedded_branch =
+  198|      1|        | _unused_arg: u8 |
+  199|      1|        {
+  200|      1|            println!(
+  201|      1|                "not called: {}",
+  202|      1|                if is_true { "check" } else { "me" }
+                                                            ^0
+  203|       |            )
+  204|      1|        }
+  205|       |    ;
+  206|       |
+  207|      1|    if is_false {
+  208|      0|        short_used_not_covered_closure_macro(0);
+  209|      0|        short_used_not_covered_closure_line_break_no_block_embedded_branch(0);
+  210|      0|        short_used_not_covered_closure_line_break_block_embedded_branch(0);
+  211|      1|    }
+  212|      1|    short_used_covered_closure_macro(0);
+  213|      1|    short_used_covered_closure_line_break_no_block_embedded_branch(0);
+  214|      1|    short_used_covered_closure_line_break_block_embedded_branch(0);
+  215|      1|}
+
diff --git a/tests/run-coverage/closure.rs b/tests/run-coverage/closure.rs
new file mode 100644
index 00000000000..eb3a1ebff88
--- /dev/null
+++ b/tests/run-coverage/closure.rs
@@ -0,0 +1,215 @@
+#![allow(unused_assignments, unused_variables)]
+// compile-flags: -C opt-level=2
+fn main() { // ^^ fix described in rustc_middle/mir/mono.rs
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+    let is_false = ! is_true;
+
+    let mut some_string = Some(String::from("the string content"));
+    println!(
+        "The string or alt: {}"
+        ,
+        some_string
+            .
+            unwrap_or_else
+        (
+            ||
+            {
+                let mut countdown = 0;
+                if is_false {
+                    countdown = 10;
+                }
+                "alt string 1".to_owned()
+            }
+        )
+    );
+
+    some_string = Some(String::from("the string content"));
+    let
+        a
+    =
+        ||
+    {
+        let mut countdown = 0;
+        if is_false {
+            countdown = 10;
+        }
+        "alt string 2".to_owned()
+    };
+    println!(
+        "The string or alt: {}"
+        ,
+        some_string
+            .
+            unwrap_or_else
+        (
+            a
+        )
+    );
+
+    some_string = None;
+    println!(
+        "The string or alt: {}"
+        ,
+        some_string
+            .
+            unwrap_or_else
+        (
+            ||
+            {
+                let mut countdown = 0;
+                if is_false {
+                    countdown = 10;
+                }
+                "alt string 3".to_owned()
+            }
+        )
+    );
+
+    some_string = None;
+    let
+        a
+    =
+        ||
+    {
+        let mut countdown = 0;
+        if is_false {
+            countdown = 10;
+        }
+        "alt string 4".to_owned()
+    };
+    println!(
+        "The string or alt: {}"
+        ,
+        some_string
+            .
+            unwrap_or_else
+        (
+            a
+        )
+    );
+
+    let
+        quote_closure
+    =
+        |val|
+    {
+        let mut countdown = 0;
+        if is_false {
+            countdown = 10;
+        }
+        format!("'{}'", val)
+    };
+    println!(
+        "Repeated, quoted string: {:?}"
+        ,
+        std::iter::repeat("repeat me")
+            .take(5)
+            .map
+        (
+            quote_closure
+        )
+            .collect::<Vec<_>>()
+    );
+
+    let
+        _unused_closure
+    =
+        |
+            mut countdown
+        |
+    {
+        if is_false {
+            countdown = 10;
+        }
+        "closure should be unused".to_owned()
+    };
+
+    let mut countdown = 10;
+    let _short_unused_closure = | _unused_arg: u8 | countdown += 1;
+
+
+    let short_used_covered_closure_macro = | used_arg: u8 | println!("called");
+    let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called");
+    let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called");
+
+
+
+
+    let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") };
+
+    let _shortish_unused_closure = | _unused_arg: u8 | {
+        println!("not called")
+    };
+
+    let _as_short_unused_closure = |
+        _unused_arg: u8
+    | { println!("not called") };
+
+    let _almost_as_short_unused_closure = |
+        _unused_arg: u8
+    | { println!("not called") }
+    ;
+
+
+
+
+
+    let _short_unused_closure_line_break_no_block = | _unused_arg: u8 |
+println!("not called")
+    ;
+
+    let _short_unused_closure_line_break_no_block2 =
+        | _unused_arg: u8 |
+            println!(
+                "not called"
+            )
+    ;
+
+    let short_used_not_covered_closure_line_break_no_block_embedded_branch =
+        | _unused_arg: u8 |
+            println!(
+                "not called: {}",
+                if is_true { "check" } else { "me" }
+            )
+    ;
+
+    let short_used_not_covered_closure_line_break_block_embedded_branch =
+        | _unused_arg: u8 |
+        {
+            println!(
+                "not called: {}",
+                if is_true { "check" } else { "me" }
+            )
+        }
+    ;
+
+    let short_used_covered_closure_line_break_no_block_embedded_branch =
+        | _unused_arg: u8 |
+            println!(
+                "not called: {}",
+                if is_true { "check" } else { "me" }
+            )
+    ;
+
+    let short_used_covered_closure_line_break_block_embedded_branch =
+        | _unused_arg: u8 |
+        {
+            println!(
+                "not called: {}",
+                if is_true { "check" } else { "me" }
+            )
+        }
+    ;
+
+    if is_false {
+        short_used_not_covered_closure_macro(0);
+        short_used_not_covered_closure_line_break_no_block_embedded_branch(0);
+        short_used_not_covered_closure_line_break_block_embedded_branch(0);
+    }
+    short_used_covered_closure_macro(0);
+    short_used_covered_closure_line_break_no_block_embedded_branch(0);
+    short_used_covered_closure_line_break_block_embedded_branch(0);
+}
diff --git a/tests/run-coverage/closure_macro.coverage b/tests/run-coverage/closure_macro.coverage
new file mode 100644
index 00000000000..87f7014760e
--- /dev/null
+++ b/tests/run-coverage/closure_macro.coverage
@@ -0,0 +1,42 @@
+    1|       |// compile-flags: --edition=2018
+    2|       |#![feature(no_coverage)]
+    3|       |
+    4|       |macro_rules! bail {
+    5|       |    ($msg:literal $(,)?) => {
+    6|       |        if $msg.len() > 0 {
+    7|       |            println!("no msg");
+    8|       |        } else {
+    9|       |            println!($msg);
+   10|       |        }
+   11|       |        return Err(String::from($msg));
+   12|       |    };
+   13|       |}
+   14|       |
+   15|       |macro_rules! on_error {
+   16|       |    ($value:expr, $error_message:expr) => {
+   17|       |        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+   18|       |            let message = format!($error_message, e);
+   19|       |            if message.len() > 0 {
+   20|       |                println!("{}", message);
+   21|       |                Ok(String::from("ok"))
+   22|       |            } else {
+   23|       |                bail!("error");
+   24|       |            }
+   25|       |        })
+   26|       |    };
+   27|       |}
+   28|       |
+   29|      1|fn load_configuration_files() -> Result<String, String> {
+   30|      1|    Ok(String::from("config"))
+   31|      1|}
+   32|       |
+   33|      1|pub fn main() -> Result<(), String> {
+   34|      1|    println!("Starting service");
+   35|      1|    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+                                                                                                 ^0
+   36|       |
+   37|      1|    let startup_delay_duration = String::from("arg");
+   38|      1|    let _ = (config, startup_delay_duration);
+   39|      1|    Ok(())
+   40|      1|}
+
diff --git a/tests/run-coverage/closure_macro.rs b/tests/run-coverage/closure_macro.rs
new file mode 100644
index 00000000000..5e3b00d1ef5
--- /dev/null
+++ b/tests/run-coverage/closure_macro.rs
@@ -0,0 +1,40 @@
+// compile-flags: --edition=2018
+#![feature(no_coverage)]
+
+macro_rules! bail {
+    ($msg:literal $(,)?) => {
+        if $msg.len() > 0 {
+            println!("no msg");
+        } else {
+            println!($msg);
+        }
+        return Err(String::from($msg));
+    };
+}
+
+macro_rules! on_error {
+    ($value:expr, $error_message:expr) => {
+        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+            let message = format!($error_message, e);
+            if message.len() > 0 {
+                println!("{}", message);
+                Ok(String::from("ok"))
+            } else {
+                bail!("error");
+            }
+        })
+    };
+}
+
+fn load_configuration_files() -> Result<String, String> {
+    Ok(String::from("config"))
+}
+
+pub fn main() -> Result<(), String> {
+    println!("Starting service");
+    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+
+    let startup_delay_duration = String::from("arg");
+    let _ = (config, startup_delay_duration);
+    Ok(())
+}
diff --git a/tests/run-coverage/closure_macro_async.coverage b/tests/run-coverage/closure_macro_async.coverage
new file mode 100644
index 00000000000..2b5418132c3
--- /dev/null
+++ b/tests/run-coverage/closure_macro_async.coverage
@@ -0,0 +1,83 @@
+    1|       |// compile-flags: --edition=2018
+    2|       |#![feature(no_coverage)]
+    3|       |
+    4|       |macro_rules! bail {
+    5|       |    ($msg:literal $(,)?) => {
+    6|       |        if $msg.len() > 0 {
+    7|       |            println!("no msg");
+    8|       |        } else {
+    9|       |            println!($msg);
+   10|       |        }
+   11|       |        return Err(String::from($msg));
+   12|       |    };
+   13|       |}
+   14|       |
+   15|       |macro_rules! on_error {
+   16|       |    ($value:expr, $error_message:expr) => {
+   17|       |        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+   18|       |            let message = format!($error_message, e);
+   19|       |            if message.len() > 0 {
+   20|       |                println!("{}", message);
+   21|       |                Ok(String::from("ok"))
+   22|       |            } else {
+   23|       |                bail!("error");
+   24|       |            }
+   25|       |        })
+   26|       |    };
+   27|       |}
+   28|       |
+   29|      1|fn load_configuration_files() -> Result<String, String> {
+   30|      1|    Ok(String::from("config"))
+   31|      1|}
+   32|       |
+   33|      1|pub async fn test() -> Result<(), String> {
+   34|      1|    println!("Starting service");
+   35|      1|    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+                                                                                                 ^0
+   36|       |
+   37|      1|    let startup_delay_duration = String::from("arg");
+   38|      1|    let _ = (config, startup_delay_duration);
+   39|      1|    Ok(())
+   40|      1|}
+   41|       |
+   42|       |#[no_coverage]
+   43|       |fn main() {
+   44|       |    executor::block_on(test());
+   45|       |}
+   46|       |
+   47|       |mod executor {
+   48|       |    use core::{
+   49|       |        future::Future,
+   50|       |        pin::Pin,
+   51|       |        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+   52|       |    };
+   53|       |
+   54|       |    #[no_coverage]
+   55|       |    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+   56|       |        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+   57|       |        use std::hint::unreachable_unchecked;
+   58|       |        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+   59|       |
+   60|       |            #[no_coverage]
+   61|       |            |_| unsafe { unreachable_unchecked() }, // clone
+   62|       |
+   63|       |            #[no_coverage]
+   64|       |            |_| unsafe { unreachable_unchecked() }, // wake
+   65|       |
+   66|       |            #[no_coverage]
+   67|       |            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+   68|       |
+   69|       |            #[no_coverage]
+   70|       |            |_| (),
+   71|       |        );
+   72|       |        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+   73|       |        let mut context = Context::from_waker(&waker);
+   74|       |
+   75|       |        loop {
+   76|       |            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+   77|       |                break val;
+   78|       |            }
+   79|       |        }
+   80|       |    }
+   81|       |}
+
diff --git a/tests/run-coverage/closure_macro_async.rs b/tests/run-coverage/closure_macro_async.rs
new file mode 100644
index 00000000000..e3e89e9c8b3
--- /dev/null
+++ b/tests/run-coverage/closure_macro_async.rs
@@ -0,0 +1,81 @@
+// compile-flags: --edition=2018
+#![feature(no_coverage)]
+
+macro_rules! bail {
+    ($msg:literal $(,)?) => {
+        if $msg.len() > 0 {
+            println!("no msg");
+        } else {
+            println!($msg);
+        }
+        return Err(String::from($msg));
+    };
+}
+
+macro_rules! on_error {
+    ($value:expr, $error_message:expr) => {
+        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+            let message = format!($error_message, e);
+            if message.len() > 0 {
+                println!("{}", message);
+                Ok(String::from("ok"))
+            } else {
+                bail!("error");
+            }
+        })
+    };
+}
+
+fn load_configuration_files() -> Result<String, String> {
+    Ok(String::from("config"))
+}
+
+pub async fn test() -> Result<(), String> {
+    println!("Starting service");
+    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+
+    let startup_delay_duration = String::from("arg");
+    let _ = (config, startup_delay_duration);
+    Ok(())
+}
+
+#[no_coverage]
+fn main() {
+    executor::block_on(test());
+}
+
+mod executor {
+    use core::{
+        future::Future,
+        pin::Pin,
+        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+    };
+
+    #[no_coverage]
+    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+        use std::hint::unreachable_unchecked;
+        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+
+            #[no_coverage]
+            |_| unsafe { unreachable_unchecked() }, // clone
+
+            #[no_coverage]
+            |_| unsafe { unreachable_unchecked() }, // wake
+
+            #[no_coverage]
+            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+
+            #[no_coverage]
+            |_| (),
+        );
+        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+        let mut context = Context::from_waker(&waker);
+
+        loop {
+            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+                break val;
+            }
+        }
+    }
+}
diff --git a/tests/run-coverage/conditions.coverage b/tests/run-coverage/conditions.coverage
new file mode 100644
index 00000000000..2d8a98a5d0c
--- /dev/null
+++ b/tests/run-coverage/conditions.coverage
@@ -0,0 +1,94 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    let mut countdown = 0;
+    5|      1|    if true {
+    6|      1|        countdown = 10;
+    7|      1|    }
+                   ^0
+    8|       |
+    9|       |    const B: u32 = 100;
+   10|      1|    let x = if countdown > 7 {
+   11|      1|        countdown -= 4;
+   12|      1|        B
+   13|      0|    } else if countdown > 2 {
+   14|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
+   15|      0|            countdown = 0;
+   16|      0|        }
+   17|      0|        countdown -= 5;
+   18|      0|        countdown
+   19|       |    } else {
+   20|      0|        return;
+   21|       |    };
+   22|       |
+   23|      1|    let mut countdown = 0;
+   24|      1|    if true {
+   25|      1|        countdown = 10;
+   26|      1|    }
+                   ^0
+   27|       |
+   28|      1|    if countdown > 7 {
+   29|      1|        countdown -= 4;
+   30|      1|    } else if countdown > 2 {
+                            ^0
+   31|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
+   32|      0|            countdown = 0;
+   33|      0|        }
+   34|      0|        countdown -= 5;
+   35|       |    } else {
+   36|      0|        return;
+   37|       |    }
+   38|       |
+   39|      1|    if true {
+   40|      1|        let mut countdown = 0;
+   41|      1|        if true {
+   42|      1|            countdown = 10;
+   43|      1|        }
+                       ^0
+   44|       |
+   45|      1|        if countdown > 7 {
+   46|      1|            countdown -= 4;
+   47|      1|        }
+   48|      0|        else if countdown > 2 {
+   49|      0|            if countdown < 1 || countdown > 5 || countdown != 9 {
+   50|      0|                countdown = 0;
+   51|      0|            }
+   52|      0|            countdown -= 5;
+   53|       |        } else {
+   54|      0|            return;
+   55|       |        }
+   56|      0|    }
+   57|       |
+   58|       |
+   59|      1|    let mut countdown = 0;
+   60|      1|    if true {
+   61|      1|        countdown = 1;
+   62|      1|    }
+                   ^0
+   63|       |
+   64|      1|    let z = if countdown > 7 {
+                      ^0
+   65|      0|        countdown -= 4;
+   66|      1|    } else if countdown > 2 {
+   67|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
+   68|      0|            countdown = 0;
+   69|      0|        }
+   70|      0|        countdown -= 5;
+   71|       |    } else {
+   72|      1|        let should_be_reachable = countdown;
+   73|      1|        println!("reached");
+   74|      1|        return;
+   75|       |    };
+   76|       |
+   77|      0|    let w = if countdown > 7 {
+   78|      0|        countdown -= 4;
+   79|      0|    } else if countdown > 2 {
+   80|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
+   81|      0|            countdown = 0;
+   82|      0|        }
+   83|      0|        countdown -= 5;
+   84|       |    } else {
+   85|      0|        return;
+   86|       |    };
+   87|      1|}
+
diff --git a/tests/run-coverage/conditions.rs b/tests/run-coverage/conditions.rs
new file mode 100644
index 00000000000..057599d1b47
--- /dev/null
+++ b/tests/run-coverage/conditions.rs
@@ -0,0 +1,87 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    let mut countdown = 0;
+    if true {
+        countdown = 10;
+    }
+
+    const B: u32 = 100;
+    let x = if countdown > 7 {
+        countdown -= 4;
+        B
+    } else if countdown > 2 {
+        if countdown < 1 || countdown > 5 || countdown != 9 {
+            countdown = 0;
+        }
+        countdown -= 5;
+        countdown
+    } else {
+        return;
+    };
+
+    let mut countdown = 0;
+    if true {
+        countdown = 10;
+    }
+
+    if countdown > 7 {
+        countdown -= 4;
+    } else if countdown > 2 {
+        if countdown < 1 || countdown > 5 || countdown != 9 {
+            countdown = 0;
+        }
+        countdown -= 5;
+    } else {
+        return;
+    }
+
+    if true {
+        let mut countdown = 0;
+        if true {
+            countdown = 10;
+        }
+
+        if countdown > 7 {
+            countdown -= 4;
+        }
+        else if countdown > 2 {
+            if countdown < 1 || countdown > 5 || countdown != 9 {
+                countdown = 0;
+            }
+            countdown -= 5;
+        } else {
+            return;
+        }
+    }
+
+
+    let mut countdown = 0;
+    if true {
+        countdown = 1;
+    }
+
+    let z = if countdown > 7 {
+        countdown -= 4;
+    } else if countdown > 2 {
+        if countdown < 1 || countdown > 5 || countdown != 9 {
+            countdown = 0;
+        }
+        countdown -= 5;
+    } else {
+        let should_be_reachable = countdown;
+        println!("reached");
+        return;
+    };
+
+    let w = if countdown > 7 {
+        countdown -= 4;
+    } else if countdown > 2 {
+        if countdown < 1 || countdown > 5 || countdown != 9 {
+            countdown = 0;
+        }
+        countdown -= 5;
+    } else {
+        return;
+    };
+}
diff --git a/tests/run-coverage/continue.coverage b/tests/run-coverage/continue.coverage
new file mode 100644
index 00000000000..bf42924b191
--- /dev/null
+++ b/tests/run-coverage/continue.coverage
@@ -0,0 +1,70 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    let is_true = std::env::args().len() == 1;
+    5|      1|
+    6|      1|    let mut x = 0;
+    7|     11|    for _ in 0..10 {
+    8|     10|        match is_true {
+    9|       |            true => {
+   10|     10|                continue;
+   11|       |            }
+   12|      0|            _ => {
+   13|      0|                x = 1;
+   14|      0|            }
+   15|      0|        }
+   16|      0|        x = 3;
+   17|       |    }
+   18|     11|    for _ in 0..10 {
+   19|     10|        match is_true {
+   20|      0|            false => {
+   21|      0|                x = 1;
+   22|      0|            }
+   23|       |            _ => {
+   24|     10|                continue;
+   25|       |            }
+   26|       |        }
+   27|      0|        x = 3;
+   28|       |    }
+   29|     11|    for _ in 0..10 {
+   30|     10|        match is_true {
+   31|     10|            true => {
+   32|     10|                x = 1;
+   33|     10|            }
+   34|       |            _ => {
+   35|      0|                continue;
+   36|       |            }
+   37|       |        }
+   38|     10|        x = 3;
+   39|       |    }
+   40|     11|    for _ in 0..10 {
+   41|     10|        if is_true {
+   42|     10|            continue;
+   43|      0|        }
+   44|      0|        x = 3;
+   45|       |    }
+   46|     11|    for _ in 0..10 {
+   47|     10|        match is_true {
+   48|      0|            false => {
+   49|      0|                x = 1;
+   50|      0|            }
+   51|     10|            _ => {
+   52|     10|                let _ = x;
+   53|     10|            }
+   54|       |        }
+   55|     10|        x = 3;
+   56|       |    }
+   57|      1|    for _ in 0..10 {
+   58|      1|        match is_true {
+   59|      0|            false => {
+   60|      0|                x = 1;
+   61|      0|            }
+   62|       |            _ => {
+   63|      1|                break;
+   64|       |            }
+   65|       |        }
+   66|      0|        x = 3;
+   67|       |    }
+   68|      1|    let _ = x;
+   69|      1|}
+
diff --git a/tests/run-coverage/continue.rs b/tests/run-coverage/continue.rs
new file mode 100644
index 00000000000..624aa98341b
--- /dev/null
+++ b/tests/run-coverage/continue.rs
@@ -0,0 +1,69 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    let is_true = std::env::args().len() == 1;
+
+    let mut x = 0;
+    for _ in 0..10 {
+        match is_true {
+            true => {
+                continue;
+            }
+            _ => {
+                x = 1;
+            }
+        }
+        x = 3;
+    }
+    for _ in 0..10 {
+        match is_true {
+            false => {
+                x = 1;
+            }
+            _ => {
+                continue;
+            }
+        }
+        x = 3;
+    }
+    for _ in 0..10 {
+        match is_true {
+            true => {
+                x = 1;
+            }
+            _ => {
+                continue;
+            }
+        }
+        x = 3;
+    }
+    for _ in 0..10 {
+        if is_true {
+            continue;
+        }
+        x = 3;
+    }
+    for _ in 0..10 {
+        match is_true {
+            false => {
+                x = 1;
+            }
+            _ => {
+                let _ = x;
+            }
+        }
+        x = 3;
+    }
+    for _ in 0..10 {
+        match is_true {
+            false => {
+                x = 1;
+            }
+            _ => {
+                break;
+            }
+        }
+        x = 3;
+    }
+    let _ = x;
+}
diff --git a/tests/run-coverage/dead_code.coverage b/tests/run-coverage/dead_code.coverage
new file mode 100644
index 00000000000..09ff14c6f27
--- /dev/null
+++ b/tests/run-coverage/dead_code.coverage
@@ -0,0 +1,39 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      0|pub fn unused_pub_fn_not_in_library() {
+    4|      0|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      0|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      0|    // dependent conditions.
+    7|      0|    let is_true = std::env::args().len() == 1;
+    8|      0|
+    9|      0|    let mut countdown = 0;
+   10|      0|    if is_true {
+   11|      0|        countdown = 10;
+   12|      0|    }
+   13|      0|}
+   14|       |
+   15|      0|fn unused_fn() {
+   16|      0|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   17|      0|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   18|      0|    // dependent conditions.
+   19|      0|    let is_true = std::env::args().len() == 1;
+   20|      0|
+   21|      0|    let mut countdown = 0;
+   22|      0|    if is_true {
+   23|      0|        countdown = 10;
+   24|      0|    }
+   25|      0|}
+   26|       |
+   27|      1|fn main() {
+   28|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   29|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   30|      1|    // dependent conditions.
+   31|      1|    let is_true = std::env::args().len() == 1;
+   32|      1|
+   33|      1|    let mut countdown = 0;
+   34|      1|    if is_true {
+   35|      1|        countdown = 10;
+   36|      1|    }
+                   ^0
+   37|      1|}
+
diff --git a/tests/run-coverage/dead_code.rs b/tests/run-coverage/dead_code.rs
new file mode 100644
index 00000000000..a1285df0ec6
--- /dev/null
+++ b/tests/run-coverage/dead_code.rs
@@ -0,0 +1,37 @@
+#![allow(unused_assignments, unused_variables)]
+
+pub fn unused_pub_fn_not_in_library() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+}
+
+fn unused_fn() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+}
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+}
diff --git a/tests/run-coverage/drop_trait.coverage b/tests/run-coverage/drop_trait.coverage
new file mode 100644
index 00000000000..293001e9590
--- /dev/null
+++ b/tests/run-coverage/drop_trait.coverage
@@ -0,0 +1,34 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// failure-status: 1
+    3|       |
+    4|       |struct Firework {
+    5|       |    strength: i32,
+    6|       |}
+    7|       |
+    8|       |impl Drop for Firework {
+    9|      2|    fn drop(&mut self) {
+   10|      2|        println!("BOOM times {}!!!", self.strength);
+   11|      2|    }
+   12|       |}
+   13|       |
+   14|      1|fn main() -> Result<(),u8> {
+   15|      1|    let _firecracker = Firework { strength: 1 };
+   16|      1|
+   17|      1|    let _tnt = Firework { strength: 100 };
+   18|      1|
+   19|      1|    if true {
+   20|      1|        println!("Exiting with error...");
+   21|      1|        return Err(1);
+   22|      0|    }
+   23|      0|
+   24|      0|    let _ = Firework { strength: 1000 };
+   25|      0|
+   26|      0|    Ok(())
+   27|      1|}
+   28|       |
+   29|       |// Expected program output:
+   30|       |//   Exiting with error...
+   31|       |//   BOOM times 100!!!
+   32|       |//   BOOM times 1!!!
+   33|       |//   Error: 1
+
diff --git a/tests/run-coverage/drop_trait.rs b/tests/run-coverage/drop_trait.rs
new file mode 100644
index 00000000000..a9b5d1d1e7f
--- /dev/null
+++ b/tests/run-coverage/drop_trait.rs
@@ -0,0 +1,33 @@
+#![allow(unused_assignments)]
+// failure-status: 1
+
+struct Firework {
+    strength: i32,
+}
+
+impl Drop for Firework {
+    fn drop(&mut self) {
+        println!("BOOM times {}!!!", self.strength);
+    }
+}
+
+fn main() -> Result<(),u8> {
+    let _firecracker = Firework { strength: 1 };
+
+    let _tnt = Firework { strength: 100 };
+
+    if true {
+        println!("Exiting with error...");
+        return Err(1);
+    }
+
+    let _ = Firework { strength: 1000 };
+
+    Ok(())
+}
+
+// Expected program output:
+//   Exiting with error...
+//   BOOM times 100!!!
+//   BOOM times 1!!!
+//   Error: 1
diff --git a/tests/run-coverage/generator.coverage b/tests/run-coverage/generator.coverage
new file mode 100644
index 00000000000..0fb3808ff2e
--- /dev/null
+++ b/tests/run-coverage/generator.coverage
@@ -0,0 +1,32 @@
+    1|       |#![feature(generators, generator_trait)]
+    2|       |
+    3|       |use std::ops::{Generator, GeneratorState};
+    4|       |use std::pin::Pin;
+    5|       |
+    6|       |// The following implementation of a function called from a `yield` statement
+    7|       |// (apparently requiring the Result and the `String` type or constructor)
+    8|       |// creates conditions where the `generator::StateTransform` MIR transform will
+    9|       |// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
+   10|       |// to handle this condition, and still report dead block coverage.
+   11|      1|fn get_u32(val: bool) -> Result<u32, String> {
+   12|      1|    if val { Ok(1) } else { Err(String::from("some error")) }
+                                          ^0
+   13|      1|}
+   14|       |
+   15|      1|fn main() {
+   16|      1|    let is_true = std::env::args().len() == 1;
+   17|      1|    let mut generator = || {
+   18|      1|        yield get_u32(is_true);
+   19|      1|        return "foo";
+   20|      1|    };
+   21|       |
+   22|      1|    match Pin::new(&mut generator).resume(()) {
+   23|      1|        GeneratorState::Yielded(Ok(1)) => {}
+   24|      0|        _ => panic!("unexpected return from resume"),
+   25|       |    }
+   26|      1|    match Pin::new(&mut generator).resume(()) {
+   27|      1|        GeneratorState::Complete("foo") => {}
+   28|      0|        _ => panic!("unexpected return from resume"),
+   29|       |    }
+   30|      1|}
+
diff --git a/tests/run-coverage/generator.rs b/tests/run-coverage/generator.rs
new file mode 100644
index 00000000000..4319991021e
--- /dev/null
+++ b/tests/run-coverage/generator.rs
@@ -0,0 +1,30 @@
+#![feature(generators, generator_trait)]
+
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
+// The following implementation of a function called from a `yield` statement
+// (apparently requiring the Result and the `String` type or constructor)
+// creates conditions where the `generator::StateTransform` MIR transform will
+// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
+// to handle this condition, and still report dead block coverage.
+fn get_u32(val: bool) -> Result<u32, String> {
+    if val { Ok(1) } else { Err(String::from("some error")) }
+}
+
+fn main() {
+    let is_true = std::env::args().len() == 1;
+    let mut generator = || {
+        yield get_u32(is_true);
+        return "foo";
+    };
+
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Yielded(Ok(1)) => {}
+        _ => panic!("unexpected return from resume"),
+    }
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Complete("foo") => {}
+        _ => panic!("unexpected return from resume"),
+    }
+}
diff --git a/tests/run-coverage/generics.coverage b/tests/run-coverage/generics.coverage
new file mode 100644
index 00000000000..7a7649674ca
--- /dev/null
+++ b/tests/run-coverage/generics.coverage
@@ -0,0 +1,71 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// failure-status: 1
+    3|       |
+    4|       |struct Firework<T> where T: Copy + std::fmt::Display {
+    5|       |    strength: T,
+    6|       |}
+    7|       |
+    8|       |impl<T> Firework<T> where T: Copy + std::fmt::Display {
+    9|       |    #[inline(always)]
+   10|      3|    fn set_strength(&mut self, new_strength: T) {
+   11|      3|        self.strength = new_strength;
+   12|      3|    }
+  ------------------
+  | <generics::Firework<f64>>::set_strength:
+  |   10|      2|    fn set_strength(&mut self, new_strength: T) {
+  |   11|      2|        self.strength = new_strength;
+  |   12|      2|    }
+  ------------------
+  | <generics::Firework<i32>>::set_strength:
+  |   10|      1|    fn set_strength(&mut self, new_strength: T) {
+  |   11|      1|        self.strength = new_strength;
+  |   12|      1|    }
+  ------------------
+   13|       |}
+   14|       |
+   15|       |impl<T> Drop for Firework<T> where T: Copy + std::fmt::Display {
+   16|       |    #[inline(always)]
+   17|      2|    fn drop(&mut self) {
+   18|      2|        println!("BOOM times {}!!!", self.strength);
+   19|      2|    }
+  ------------------
+  | <generics::Firework<f64> as core::ops::drop::Drop>::drop:
+  |   17|      1|    fn drop(&mut self) {
+  |   18|      1|        println!("BOOM times {}!!!", self.strength);
+  |   19|      1|    }
+  ------------------
+  | <generics::Firework<i32> as core::ops::drop::Drop>::drop:
+  |   17|      1|    fn drop(&mut self) {
+  |   18|      1|        println!("BOOM times {}!!!", self.strength);
+  |   19|      1|    }
+  ------------------
+   20|       |}
+   21|       |
+   22|      1|fn main() -> Result<(),u8> {
+   23|      1|    let mut firecracker = Firework { strength: 1 };
+   24|      1|    firecracker.set_strength(2);
+   25|      1|
+   26|      1|    let mut tnt = Firework { strength: 100.1 };
+   27|      1|    tnt.set_strength(200.1);
+   28|      1|    tnt.set_strength(300.3);
+   29|      1|
+   30|      1|    if true {
+   31|      1|        println!("Exiting with error...");
+   32|      1|        return Err(1);
+   33|      0|    }
+   34|      0|
+   35|      0|
+   36|      0|
+   37|      0|
+   38|      0|
+   39|      0|    let _ = Firework { strength: 1000 };
+   40|      0|
+   41|      0|    Ok(())
+   42|      1|}
+   43|       |
+   44|       |// Expected program output:
+   45|       |//   Exiting with error...
+   46|       |//   BOOM times 100!!!
+   47|       |//   BOOM times 1!!!
+   48|       |//   Error: 1
+
diff --git a/tests/run-coverage/generics.rs b/tests/run-coverage/generics.rs
new file mode 100644
index 00000000000..150ffb9db39
--- /dev/null
+++ b/tests/run-coverage/generics.rs
@@ -0,0 +1,48 @@
+#![allow(unused_assignments)]
+// failure-status: 1
+
+struct Firework<T> where T: Copy + std::fmt::Display {
+    strength: T,
+}
+
+impl<T> Firework<T> where T: Copy + std::fmt::Display {
+    #[inline(always)]
+    fn set_strength(&mut self, new_strength: T) {
+        self.strength = new_strength;
+    }
+}
+
+impl<T> Drop for Firework<T> where T: Copy + std::fmt::Display {
+    #[inline(always)]
+    fn drop(&mut self) {
+        println!("BOOM times {}!!!", self.strength);
+    }
+}
+
+fn main() -> Result<(),u8> {
+    let mut firecracker = Firework { strength: 1 };
+    firecracker.set_strength(2);
+
+    let mut tnt = Firework { strength: 100.1 };
+    tnt.set_strength(200.1);
+    tnt.set_strength(300.3);
+
+    if true {
+        println!("Exiting with error...");
+        return Err(1);
+    }
+
+
+
+
+
+    let _ = Firework { strength: 1000 };
+
+    Ok(())
+}
+
+// Expected program output:
+//   Exiting with error...
+//   BOOM times 100!!!
+//   BOOM times 1!!!
+//   Error: 1
diff --git a/tests/run-coverage/if.coverage b/tests/run-coverage/if.coverage
new file mode 100644
index 00000000000..0c9eff227ed
--- /dev/null
+++ b/tests/run-coverage/if.coverage
@@ -0,0 +1,30 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let
+    8|      1|    is_true
+    9|      1|    =
+   10|      1|        std::env::args().len()
+   11|      1|    ==
+   12|      1|        1
+   13|      1|    ;
+   14|      1|    let
+   15|      1|        mut
+   16|      1|    countdown
+   17|      1|    =
+   18|      1|        0
+   19|      1|    ;
+   20|      1|    if
+   21|      1|        is_true
+   22|      1|    {
+   23|      1|        countdown
+   24|      1|        =
+   25|      1|            10
+   26|      1|        ;
+   27|      1|    }
+                   ^0
+   28|      1|}
+
diff --git a/tests/run-coverage/if.rs b/tests/run-coverage/if.rs
new file mode 100644
index 00000000000..8ad5042ff7b
--- /dev/null
+++ b/tests/run-coverage/if.rs
@@ -0,0 +1,28 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let
+    is_true
+    =
+        std::env::args().len()
+    ==
+        1
+    ;
+    let
+        mut
+    countdown
+    =
+        0
+    ;
+    if
+        is_true
+    {
+        countdown
+        =
+            10
+        ;
+    }
+}
diff --git a/tests/run-coverage/if_else.coverage b/tests/run-coverage/if_else.coverage
new file mode 100644
index 00000000000..4285d318686
--- /dev/null
+++ b/tests/run-coverage/if_else.coverage
@@ -0,0 +1,41 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|
+    9|      1|    let mut countdown = 0;
+   10|      1|    if
+   11|      1|        is_true
+   12|      1|    {
+   13|      1|        countdown
+   14|      1|        =
+   15|      1|            10
+   16|      1|        ;
+   17|      1|    }
+   18|       |    else // Note coverage region difference without semicolon
+   19|       |    {
+   20|      0|        countdown
+   21|      0|        =
+   22|      0|            100
+   23|       |    }
+   24|       |
+   25|       |    if
+   26|      1|        is_true
+   27|      1|    {
+   28|      1|        countdown
+   29|      1|        =
+   30|      1|            10
+   31|      1|        ;
+   32|      1|    }
+   33|       |    else
+   34|      0|    {
+   35|      0|        countdown
+   36|      0|        =
+   37|      0|            100
+   38|      0|        ;
+   39|      0|    }
+   40|      1|}
+
diff --git a/tests/run-coverage/if_else.rs b/tests/run-coverage/if_else.rs
new file mode 100644
index 00000000000..3244e1e3afd
--- /dev/null
+++ b/tests/run-coverage/if_else.rs
@@ -0,0 +1,40 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 0;
+    if
+        is_true
+    {
+        countdown
+        =
+            10
+        ;
+    }
+    else // Note coverage region difference without semicolon
+    {
+        countdown
+        =
+            100
+    }
+
+    if
+        is_true
+    {
+        countdown
+        =
+            10
+        ;
+    }
+    else
+    {
+        countdown
+        =
+            100
+        ;
+    }
+}
diff --git a/tests/run-coverage/inline-dead.coverage b/tests/run-coverage/inline-dead.coverage
new file mode 100644
index 00000000000..a59fe1146f4
--- /dev/null
+++ b/tests/run-coverage/inline-dead.coverage
@@ -0,0 +1,28 @@
+    1|       |// Regression test for issue #98833.
+    2|       |// compile-flags: -Zinline-mir -Cdebug-assertions=off
+    3|       |
+    4|      1|fn main() {
+    5|      1|    println!("{}", live::<false>());
+    6|      1|
+    7|      1|    let f = |x: bool| {
+    8|       |        debug_assert!(
+    9|      0|            x
+   10|       |        );
+   11|      1|    };
+   12|      1|    f(false);
+   13|      1|}
+   14|       |
+   15|       |#[inline]
+   16|      1|fn live<const B: bool>() -> u32 {
+   17|      1|    if B {
+   18|      0|        dead()
+   19|       |    } else {
+   20|      1|        0
+   21|       |    }
+   22|      1|}
+   23|       |
+   24|       |#[inline]
+   25|      0|fn dead() -> u32 {
+   26|      0|    42
+   27|      0|}
+
diff --git a/tests/run-coverage/inline-dead.rs b/tests/run-coverage/inline-dead.rs
new file mode 100644
index 00000000000..854fa062967
--- /dev/null
+++ b/tests/run-coverage/inline-dead.rs
@@ -0,0 +1,27 @@
+// Regression test for issue #98833.
+// compile-flags: -Zinline-mir -Cdebug-assertions=off
+
+fn main() {
+    println!("{}", live::<false>());
+
+    let f = |x: bool| {
+        debug_assert!(
+            x
+        );
+    };
+    f(false);
+}
+
+#[inline]
+fn live<const B: bool>() -> u32 {
+    if B {
+        dead()
+    } else {
+        0
+    }
+}
+
+#[inline]
+fn dead() -> u32 {
+    42
+}
diff --git a/tests/run-coverage/inline.coverage b/tests/run-coverage/inline.coverage
new file mode 100644
index 00000000000..6f5d1544fa0
--- /dev/null
+++ b/tests/run-coverage/inline.coverage
@@ -0,0 +1,54 @@
+    1|       |// compile-flags: -Zinline-mir
+    2|       |
+    3|       |use std::fmt::Display;
+    4|       |
+    5|      1|fn main() {
+    6|      1|    permutations(&['a', 'b', 'c']);
+    7|      1|}
+    8|       |
+    9|       |#[inline(always)]
+   10|      1|fn permutations<T: Copy + Display>(xs: &[T]) {
+   11|      1|    let mut ys = xs.to_owned();
+   12|      1|    permutate(&mut ys, 0);
+   13|      1|}
+   14|       |
+   15|     16|fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
+   16|     16|    let n = length(xs);
+   17|     16|    if k == n {
+   18|      6|        display(xs);
+   19|     10|    } else if k < n {
+   20|     15|        for i in k..n {
+                               ^10
+   21|     15|            swap(xs, i, k);
+   22|     15|            permutate(xs, k + 1);
+   23|     15|            swap(xs, i, k);
+   24|     15|        }
+   25|      0|    } else {
+   26|      0|        error();
+   27|      0|    }
+   28|     16|}
+   29|       |
+   30|     16|fn length<T>(xs: &[T]) -> usize {
+   31|     16|    xs.len()
+   32|     16|}
+   33|       |
+   34|       |#[inline]
+   35|     30|fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
+   36|     30|    let t = xs[i];
+   37|     30|    xs[i] = xs[j];
+   38|     30|    xs[j] = t;
+   39|     30|}
+   40|       |
+   41|      6|fn display<T: Display>(xs: &[T]) {
+   42|     24|    for x in xs {
+                      ^18
+   43|     18|        print!("{}", x);
+   44|     18|    }
+   45|      6|    println!();
+   46|      6|}
+   47|       |
+   48|       |#[inline(always)]
+   49|      0|fn error() {
+   50|      0|    panic!("error");
+   51|      0|}
+
diff --git a/tests/run-coverage/inline.rs b/tests/run-coverage/inline.rs
new file mode 100644
index 00000000000..9cfab9ddbad
--- /dev/null
+++ b/tests/run-coverage/inline.rs
@@ -0,0 +1,51 @@
+// compile-flags: -Zinline-mir
+
+use std::fmt::Display;
+
+fn main() {
+    permutations(&['a', 'b', 'c']);
+}
+
+#[inline(always)]
+fn permutations<T: Copy + Display>(xs: &[T]) {
+    let mut ys = xs.to_owned();
+    permutate(&mut ys, 0);
+}
+
+fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
+    let n = length(xs);
+    if k == n {
+        display(xs);
+    } else if k < n {
+        for i in k..n {
+            swap(xs, i, k);
+            permutate(xs, k + 1);
+            swap(xs, i, k);
+        }
+    } else {
+        error();
+    }
+}
+
+fn length<T>(xs: &[T]) -> usize {
+    xs.len()
+}
+
+#[inline]
+fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
+    let t = xs[i];
+    xs[i] = xs[j];
+    xs[j] = t;
+}
+
+fn display<T: Display>(xs: &[T]) {
+    for x in xs {
+        print!("{}", x);
+    }
+    println!();
+}
+
+#[inline(always)]
+fn error() {
+    panic!("error");
+}
diff --git a/tests/run-coverage/inner_items.coverage b/tests/run-coverage/inner_items.coverage
new file mode 100644
index 00000000000..883254a09ba
--- /dev/null
+++ b/tests/run-coverage/inner_items.coverage
@@ -0,0 +1,60 @@
+    1|       |#![allow(unused_assignments, unused_variables, dead_code)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|
+    9|      1|    let mut countdown = 0;
+   10|      1|    if is_true {
+   11|      1|        countdown = 10;
+   12|      1|    }
+                   ^0
+   13|       |
+   14|       |    mod in_mod {
+   15|       |        const IN_MOD_CONST: u32 = 1000;
+   16|       |    }
+   17|       |
+   18|      3|    fn in_func(a: u32) {
+   19|      3|        let b = 1;
+   20|      3|        let c = a + b;
+   21|      3|        println!("c = {}", c)
+   22|      3|    }
+   23|       |
+   24|       |    struct InStruct {
+   25|       |        in_struct_field: u32,
+   26|       |    }
+   27|       |
+   28|       |    const IN_CONST: u32 = 1234;
+   29|       |
+   30|       |    trait InTrait {
+   31|       |        fn trait_func(&mut self, incr: u32);
+   32|       |
+   33|      1|        fn default_trait_func(&mut self) {
+   34|      1|            in_func(IN_CONST);
+   35|      1|            self.trait_func(IN_CONST);
+   36|      1|        }
+   37|       |    }
+   38|       |
+   39|       |    impl InTrait for InStruct {
+   40|      1|        fn trait_func(&mut self, incr: u32) {
+   41|      1|            self.in_struct_field += incr;
+   42|      1|            in_func(self.in_struct_field);
+   43|      1|        }
+   44|       |    }
+   45|       |
+   46|       |    type InType = String;
+   47|       |
+   48|      1|    if is_true {
+   49|      1|        in_func(countdown);
+   50|      1|    }
+                   ^0
+   51|       |
+   52|      1|    let mut val = InStruct {
+   53|      1|        in_struct_field: 101,
+   54|      1|    };
+   55|      1|
+   56|      1|    val.default_trait_func();
+   57|      1|}
+
diff --git a/tests/run-coverage/inner_items.rs b/tests/run-coverage/inner_items.rs
new file mode 100644
index 00000000000..bcb62b3031c
--- /dev/null
+++ b/tests/run-coverage/inner_items.rs
@@ -0,0 +1,57 @@
+#![allow(unused_assignments, unused_variables, dead_code)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 0;
+    if is_true {
+        countdown = 10;
+    }
+
+    mod in_mod {
+        const IN_MOD_CONST: u32 = 1000;
+    }
+
+    fn in_func(a: u32) {
+        let b = 1;
+        let c = a + b;
+        println!("c = {}", c)
+    }
+
+    struct InStruct {
+        in_struct_field: u32,
+    }
+
+    const IN_CONST: u32 = 1234;
+
+    trait InTrait {
+        fn trait_func(&mut self, incr: u32);
+
+        fn default_trait_func(&mut self) {
+            in_func(IN_CONST);
+            self.trait_func(IN_CONST);
+        }
+    }
+
+    impl InTrait for InStruct {
+        fn trait_func(&mut self, incr: u32) {
+            self.in_struct_field += incr;
+            in_func(self.in_struct_field);
+        }
+    }
+
+    type InType = String;
+
+    if is_true {
+        in_func(countdown);
+    }
+
+    let mut val = InStruct {
+        in_struct_field: 101,
+    };
+
+    val.default_trait_func();
+}
diff --git a/tests/run-coverage/issue-83601.coverage b/tests/run-coverage/issue-83601.coverage
new file mode 100644
index 00000000000..25c74ab2e70
--- /dev/null
+++ b/tests/run-coverage/issue-83601.coverage
@@ -0,0 +1,16 @@
+    1|       |// Shows that rust-lang/rust/83601 is resolved
+    2|       |
+    3|      3|#[derive(Debug, PartialEq, Eq)]
+                              ^2
+    4|       |struct Foo(u32);
+    5|       |
+    6|      1|fn main() {
+    7|      1|    let bar = Foo(1);
+    8|      1|    assert_eq!(bar, Foo(1));
+    9|      1|    let baz = Foo(0);
+   10|      1|    assert_ne!(baz, Foo(1));
+   11|      1|    println!("{:?}", Foo(1));
+   12|      1|    println!("{:?}", bar);
+   13|      1|    println!("{:?}", baz);
+   14|      1|}
+
diff --git a/tests/run-coverage/issue-83601.rs b/tests/run-coverage/issue-83601.rs
new file mode 100644
index 00000000000..0b72a81947c
--- /dev/null
+++ b/tests/run-coverage/issue-83601.rs
@@ -0,0 +1,14 @@
+// Shows that rust-lang/rust/83601 is resolved
+
+#[derive(Debug, PartialEq, Eq)]
+struct Foo(u32);
+
+fn main() {
+    let bar = Foo(1);
+    assert_eq!(bar, Foo(1));
+    let baz = Foo(0);
+    assert_ne!(baz, Foo(1));
+    println!("{:?}", Foo(1));
+    println!("{:?}", bar);
+    println!("{:?}", baz);
+}
diff --git a/tests/run-coverage/issue-84561.coverage b/tests/run-coverage/issue-84561.coverage
new file mode 100644
index 00000000000..7a97e353245
--- /dev/null
+++ b/tests/run-coverage/issue-84561.coverage
@@ -0,0 +1,189 @@
+    1|       |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
+    2|       |
+    3|       |// failure-status: 101
+    4|     21|#[derive(PartialEq, Eq)]
+    5|       |struct Foo(u32);
+    6|      1|fn test3() {
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|    let bar = Foo(1);
+    9|      1|    assert_eq!(bar, Foo(1));
+   10|      1|    let baz = Foo(0);
+   11|      1|    assert_ne!(baz, Foo(1));
+   12|      1|    println!("{:?}", Foo(1));
+   13|      1|    println!("{:?}", bar);
+   14|      1|    println!("{:?}", baz);
+   15|      1|
+   16|      1|    assert_eq!(Foo(1), Foo(1));
+   17|      1|    assert_ne!(Foo(0), Foo(1));
+   18|      1|    assert_eq!(Foo(2), Foo(2));
+   19|      1|    let bar = Foo(0);
+   20|      1|    assert_ne!(bar, Foo(3));
+   21|      1|    assert_ne!(Foo(0), Foo(4));
+   22|      1|    assert_eq!(Foo(3), Foo(3), "with a message");
+                                             ^0
+   23|      1|    println!("{:?}", bar);
+   24|      1|    println!("{:?}", Foo(1));
+   25|      1|
+   26|      1|    assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
+                                             ^0                 ^0                      ^0
+   27|      1|    assert_ne!(
+   28|       |        Foo(0)
+   29|       |        ,
+   30|       |        Foo(5)
+   31|       |        ,
+   32|      0|        "{}"
+   33|      0|        ,
+   34|      0|        if
+   35|      0|        is_true
+   36|       |        {
+   37|      0|            "true message"
+   38|       |        } else {
+   39|      0|            "false message"
+   40|       |        }
+   41|       |    );
+   42|       |
+   43|      1|    let is_true = std::env::args().len() == 1;
+   44|      1|
+   45|      1|    assert_eq!(
+   46|      1|        Foo(1),
+   47|      1|        Foo(1)
+   48|      1|    );
+   49|      1|    assert_ne!(
+   50|      1|        Foo(0),
+   51|      1|        Foo(1)
+   52|      1|    );
+   53|      1|    assert_eq!(
+   54|      1|        Foo(2),
+   55|      1|        Foo(2)
+   56|      1|    );
+   57|      1|    let bar = Foo(1);
+   58|      1|    assert_ne!(
+   59|      1|        bar,
+   60|      1|        Foo(3)
+   61|      1|    );
+   62|      1|    if is_true {
+   63|      1|        assert_ne!(
+   64|      1|            Foo(0),
+   65|      1|            Foo(4)
+   66|      1|        );
+   67|       |    } else {
+   68|      0|        assert_eq!(
+   69|      0|            Foo(3),
+   70|      0|            Foo(3)
+   71|      0|        );
+   72|       |    }
+   73|      1|    if is_true {
+   74|      1|        assert_ne!(
+   75|       |            Foo(0),
+   76|       |            Foo(4),
+   77|      0|            "with a message"
+   78|       |        );
+   79|       |    } else {
+   80|      0|        assert_eq!(
+   81|       |            Foo(3),
+   82|       |            Foo(3),
+   83|      0|            "with a message"
+   84|       |        );
+   85|       |    }
+   86|      1|    assert_ne!(
+   87|      1|        if is_true {
+   88|      1|            Foo(0)
+   89|       |        } else {
+   90|      0|            Foo(1)
+   91|       |        },
+   92|       |        Foo(5)
+   93|       |    );
+   94|      1|    assert_ne!(
+   95|      1|        Foo(5),
+   96|      1|        if is_true {
+   97|      1|            Foo(0)
+   98|       |        } else {
+   99|      0|            Foo(1)
+  100|       |        }
+  101|       |    );
+  102|      1|    assert_ne!(
+  103|      1|        if is_true {
+  104|      1|            assert_eq!(
+  105|      1|                Foo(3),
+  106|      1|                Foo(3)
+  107|      1|            );
+  108|      1|            Foo(0)
+  109|       |        } else {
+  110|      0|            assert_ne!(
+  111|      0|                if is_true {
+  112|      0|                    Foo(0)
+  113|       |                } else {
+  114|      0|                    Foo(1)
+  115|       |                },
+  116|       |                Foo(5)
+  117|       |            );
+  118|      0|            Foo(1)
+  119|       |        },
+  120|       |        Foo(5),
+  121|      0|        "with a message"
+  122|       |    );
+  123|      1|    assert_eq!(
+  124|       |        Foo(1),
+  125|       |        Foo(3),
+  126|      1|        "this assert should fail"
+  127|       |    );
+  128|      0|    assert_eq!(
+  129|       |        Foo(3),
+  130|       |        Foo(3),
+  131|      0|        "this assert should not be reached"
+  132|       |    );
+  133|      0|}
+  134|       |
+  135|       |impl std::fmt::Debug for Foo {
+  136|       |    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+  137|      7|        write!(f, "try and succeed")?;
+                                                  ^0
+  138|      7|        Ok(())
+  139|      7|    }
+  140|       |}
+  141|       |
+  142|       |static mut DEBUG_LEVEL_ENABLED: bool = false;
+  143|       |
+  144|       |macro_rules! debug {
+  145|       |    ($($arg:tt)+) => (
+  146|       |        if unsafe { DEBUG_LEVEL_ENABLED } {
+  147|       |            println!($($arg)+);
+  148|       |        }
+  149|       |    );
+  150|       |}
+  151|       |
+  152|      1|fn test1() {
+  153|      1|    debug!("debug is enabled");
+                         ^0
+  154|      1|    debug!("debug is enabled");
+                         ^0
+  155|      1|    let _ = 0;
+  156|      1|    debug!("debug is enabled");
+                         ^0
+  157|      1|    unsafe {
+  158|      1|        DEBUG_LEVEL_ENABLED = true;
+  159|      1|    }
+  160|      1|    debug!("debug is enabled");
+  161|      1|}
+  162|       |
+  163|       |macro_rules! call_debug {
+  164|       |    ($($arg:tt)+) => (
+  165|      1|        fn call_print(s: &str) {
+  166|      1|            print!("{}", s);
+  167|      1|        }
+  168|       |
+  169|       |        call_print("called from call_debug: ");
+  170|       |        debug!($($arg)+);
+  171|       |    );
+  172|       |}
+  173|       |
+  174|      1|fn test2() {
+  175|      1|    call_debug!("debug is enabled");
+  176|      1|}
+  177|       |
+  178|      1|fn main() {
+  179|      1|    test1();
+  180|      1|    test2();
+  181|      1|    test3();
+  182|      1|}
+
diff --git a/tests/run-coverage/issue-84561.rs b/tests/run-coverage/issue-84561.rs
new file mode 100644
index 00000000000..facf5b5b4cf
--- /dev/null
+++ b/tests/run-coverage/issue-84561.rs
@@ -0,0 +1,182 @@
+// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
+
+// failure-status: 101
+#[derive(PartialEq, Eq)]
+struct Foo(u32);
+fn test3() {
+    let is_true = std::env::args().len() == 1;
+    let bar = Foo(1);
+    assert_eq!(bar, Foo(1));
+    let baz = Foo(0);
+    assert_ne!(baz, Foo(1));
+    println!("{:?}", Foo(1));
+    println!("{:?}", bar);
+    println!("{:?}", baz);
+
+    assert_eq!(Foo(1), Foo(1));
+    assert_ne!(Foo(0), Foo(1));
+    assert_eq!(Foo(2), Foo(2));
+    let bar = Foo(0);
+    assert_ne!(bar, Foo(3));
+    assert_ne!(Foo(0), Foo(4));
+    assert_eq!(Foo(3), Foo(3), "with a message");
+    println!("{:?}", bar);
+    println!("{:?}", Foo(1));
+
+    assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
+    assert_ne!(
+        Foo(0)
+        ,
+        Foo(5)
+        ,
+        "{}"
+        ,
+        if
+        is_true
+        {
+            "true message"
+        } else {
+            "false message"
+        }
+    );
+
+    let is_true = std::env::args().len() == 1;
+
+    assert_eq!(
+        Foo(1),
+        Foo(1)
+    );
+    assert_ne!(
+        Foo(0),
+        Foo(1)
+    );
+    assert_eq!(
+        Foo(2),
+        Foo(2)
+    );
+    let bar = Foo(1);
+    assert_ne!(
+        bar,
+        Foo(3)
+    );
+    if is_true {
+        assert_ne!(
+            Foo(0),
+            Foo(4)
+        );
+    } else {
+        assert_eq!(
+            Foo(3),
+            Foo(3)
+        );
+    }
+    if is_true {
+        assert_ne!(
+            Foo(0),
+            Foo(4),
+            "with a message"
+        );
+    } else {
+        assert_eq!(
+            Foo(3),
+            Foo(3),
+            "with a message"
+        );
+    }
+    assert_ne!(
+        if is_true {
+            Foo(0)
+        } else {
+            Foo(1)
+        },
+        Foo(5)
+    );
+    assert_ne!(
+        Foo(5),
+        if is_true {
+            Foo(0)
+        } else {
+            Foo(1)
+        }
+    );
+    assert_ne!(
+        if is_true {
+            assert_eq!(
+                Foo(3),
+                Foo(3)
+            );
+            Foo(0)
+        } else {
+            assert_ne!(
+                if is_true {
+                    Foo(0)
+                } else {
+                    Foo(1)
+                },
+                Foo(5)
+            );
+            Foo(1)
+        },
+        Foo(5),
+        "with a message"
+    );
+    assert_eq!(
+        Foo(1),
+        Foo(3),
+        "this assert should fail"
+    );
+    assert_eq!(
+        Foo(3),
+        Foo(3),
+        "this assert should not be reached"
+    );
+}
+
+impl std::fmt::Debug for Foo {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        write!(f, "try and succeed")?;
+        Ok(())
+    }
+}
+
+static mut DEBUG_LEVEL_ENABLED: bool = false;
+
+macro_rules! debug {
+    ($($arg:tt)+) => (
+        if unsafe { DEBUG_LEVEL_ENABLED } {
+            println!($($arg)+);
+        }
+    );
+}
+
+fn test1() {
+    debug!("debug is enabled");
+    debug!("debug is enabled");
+    let _ = 0;
+    debug!("debug is enabled");
+    unsafe {
+        DEBUG_LEVEL_ENABLED = true;
+    }
+    debug!("debug is enabled");
+}
+
+macro_rules! call_debug {
+    ($($arg:tt)+) => (
+        fn call_print(s: &str) {
+            print!("{}", s);
+        }
+
+        call_print("called from call_debug: ");
+        debug!($($arg)+);
+    );
+}
+
+fn test2() {
+    call_debug!("debug is enabled");
+}
+
+fn main() {
+    test1();
+    test2();
+    test3();
+}
diff --git a/tests/run-coverage/issue-85461.coverage b/tests/run-coverage/issue-85461.coverage
new file mode 100644
index 00000000000..d78a4a1129c
--- /dev/null
+++ b/tests/run-coverage/issue-85461.coverage
@@ -0,0 +1,36 @@
+$DIR/auxiliary/inline_always_with_dead_code.rs:
+    1|       |// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0
+    2|       |
+    3|       |#![allow(dead_code)]
+    4|       |
+    5|       |mod foo {
+    6|       |    #[inline(always)]
+    7|      2|    pub fn called() { }
+    8|       |
+    9|      0|    fn uncalled() { }
+   10|       |}
+   11|       |
+   12|       |pub mod bar {
+   13|      1|    pub fn call_me() {
+   14|      1|        super::foo::called();
+   15|      1|    }
+   16|       |}
+   17|       |
+   18|       |pub mod baz {
+   19|      1|    pub fn call_me() {
+   20|      1|        super::foo::called();
+   21|      1|    }
+   22|       |}
+
+$DIR/issue-85461.rs:
+    1|       |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+    2|       |// aux-build:inline_always_with_dead_code.rs
+    3|       |extern crate inline_always_with_dead_code;
+    4|       |
+    5|       |use inline_always_with_dead_code::{bar, baz};
+    6|       |
+    7|      1|fn main() {
+    8|      1|    bar::call_me();
+    9|      1|    baz::call_me();
+   10|      1|}
+
diff --git a/tests/run-coverage/issue-85461.rs b/tests/run-coverage/issue-85461.rs
new file mode 100644
index 00000000000..6f626b4a65b
--- /dev/null
+++ b/tests/run-coverage/issue-85461.rs
@@ -0,0 +1,10 @@
+// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+// aux-build:inline_always_with_dead_code.rs
+extern crate inline_always_with_dead_code;
+
+use inline_always_with_dead_code::{bar, baz};
+
+fn main() {
+    bar::call_me();
+    baz::call_me();
+}
diff --git a/tests/run-coverage/issue-93054.coverage b/tests/run-coverage/issue-93054.coverage
new file mode 100644
index 00000000000..a1655adedd4
--- /dev/null
+++ b/tests/run-coverage/issue-93054.coverage
@@ -0,0 +1,29 @@
+    1|       |// Regression test for #93054: Functions using uninhabited types often only have a single,
+    2|       |// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
+    3|       |// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
+    4|       |
+    5|       |// compile-flags: --edition=2021
+    6|       |
+    7|       |enum Never { }
+    8|       |
+    9|       |impl Never {
+   10|       |    fn foo(self) {
+   11|       |        match self { }
+   12|       |        make().map(|never| match never { });
+   13|       |    }
+   14|       |
+   15|       |    fn bar(&self) {
+   16|       |        match *self { }
+   17|       |    }
+   18|       |}
+   19|       |
+   20|      0|async fn foo2(never: Never) {
+   21|       |    match never { }
+   22|       |}
+   23|       |
+   24|      0|fn make() -> Option<Never> {
+   25|      0|    None
+   26|      0|}
+   27|       |
+   28|      1|fn main() { }
+
diff --git a/tests/run-coverage/issue-93054.rs b/tests/run-coverage/issue-93054.rs
new file mode 100644
index 00000000000..c160b3db03f
--- /dev/null
+++ b/tests/run-coverage/issue-93054.rs
@@ -0,0 +1,28 @@
+// Regression test for #93054: Functions using uninhabited types often only have a single,
+// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
+// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
+
+// compile-flags: --edition=2021
+
+enum Never { }
+
+impl Never {
+    fn foo(self) {
+        match self { }
+        make().map(|never| match never { });
+    }
+
+    fn bar(&self) {
+        match *self { }
+    }
+}
+
+async fn foo2(never: Never) {
+    match never { }
+}
+
+fn make() -> Option<Never> {
+    None
+}
+
+fn main() { }
diff --git a/tests/run-coverage/lazy_boolean.coverage b/tests/run-coverage/lazy_boolean.coverage
new file mode 100644
index 00000000000..bd349df2fbc
--- /dev/null
+++ b/tests/run-coverage/lazy_boolean.coverage
@@ -0,0 +1,64 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|
+    9|      1|    let (mut a, mut b, mut c) = (0, 0, 0);
+   10|      1|    if is_true {
+   11|      1|        a = 1;
+   12|      1|        b = 10;
+   13|      1|        c = 100;
+   14|      1|    }
+                   ^0
+   15|       |    let
+   16|      1|        somebool
+   17|       |        =
+   18|      1|            a < b
+   19|       |        ||
+   20|      0|            b < c
+   21|       |    ;
+   22|       |    let
+   23|      1|        somebool
+   24|       |        =
+   25|      1|            b < a
+   26|       |        ||
+   27|      1|            b < c
+   28|       |    ;
+   29|      1|    let somebool = a < b && b < c;
+   30|      1|    let somebool = b < a && b < c;
+                                          ^0
+   31|       |
+   32|       |    if
+   33|      1|        !
+   34|      1|        is_true
+   35|      0|    {
+   36|      0|        a = 2
+   37|      0|        ;
+   38|      1|    }
+   39|       |
+   40|       |    if
+   41|      1|        is_true
+   42|      1|    {
+   43|      1|        b = 30
+   44|      1|        ;
+   45|      1|    }
+   46|       |    else
+   47|      0|    {
+   48|      0|        c = 400
+   49|      0|        ;
+   50|      0|    }
+   51|       |
+   52|      1|    if !is_true {
+   53|      0|        a = 2;
+   54|      1|    }
+   55|       |
+   56|      1|    if is_true {
+   57|      1|        b = 30;
+   58|      1|    } else {
+   59|      0|        c = 400;
+   60|      0|    }
+   61|      1|}
+
diff --git a/tests/run-coverage/lazy_boolean.rs b/tests/run-coverage/lazy_boolean.rs
new file mode 100644
index 00000000000..bb6219e851c
--- /dev/null
+++ b/tests/run-coverage/lazy_boolean.rs
@@ -0,0 +1,61 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let (mut a, mut b, mut c) = (0, 0, 0);
+    if is_true {
+        a = 1;
+        b = 10;
+        c = 100;
+    }
+    let
+        somebool
+        =
+            a < b
+        ||
+            b < c
+    ;
+    let
+        somebool
+        =
+            b < a
+        ||
+            b < c
+    ;
+    let somebool = a < b && b < c;
+    let somebool = b < a && b < c;
+
+    if
+        !
+        is_true
+    {
+        a = 2
+        ;
+    }
+
+    if
+        is_true
+    {
+        b = 30
+        ;
+    }
+    else
+    {
+        c = 400
+        ;
+    }
+
+    if !is_true {
+        a = 2;
+    }
+
+    if is_true {
+        b = 30;
+    } else {
+        c = 400;
+    }
+}
diff --git a/tests/run-coverage/loop_break_value.coverage b/tests/run-coverage/loop_break_value.coverage
new file mode 100644
index 00000000000..022fe4c5962
--- /dev/null
+++ b/tests/run-coverage/loop_break_value.coverage
@@ -0,0 +1,14 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    let result
+    5|      1|        =
+    6|      1|            loop
+    7|      1|        {
+    8|      1|            break
+    9|      1|            10
+   10|      1|            ;
+   11|      1|        }
+   12|      1|    ;
+   13|      1|}
+
diff --git a/tests/run-coverage/loop_break_value.rs b/tests/run-coverage/loop_break_value.rs
new file mode 100644
index 00000000000..dbc4fad7a23
--- /dev/null
+++ b/tests/run-coverage/loop_break_value.rs
@@ -0,0 +1,13 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    let result
+        =
+            loop
+        {
+            break
+            10
+            ;
+        }
+    ;
+}
diff --git a/tests/run-coverage/loops_branches.coverage b/tests/run-coverage/loops_branches.coverage
new file mode 100644
index 00000000000..b7ad79a2484
--- /dev/null
+++ b/tests/run-coverage/loops_branches.coverage
@@ -0,0 +1,68 @@
+    1|       |#![allow(unused_assignments, unused_variables, while_true)]
+    2|       |
+    3|       |// This test confirms that (1) unexecuted infinite loops are handled correctly by the
+    4|       |// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped.
+    5|       |
+    6|       |struct DebugTest;
+    7|       |
+    8|       |impl std::fmt::Debug for DebugTest {
+    9|      1|    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+   10|      1|        if true {
+   11|      1|            if false {
+   12|      0|                while true {
+   13|      0|                }
+   14|      1|            }
+   15|      1|            write!(f, "cool")?;
+                                           ^0
+   16|      0|        } else {
+   17|      0|        }
+   18|       |
+   19|     11|        for i in 0..10 {
+                          ^10
+   20|     10|            if true {
+   21|     10|                if false {
+   22|      0|                    while true {}
+   23|     10|                }
+   24|     10|                write!(f, "cool")?;
+                                               ^0
+   25|      0|            } else {
+   26|      0|            }
+   27|       |        }
+   28|      1|        Ok(())
+   29|      1|    }
+   30|       |}
+   31|       |
+   32|       |struct DisplayTest;
+   33|       |
+   34|       |impl std::fmt::Display for DisplayTest {
+   35|      1|    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+   36|      1|        if false {
+   37|      0|        } else {
+   38|      1|            if false {
+   39|      0|                while true {}
+   40|      1|            }
+   41|      1|            write!(f, "cool")?;
+                                           ^0
+   42|       |        }
+   43|     11|        for i in 0..10 {
+                          ^10
+   44|     10|            if false {
+   45|      0|            } else {
+   46|     10|                if false {
+   47|      0|                    while true {}
+   48|     10|                }
+   49|     10|                write!(f, "cool")?;
+                                               ^0
+   50|       |            }
+   51|       |        }
+   52|      1|        Ok(())
+   53|      1|    }
+   54|       |}
+   55|       |
+   56|      1|fn main() {
+   57|      1|    let debug_test = DebugTest;
+   58|      1|    println!("{:?}", debug_test);
+   59|      1|    let display_test = DisplayTest;
+   60|      1|    println!("{}", display_test);
+   61|      1|}
+
diff --git a/tests/run-coverage/loops_branches.rs b/tests/run-coverage/loops_branches.rs
new file mode 100644
index 00000000000..7116ce47f4b
--- /dev/null
+++ b/tests/run-coverage/loops_branches.rs
@@ -0,0 +1,61 @@
+#![allow(unused_assignments, unused_variables, while_true)]
+
+// This test confirms that (1) unexecuted infinite loops are handled correctly by the
+// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped.
+
+struct DebugTest;
+
+impl std::fmt::Debug for DebugTest {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        if true {
+            if false {
+                while true {
+                }
+            }
+            write!(f, "cool")?;
+        } else {
+        }
+
+        for i in 0..10 {
+            if true {
+                if false {
+                    while true {}
+                }
+                write!(f, "cool")?;
+            } else {
+            }
+        }
+        Ok(())
+    }
+}
+
+struct DisplayTest;
+
+impl std::fmt::Display for DisplayTest {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        if false {
+        } else {
+            if false {
+                while true {}
+            }
+            write!(f, "cool")?;
+        }
+        for i in 0..10 {
+            if false {
+            } else {
+                if false {
+                    while true {}
+                }
+                write!(f, "cool")?;
+            }
+        }
+        Ok(())
+    }
+}
+
+fn main() {
+    let debug_test = DebugTest;
+    println!("{:?}", debug_test);
+    let display_test = DisplayTest;
+    println!("{}", display_test);
+}
diff --git a/tests/run-coverage/match_or_pattern.coverage b/tests/run-coverage/match_or_pattern.coverage
new file mode 100644
index 00000000000..a0fccb24f99
--- /dev/null
+++ b/tests/run-coverage/match_or_pattern.coverage
@@ -0,0 +1,50 @@
+    1|       |#![feature(or_patterns)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|
+    9|      1|    let mut a: u8 = 0;
+   10|      1|    let mut b: u8 = 0;
+   11|      1|    if is_true {
+   12|      1|        a = 2;
+   13|      1|        b = 0;
+   14|      1|    }
+                   ^0
+   15|      1|    match (a, b) {
+   16|       |        // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
+   17|       |        // This test confirms a fix for Issue #79569.
+   18|      0|        (0 | 1, 2 | 3) => {}
+   19|      1|        _ => {}
+   20|       |    }
+   21|      1|    if is_true {
+   22|      1|        a = 0;
+   23|      1|        b = 0;
+   24|      1|    }
+                   ^0
+   25|      1|    match (a, b) {
+   26|      0|        (0 | 1, 2 | 3) => {}
+   27|      1|        _ => {}
+   28|       |    }
+   29|      1|    if is_true {
+   30|      1|        a = 2;
+   31|      1|        b = 2;
+   32|      1|    }
+                   ^0
+   33|      1|    match (a, b) {
+   34|      0|        (0 | 1, 2 | 3) => {}
+   35|      1|        _ => {}
+   36|       |    }
+   37|      1|    if is_true {
+   38|      1|        a = 0;
+   39|      1|        b = 2;
+   40|      1|    }
+                   ^0
+   41|      1|    match (a, b) {
+   42|      1|        (0 | 1, 2 | 3) => {}
+   43|      0|        _ => {}
+   44|       |    }
+   45|      1|}
+
diff --git a/tests/run-coverage/match_or_pattern.rs b/tests/run-coverage/match_or_pattern.rs
new file mode 100644
index 00000000000..4c6a8a9b703
--- /dev/null
+++ b/tests/run-coverage/match_or_pattern.rs
@@ -0,0 +1,45 @@
+#![feature(or_patterns)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut a: u8 = 0;
+    let mut b: u8 = 0;
+    if is_true {
+        a = 2;
+        b = 0;
+    }
+    match (a, b) {
+        // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
+        // This test confirms a fix for Issue #79569.
+        (0 | 1, 2 | 3) => {}
+        _ => {}
+    }
+    if is_true {
+        a = 0;
+        b = 0;
+    }
+    match (a, b) {
+        (0 | 1, 2 | 3) => {}
+        _ => {}
+    }
+    if is_true {
+        a = 2;
+        b = 2;
+    }
+    match (a, b) {
+        (0 | 1, 2 | 3) => {}
+        _ => {}
+    }
+    if is_true {
+        a = 0;
+        b = 2;
+    }
+    match (a, b) {
+        (0 | 1, 2 | 3) => {}
+        _ => {}
+    }
+}
diff --git a/tests/run-coverage/nested_loops.coverage b/tests/run-coverage/nested_loops.coverage
new file mode 100644
index 00000000000..0dbd6bcf313
--- /dev/null
+++ b/tests/run-coverage/nested_loops.coverage
@@ -0,0 +1,26 @@
+    1|      1|fn main() {
+    2|      1|    let is_true = std::env::args().len() == 1;
+    3|      1|    let mut countdown = 10;
+    4|       |
+    5|      1|    'outer: while countdown > 0 {
+    6|      1|        let mut a = 100;
+    7|      1|        let mut b = 100;
+    8|      3|        for _ in 0..50 {
+    9|      3|            if a < 30 {
+   10|      0|                break;
+   11|      3|            }
+   12|      3|            a -= 5;
+   13|      3|            b -= 5;
+   14|      3|            if b < 90 {
+   15|      1|                a -= 10;
+   16|      1|                if is_true {
+   17|      1|                    break 'outer;
+   18|      0|                } else {
+   19|      0|                    a -= 2;
+   20|      0|                }
+   21|      2|            }
+   22|       |        }
+   23|      0|        countdown -= 1;
+   24|       |    }
+   25|      1|}
+
diff --git a/tests/run-coverage/nested_loops.rs b/tests/run-coverage/nested_loops.rs
new file mode 100644
index 00000000000..4c7c7842796
--- /dev/null
+++ b/tests/run-coverage/nested_loops.rs
@@ -0,0 +1,25 @@
+fn main() {
+    let is_true = std::env::args().len() == 1;
+    let mut countdown = 10;
+
+    'outer: while countdown > 0 {
+        let mut a = 100;
+        let mut b = 100;
+        for _ in 0..50 {
+            if a < 30 {
+                break;
+            }
+            a -= 5;
+            b -= 5;
+            if b < 90 {
+                a -= 10;
+                if is_true {
+                    break 'outer;
+                } else {
+                    a -= 2;
+                }
+            }
+        }
+        countdown -= 1;
+    }
+}
diff --git a/tests/run-coverage/no_cov_crate.coverage b/tests/run-coverage/no_cov_crate.coverage
new file mode 100644
index 00000000000..83a9204136f
--- /dev/null
+++ b/tests/run-coverage/no_cov_crate.coverage
@@ -0,0 +1,87 @@
+    1|       |// Enables `no_coverage` on the entire crate
+    2|       |#![feature(no_coverage)]
+    3|       |
+    4|       |#[no_coverage]
+    5|       |fn do_not_add_coverage_1() {
+    6|       |    println!("called but not covered");
+    7|       |}
+    8|       |
+    9|       |fn do_not_add_coverage_2() {
+   10|       |    #![no_coverage]
+   11|       |    println!("called but not covered");
+   12|       |}
+   13|       |
+   14|       |#[no_coverage]
+   15|       |fn do_not_add_coverage_not_called() {
+   16|       |    println!("not called and not covered");
+   17|       |}
+   18|       |
+   19|      1|fn add_coverage_1() {
+   20|      1|    println!("called and covered");
+   21|      1|}
+   22|       |
+   23|      1|fn add_coverage_2() {
+   24|      1|    println!("called and covered");
+   25|      1|}
+   26|       |
+   27|      0|fn add_coverage_not_called() {
+   28|      0|    println!("not called but covered");
+   29|      0|}
+   30|       |
+   31|       |// FIXME: These test-cases illustrate confusing results of nested functions.
+   32|       |// See https://github.com/rust-lang/rust/issues/93319
+   33|       |mod nested_fns {
+   34|       |    #[no_coverage]
+   35|       |    pub fn outer_not_covered(is_true: bool) {
+   36|      1|        fn inner(is_true: bool) {
+   37|      1|            if is_true {
+   38|      1|                println!("called and covered");
+   39|      1|            } else {
+   40|      0|                println!("absolutely not covered");
+   41|      0|            }
+   42|      1|        }
+   43|       |        println!("called but not covered");
+   44|       |        inner(is_true);
+   45|       |    }
+   46|       |
+   47|      1|    pub fn outer(is_true: bool) {
+   48|      1|        println!("called and covered");
+   49|      1|        inner_not_covered(is_true);
+   50|      1|
+   51|      1|        #[no_coverage]
+   52|      1|        fn inner_not_covered(is_true: bool) {
+   53|      1|            if is_true {
+   54|      1|                println!("called but not covered");
+   55|      1|            } else {
+   56|      1|                println!("absolutely not covered");
+   57|      1|            }
+   58|      1|        }
+   59|      1|    }
+   60|       |
+   61|      1|    pub fn outer_both_covered(is_true: bool) {
+   62|      1|        println!("called and covered");
+   63|      1|        inner(is_true);
+   64|      1|
+   65|      1|        fn inner(is_true: bool) {
+   66|      1|            if is_true {
+   67|      1|                println!("called and covered");
+   68|      1|            } else {
+   69|      0|                println!("absolutely not covered");
+   70|      0|            }
+   71|      1|        }
+   72|      1|    }
+   73|       |}
+   74|       |
+   75|      1|fn main() {
+   76|      1|    let is_true = std::env::args().len() == 1;
+   77|      1|
+   78|      1|    do_not_add_coverage_1();
+   79|      1|    do_not_add_coverage_2();
+   80|      1|    add_coverage_1();
+   81|      1|    add_coverage_2();
+   82|      1|
+   83|      1|    nested_fns::outer_not_covered(is_true);
+   84|      1|    nested_fns::outer(is_true);
+   85|      1|    nested_fns::outer_both_covered(is_true);
+   86|      1|}
+
diff --git a/tests/run-coverage/no_cov_crate.rs b/tests/run-coverage/no_cov_crate.rs
new file mode 100644
index 00000000000..0bfbdda2cab
--- /dev/null
+++ b/tests/run-coverage/no_cov_crate.rs
@@ -0,0 +1,86 @@
+// Enables `no_coverage` on the entire crate
+#![feature(no_coverage)]
+
+#[no_coverage]
+fn do_not_add_coverage_1() {
+    println!("called but not covered");
+}
+
+fn do_not_add_coverage_2() {
+    #![no_coverage]
+    println!("called but not covered");
+}
+
+#[no_coverage]
+fn do_not_add_coverage_not_called() {
+    println!("not called and not covered");
+}
+
+fn add_coverage_1() {
+    println!("called and covered");
+}
+
+fn add_coverage_2() {
+    println!("called and covered");
+}
+
+fn add_coverage_not_called() {
+    println!("not called but covered");
+}
+
+// FIXME: These test-cases illustrate confusing results of nested functions.
+// See https://github.com/rust-lang/rust/issues/93319
+mod nested_fns {
+    #[no_coverage]
+    pub fn outer_not_covered(is_true: bool) {
+        fn inner(is_true: bool) {
+            if is_true {
+                println!("called and covered");
+            } else {
+                println!("absolutely not covered");
+            }
+        }
+        println!("called but not covered");
+        inner(is_true);
+    }
+
+    pub fn outer(is_true: bool) {
+        println!("called and covered");
+        inner_not_covered(is_true);
+
+        #[no_coverage]
+        fn inner_not_covered(is_true: bool) {
+            if is_true {
+                println!("called but not covered");
+            } else {
+                println!("absolutely not covered");
+            }
+        }
+    }
+
+    pub fn outer_both_covered(is_true: bool) {
+        println!("called and covered");
+        inner(is_true);
+
+        fn inner(is_true: bool) {
+            if is_true {
+                println!("called and covered");
+            } else {
+                println!("absolutely not covered");
+            }
+        }
+    }
+}
+
+fn main() {
+    let is_true = std::env::args().len() == 1;
+
+    do_not_add_coverage_1();
+    do_not_add_coverage_2();
+    add_coverage_1();
+    add_coverage_2();
+
+    nested_fns::outer_not_covered(is_true);
+    nested_fns::outer(is_true);
+    nested_fns::outer_both_covered(is_true);
+}
diff --git a/tests/run-coverage/overflow.coverage b/tests/run-coverage/overflow.coverage
new file mode 100644
index 00000000000..95043759166
--- /dev/null
+++ b/tests/run-coverage/overflow.coverage
@@ -0,0 +1,64 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// failure-status: 101
+    3|       |
+    4|      4|fn might_overflow(to_add: u32) -> u32 {
+    5|      4|    if to_add > 5 {
+    6|      1|        println!("this will probably overflow");
+    7|      3|    }
+    8|      4|    let add_to = u32::MAX - 5;
+    9|      4|    println!("does {} + {} overflow?", add_to, to_add);
+   10|      4|    let result = to_add + add_to;
+   11|      4|    println!("continuing after overflow check");
+   12|      4|    result
+   13|      4|}
+   14|       |
+   15|      1|fn main() -> Result<(),u8> {
+   16|      1|    let mut countdown = 10;
+   17|     11|    while countdown > 0 {
+   18|     11|        if countdown == 1 {
+   19|      1|            let result = might_overflow(10);
+   20|      1|            println!("Result: {}", result);
+   21|     10|        } else if countdown < 5 {
+   22|      3|            let result = might_overflow(1);
+   23|      3|            println!("Result: {}", result);
+   24|      6|        }
+   25|     10|        countdown -= 1;
+   26|       |    }
+   27|      0|    Ok(())
+   28|      0|}
+   29|       |
+   30|       |// Notes:
+   31|       |//   1. Compare this program and its coverage results to those of the very similar test `assert.rs`,
+   32|       |//      and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`.
+   33|       |//   2. This test confirms the coverage generated when a program passes or fails a
+   34|       |//      compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case).
+   35|       |//   3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`,
+   36|       |//      compiler-generated assertion failures are assumed to be a symptom of a program bug, not
+   37|       |//      expected behavior. To simplify the coverage graphs and keep instrumented programs as
+   38|       |//      small and fast as possible, `Assert` terminators are assumed to always succeed, and
+   39|       |//      therefore are considered "non-branching" terminators. So, an `Assert` terminator does not
+   40|       |//      get its own coverage counter.
+   41|       |//   4. After an unhandled panic or failed Assert, coverage results may not always be intuitive.
+   42|       |//      In this test, the final count for the statements after the `if` block in `might_overflow()`
+   43|       |//      is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending
+   44|       |//      on the MIR graph and the structure of the code, this count could have been 3 (which might
+   45|       |//      have been valid for the overflowed add `+`, but should have been 4 for the lines before
+   46|       |//      the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented
+   47|       |//      via StatementKind::Counter at the end of the block, but (as in the case in this test),
+   48|       |//      a CounterKind::Expression is always evaluated. In this case, the expression was based on
+   49|       |//      a `Counter` incremented as part of the evaluation of the `if` expression, which was
+   50|       |//      executed, and counted, 4 times, before reaching the overflow add.
+   51|       |
+   52|       |// If the program did not overflow, the coverage for `might_overflow()` would look like this:
+   53|       |//
+   54|       |//     4|       |fn might_overflow(to_add: u32) -> u32 {
+   55|       |//     5|      4|    if to_add > 5 {
+   56|       |//     6|      0|        println!("this will probably overflow");
+   57|       |//     7|      4|    }
+   58|       |//     8|      4|    let add_to = u32::MAX - 5;
+   59|       |//     9|      4|    println!("does {} + {} overflow?", add_to, to_add);
+   60|       |//    10|      4|    let result = to_add + add_to;
+   61|       |//    11|      4|    println!("continuing after overflow check");
+   62|       |//    12|      4|    result
+   63|       |//    13|      4|}
+
diff --git a/tests/run-coverage/overflow.rs b/tests/run-coverage/overflow.rs
new file mode 100644
index 00000000000..7df8de6f3cd
--- /dev/null
+++ b/tests/run-coverage/overflow.rs
@@ -0,0 +1,63 @@
+#![allow(unused_assignments)]
+// failure-status: 101
+
+fn might_overflow(to_add: u32) -> u32 {
+    if to_add > 5 {
+        println!("this will probably overflow");
+    }
+    let add_to = u32::MAX - 5;
+    println!("does {} + {} overflow?", add_to, to_add);
+    let result = to_add + add_to;
+    println!("continuing after overflow check");
+    result
+}
+
+fn main() -> Result<(),u8> {
+    let mut countdown = 10;
+    while countdown > 0 {
+        if countdown == 1 {
+            let result = might_overflow(10);
+            println!("Result: {}", result);
+        } else if countdown < 5 {
+            let result = might_overflow(1);
+            println!("Result: {}", result);
+        }
+        countdown -= 1;
+    }
+    Ok(())
+}
+
+// Notes:
+//   1. Compare this program and its coverage results to those of the very similar test `assert.rs`,
+//      and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`.
+//   2. This test confirms the coverage generated when a program passes or fails a
+//      compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case).
+//   3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`,
+//      compiler-generated assertion failures are assumed to be a symptom of a program bug, not
+//      expected behavior. To simplify the coverage graphs and keep instrumented programs as
+//      small and fast as possible, `Assert` terminators are assumed to always succeed, and
+//      therefore are considered "non-branching" terminators. So, an `Assert` terminator does not
+//      get its own coverage counter.
+//   4. After an unhandled panic or failed Assert, coverage results may not always be intuitive.
+//      In this test, the final count for the statements after the `if` block in `might_overflow()`
+//      is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending
+//      on the MIR graph and the structure of the code, this count could have been 3 (which might
+//      have been valid for the overflowed add `+`, but should have been 4 for the lines before
+//      the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented
+//      via StatementKind::Counter at the end of the block, but (as in the case in this test),
+//      a CounterKind::Expression is always evaluated. In this case, the expression was based on
+//      a `Counter` incremented as part of the evaluation of the `if` expression, which was
+//      executed, and counted, 4 times, before reaching the overflow add.
+
+// If the program did not overflow, the coverage for `might_overflow()` would look like this:
+//
+//     4|       |fn might_overflow(to_add: u32) -> u32 {
+//     5|      4|    if to_add > 5 {
+//     6|      0|        println!("this will probably overflow");
+//     7|      4|    }
+//     8|      4|    let add_to = u32::MAX - 5;
+//     9|      4|    println!("does {} + {} overflow?", add_to, to_add);
+//    10|      4|    let result = to_add + add_to;
+//    11|      4|    println!("continuing after overflow check");
+//    12|      4|    result
+//    13|      4|}
diff --git a/tests/run-coverage/panic_unwind.coverage b/tests/run-coverage/panic_unwind.coverage
new file mode 100644
index 00000000000..58b9ba448ee
--- /dev/null
+++ b/tests/run-coverage/panic_unwind.coverage
@@ -0,0 +1,32 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// failure-status: 101
+    3|       |
+    4|      4|fn might_panic(should_panic: bool) {
+    5|      4|    if should_panic {
+    6|      1|        println!("panicking...");
+    7|      1|        panic!("panics");
+    8|      3|    } else {
+    9|      3|        println!("Don't Panic");
+   10|      3|    }
+   11|      3|}
+   12|       |
+   13|      1|fn main() -> Result<(), u8> {
+   14|      1|    let mut countdown = 10;
+   15|     11|    while countdown > 0 {
+   16|     11|        if countdown == 1 {
+   17|      1|            might_panic(true);
+   18|     10|        } else if countdown < 5 {
+   19|      3|            might_panic(false);
+   20|      6|        }
+   21|     10|        countdown -= 1;
+   22|       |    }
+   23|      0|    Ok(())
+   24|      0|}
+   25|       |
+   26|       |// Notes:
+   27|       |//   1. Compare this program and its coverage results to those of the similar tests `abort.rs` and
+   28|       |//      `try_error_result.rs`.
+   29|       |//   2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
+   30|       |//      normal program exit cleanup, including writing out the current values of the coverage
+   31|       |//      counters.
+
diff --git a/tests/run-coverage/panic_unwind.rs b/tests/run-coverage/panic_unwind.rs
new file mode 100644
index 00000000000..638d2eb6aaa
--- /dev/null
+++ b/tests/run-coverage/panic_unwind.rs
@@ -0,0 +1,31 @@
+#![allow(unused_assignments)]
+// failure-status: 101
+
+fn might_panic(should_panic: bool) {
+    if should_panic {
+        println!("panicking...");
+        panic!("panics");
+    } else {
+        println!("Don't Panic");
+    }
+}
+
+fn main() -> Result<(), u8> {
+    let mut countdown = 10;
+    while countdown > 0 {
+        if countdown == 1 {
+            might_panic(true);
+        } else if countdown < 5 {
+            might_panic(false);
+        }
+        countdown -= 1;
+    }
+    Ok(())
+}
+
+// Notes:
+//   1. Compare this program and its coverage results to those of the similar tests `abort.rs` and
+//      `try_error_result.rs`.
+//   2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
+//      normal program exit cleanup, including writing out the current values of the coverage
+//      counters.
diff --git a/tests/run-coverage/partial_eq.coverage b/tests/run-coverage/partial_eq.coverage
new file mode 100644
index 00000000000..a77175af663
--- /dev/null
+++ b/tests/run-coverage/partial_eq.coverage
@@ -0,0 +1,48 @@
+    1|       |// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the
+    2|       |// structure of this test.
+    3|       |
+    4|      2|#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+                       ^0            ^0      ^0     ^1       ^1 ^0^0
+    5|       |pub struct Version {
+    6|       |    major: usize,
+    7|       |    minor: usize,
+    8|       |    patch: usize,
+    9|       |}
+   10|       |
+   11|       |impl Version {
+   12|      2|    pub fn new(major: usize, minor: usize, patch: usize) -> Self {
+   13|      2|        Self {
+   14|      2|            major,
+   15|      2|            minor,
+   16|      2|            patch,
+   17|      2|        }
+   18|      2|    }
+   19|       |}
+   20|       |
+   21|      1|fn main() {
+   22|      1|    let version_3_2_1 = Version::new(3, 2, 1);
+   23|      1|    let version_3_3_0 = Version::new(3, 3, 0);
+   24|      1|
+   25|      1|    println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0);
+   26|      1|}
+   27|       |
+   28|       |/*
+   29|       |
+   30|       |This test verifies a bug was fixed that otherwise generated this error:
+   31|       |
+   32|       |thread 'rustc' panicked at 'No counters provided the source_hash for function:
+   33|       |    Instance {
+   34|       |        def: Item(WithOptConstParam {
+   35|       |            did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp),
+   36|       |            const_param_did: None
+   37|       |        }),
+   38|       |        substs: []
+   39|       |    }'
+   40|       |The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage
+   41|       |without a code region associated with any `Counter`. Code regions were associated with at least
+   42|       |one expression, which is allowed, but the `function_source_hash` was only passed to the codegen
+   43|       |(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the
+   44|       |`function_source_hash` without a code region, if necessary.
+   45|       |
+   46|       |*/
+
diff --git a/tests/run-coverage/partial_eq.rs b/tests/run-coverage/partial_eq.rs
new file mode 100644
index 00000000000..4ceaba9b111
--- /dev/null
+++ b/tests/run-coverage/partial_eq.rs
@@ -0,0 +1,46 @@
+// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the
+// structure of this test.
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Version {
+    major: usize,
+    minor: usize,
+    patch: usize,
+}
+
+impl Version {
+    pub fn new(major: usize, minor: usize, patch: usize) -> Self {
+        Self {
+            major,
+            minor,
+            patch,
+        }
+    }
+}
+
+fn main() {
+    let version_3_2_1 = Version::new(3, 2, 1);
+    let version_3_3_0 = Version::new(3, 3, 0);
+
+    println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0);
+}
+
+/*
+
+This test verifies a bug was fixed that otherwise generated this error:
+
+thread 'rustc' panicked at 'No counters provided the source_hash for function:
+    Instance {
+        def: Item(WithOptConstParam {
+            did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp),
+            const_param_did: None
+        }),
+        substs: []
+    }'
+The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage
+without a code region associated with any `Counter`. Code regions were associated with at least
+one expression, which is allowed, but the `function_source_hash` was only passed to the codegen
+(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the
+`function_source_hash` without a code region, if necessary.
+
+*/
diff --git a/tests/run-coverage/simple_loop.coverage b/tests/run-coverage/simple_loop.coverage
new file mode 100644
index 00000000000..feb83bad674
--- /dev/null
+++ b/tests/run-coverage/simple_loop.coverage
@@ -0,0 +1,37 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|
+    9|      1|    let mut countdown = 0;
+   10|      1|
+   11|      1|    if
+   12|      1|        is_true
+   13|      1|    {
+   14|      1|        countdown
+   15|      1|        =
+   16|      1|            10
+   17|      1|        ;
+   18|      1|    }
+                   ^0
+   19|       |
+   20|       |    loop
+   21|       |    {
+   22|       |        if
+   23|     11|            countdown
+   24|     11|                ==
+   25|     11|            0
+   26|       |        {
+   27|      1|            break
+   28|       |            ;
+   29|     10|        }
+   30|     10|        countdown
+   31|     10|        -=
+   32|     10|        1
+   33|       |        ;
+   34|       |    }
+   35|      1|}
+
diff --git a/tests/run-coverage/simple_loop.rs b/tests/run-coverage/simple_loop.rs
new file mode 100644
index 00000000000..6f7f23475b8
--- /dev/null
+++ b/tests/run-coverage/simple_loop.rs
@@ -0,0 +1,35 @@
+#![allow(unused_assignments)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 0;
+
+    if
+        is_true
+    {
+        countdown
+        =
+            10
+        ;
+    }
+
+    loop
+    {
+        if
+            countdown
+                ==
+            0
+        {
+            break
+            ;
+        }
+        countdown
+        -=
+        1
+        ;
+    }
+}
diff --git a/tests/run-coverage/simple_match.coverage b/tests/run-coverage/simple_match.coverage
new file mode 100644
index 00000000000..b9298213111
--- /dev/null
+++ b/tests/run-coverage/simple_match.coverage
@@ -0,0 +1,45 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|      1|fn main() {
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|
+    9|      1|    let mut countdown = 1;
+   10|      1|    if is_true {
+   11|      1|        countdown = 0;
+   12|      1|    }
+                   ^0
+   13|       |
+   14|       |    for
+   15|       |        _
+   16|       |    in
+   17|      3|        0..2
+   18|       |    {
+   19|       |        let z
+   20|       |        ;
+   21|       |        match
+   22|      2|            countdown
+   23|       |        {
+   24|      1|            x
+   25|       |            if
+   26|      2|                x
+   27|      2|                    <
+   28|      2|                1
+   29|       |            =>
+   30|      1|            {
+   31|      1|                z = countdown
+   32|      1|                ;
+   33|      1|                let y = countdown
+   34|      1|                ;
+   35|      1|                countdown = 10
+   36|      1|                ;
+   37|      1|            }
+   38|       |            _
+   39|       |            =>
+   40|      1|            {}
+   41|       |        }
+   42|       |    }
+   43|      1|}
+
diff --git a/tests/run-coverage/simple_match.rs b/tests/run-coverage/simple_match.rs
new file mode 100644
index 00000000000..be99e59a826
--- /dev/null
+++ b/tests/run-coverage/simple_match.rs
@@ -0,0 +1,43 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    // dependent conditions.
+    let is_true = std::env::args().len() == 1;
+
+    let mut countdown = 1;
+    if is_true {
+        countdown = 0;
+    }
+
+    for
+        _
+    in
+        0..2
+    {
+        let z
+        ;
+        match
+            countdown
+        {
+            x
+            if
+                x
+                    <
+                1
+            =>
+            {
+                z = countdown
+                ;
+                let y = countdown
+                ;
+                countdown = 10
+                ;
+            }
+            _
+            =>
+            {}
+        }
+    }
+}
diff --git a/tests/run-coverage/sort_groups.coverage b/tests/run-coverage/sort_groups.coverage
new file mode 100644
index 00000000000..81468cb35da
--- /dev/null
+++ b/tests/run-coverage/sort_groups.coverage
@@ -0,0 +1,49 @@
+    1|       |// compile-flags: --edition=2021
+    2|       |
+    3|       |// Demonstrate that `sort_subviews.py` can sort instantiation groups into a
+    4|       |// predictable order, while preserving their heterogeneous contents.
+    5|       |
+    6|      1|fn main() {
+    7|      1|    let cond = std::env::args().len() > 1;
+    8|      1|    generic_fn::<()>(cond);
+    9|      1|    generic_fn::<&'static str>(!cond);
+   10|      1|    if false {
+   11|      0|        generic_fn::<char>(cond);
+   12|      1|    }
+   13|      1|    generic_fn::<i32>(cond);
+   14|      1|    other_fn();
+   15|      1|}
+   16|       |
+   17|      3|fn generic_fn<T>(cond: bool) {
+   18|      3|    if cond {
+   19|      1|        println!("{}", std::any::type_name::<T>());
+   20|      2|    }
+   21|      3|}
+  ------------------
+  | Unexecuted instantiation: sort_groups::generic_fn::<char>
+  ------------------
+  | sort_groups::generic_fn::<&str>:
+  |   17|      1|fn generic_fn<T>(cond: bool) {
+  |   18|      1|    if cond {
+  |   19|      1|        println!("{}", std::any::type_name::<T>());
+  |   20|      1|    }
+  |                   ^0
+  |   21|      1|}
+  ------------------
+  | sort_groups::generic_fn::<()>:
+  |   17|      1|fn generic_fn<T>(cond: bool) {
+  |   18|      1|    if cond {
+  |   19|      0|        println!("{}", std::any::type_name::<T>());
+  |   20|      1|    }
+  |   21|      1|}
+  ------------------
+  | sort_groups::generic_fn::<i32>:
+  |   17|      1|fn generic_fn<T>(cond: bool) {
+  |   18|      1|    if cond {
+  |   19|      0|        println!("{}", std::any::type_name::<T>());
+  |   20|      1|    }
+  |   21|      1|}
+  ------------------
+   22|       |
+   23|      1|fn other_fn() {}
+
diff --git a/tests/run-coverage/sort_groups.rs b/tests/run-coverage/sort_groups.rs
new file mode 100644
index 00000000000..f89f9f3ec61
--- /dev/null
+++ b/tests/run-coverage/sort_groups.rs
@@ -0,0 +1,23 @@
+// compile-flags: --edition=2021
+
+// Demonstrate that `sort_subviews.py` can sort instantiation groups into a
+// predictable order, while preserving their heterogeneous contents.
+
+fn main() {
+    let cond = std::env::args().len() > 1;
+    generic_fn::<()>(cond);
+    generic_fn::<&'static str>(!cond);
+    if false {
+        generic_fn::<char>(cond);
+    }
+    generic_fn::<i32>(cond);
+    other_fn();
+}
+
+fn generic_fn<T>(cond: bool) {
+    if cond {
+        println!("{}", std::any::type_name::<T>());
+    }
+}
+
+fn other_fn() {}
diff --git a/tests/run-coverage/test_harness.coverage b/tests/run-coverage/test_harness.coverage
new file mode 100644
index 00000000000..93bd1cfcb48
--- /dev/null
+++ b/tests/run-coverage/test_harness.coverage
@@ -0,0 +1,11 @@
+    1|       |// Verify that the entry point injected by the test harness doesn't cause
+    2|       |// weird artifacts in the coverage report (e.g. issue #10749).
+    3|       |
+    4|       |// compile-flags: --test
+    5|       |
+    6|       |#[allow(dead_code)]
+    7|      0|fn unused() {}
+    8|       |
+    9|      1|#[test]
+   10|      1|fn my_test() {}
+
diff --git a/tests/run-coverage/test_harness.rs b/tests/run-coverage/test_harness.rs
new file mode 100644
index 00000000000..12a755734c1
--- /dev/null
+++ b/tests/run-coverage/test_harness.rs
@@ -0,0 +1,10 @@
+// Verify that the entry point injected by the test harness doesn't cause
+// weird artifacts in the coverage report (e.g. issue #10749).
+
+// compile-flags: --test
+
+#[allow(dead_code)]
+fn unused() {}
+
+#[test]
+fn my_test() {}
diff --git a/tests/run-coverage/tight_inf_loop.coverage b/tests/run-coverage/tight_inf_loop.coverage
new file mode 100644
index 00000000000..2d4c57f451a
--- /dev/null
+++ b/tests/run-coverage/tight_inf_loop.coverage
@@ -0,0 +1,6 @@
+    1|      1|fn main() {
+    2|      1|    if false {
+    3|      0|        loop {}
+    4|      1|    }
+    5|      1|}
+
diff --git a/tests/run-coverage/tight_inf_loop.rs b/tests/run-coverage/tight_inf_loop.rs
new file mode 100644
index 00000000000..cef99027aaa
--- /dev/null
+++ b/tests/run-coverage/tight_inf_loop.rs
@@ -0,0 +1,5 @@
+fn main() {
+    if false {
+        loop {}
+    }
+}
diff --git a/tests/run-coverage/try_error_result.coverage b/tests/run-coverage/try_error_result.coverage
new file mode 100644
index 00000000000..efe573a5607
--- /dev/null
+++ b/tests/run-coverage/try_error_result.coverage
@@ -0,0 +1,125 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// failure-status: 1
+    3|       |
+    4|      6|fn call(return_error: bool) -> Result<(),()> {
+    5|      6|    if return_error {
+    6|      1|        Err(())
+    7|       |    } else {
+    8|      5|        Ok(())
+    9|       |    }
+   10|      6|}
+   11|       |
+   12|      1|fn test1() -> Result<(),()> {
+   13|      1|    let mut
+   14|      1|        countdown = 10
+   15|       |    ;
+   16|       |    for
+   17|       |        _
+   18|       |    in
+   19|      6|        0..10
+   20|       |    {
+   21|      6|        countdown
+   22|      6|            -= 1
+   23|      6|        ;
+   24|      6|        if
+   25|      6|            countdown < 5
+   26|       |        {
+   27|      1|            call(/*return_error=*/ true)?;
+   28|      0|            call(/*return_error=*/ false)?;
+   29|       |        }
+   30|       |        else
+   31|       |        {
+   32|      5|            call(/*return_error=*/ false)?;
+                                                       ^0
+   33|       |        }
+   34|       |    }
+   35|      0|    Ok(())
+   36|      1|}
+   37|       |
+   38|       |struct Thing1;
+   39|       |impl Thing1 {
+   40|     18|    fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
+   41|     18|        if return_error {
+   42|      1|            Err(())
+   43|       |        } else {
+   44|     17|            Ok(Thing2{})
+   45|       |        }
+   46|     18|    }
+   47|       |}
+   48|       |
+   49|       |struct Thing2;
+   50|       |impl Thing2 {
+   51|     17|    fn call(&self, return_error: bool) -> Result<u32,()> {
+   52|     17|        if return_error {
+   53|      2|            Err(())
+   54|       |        } else {
+   55|     15|            Ok(57)
+   56|       |        }
+   57|     17|    }
+   58|       |}
+   59|       |
+   60|      1|fn test2() -> Result<(),()> {
+   61|      1|    let thing1 = Thing1{};
+   62|      1|    let mut
+   63|      1|        countdown = 10
+   64|       |    ;
+   65|       |    for
+   66|       |        _
+   67|       |    in
+   68|      6|        0..10
+   69|       |    {
+   70|      6|        countdown
+   71|      6|            -= 1
+   72|      6|        ;
+   73|      6|        if
+   74|      6|            countdown < 5
+   75|       |        {
+   76|      1|            thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
+                                                            ^0
+   77|      1|            thing1
+   78|      1|                .
+   79|      1|                get_thing_2(/*return_error=*/ false)
+   80|      0|                ?
+   81|       |                .
+   82|      1|                call(/*return_error=*/ true)
+   83|      1|                .
+   84|      1|                expect_err(
+   85|      1|                    "call should fail"
+   86|      1|                );
+   87|      1|            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
+                              ^0                                                ^0                          ^0
+   88|      0|            assert_eq!(val, 57);
+   89|      0|            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
+   90|      0|            assert_eq!(val, 57);
+   91|       |        }
+   92|       |        else
+   93|       |        {
+   94|      5|            let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
+                                                                               ^0                             ^0
+   95|      5|            assert_eq!(val, 57);
+   96|      5|            let val = thing1
+   97|      5|                .get_thing_2(/*return_error=*/ false)?
+                                                                   ^0
+   98|      5|                .call(/*return_error=*/ false)?;
+                                                            ^0
+   99|      5|            assert_eq!(val, 57);
+  100|      5|            let val = thing1
+  101|      5|                .get_thing_2(/*return_error=*/ false)
+  102|      0|                ?
+  103|      5|                .call(/*return_error=*/ false)
+  104|      0|                ?
+  105|       |                ;
+  106|      5|            assert_eq!(val, 57);
+  107|       |        }
+  108|       |    }
+  109|      0|    Ok(())
+  110|      1|}
+  111|       |
+  112|      1|fn main() -> Result<(),()> {
+  113|      1|    test1().expect_err("test1 should fail");
+  114|      1|    test2()
+  115|      1|    ?
+  116|       |    ;
+  117|      0|    Ok(())
+  118|      1|}
+
diff --git a/tests/run-coverage/try_error_result.rs b/tests/run-coverage/try_error_result.rs
new file mode 100644
index 00000000000..9eb1d2db218
--- /dev/null
+++ b/tests/run-coverage/try_error_result.rs
@@ -0,0 +1,118 @@
+#![allow(unused_assignments)]
+// failure-status: 1
+
+fn call(return_error: bool) -> Result<(),()> {
+    if return_error {
+        Err(())
+    } else {
+        Ok(())
+    }
+}
+
+fn test1() -> Result<(),()> {
+    let mut
+        countdown = 10
+    ;
+    for
+        _
+    in
+        0..10
+    {
+        countdown
+            -= 1
+        ;
+        if
+            countdown < 5
+        {
+            call(/*return_error=*/ true)?;
+            call(/*return_error=*/ false)?;
+        }
+        else
+        {
+            call(/*return_error=*/ false)?;
+        }
+    }
+    Ok(())
+}
+
+struct Thing1;
+impl Thing1 {
+    fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
+        if return_error {
+            Err(())
+        } else {
+            Ok(Thing2{})
+        }
+    }
+}
+
+struct Thing2;
+impl Thing2 {
+    fn call(&self, return_error: bool) -> Result<u32,()> {
+        if return_error {
+            Err(())
+        } else {
+            Ok(57)
+        }
+    }
+}
+
+fn test2() -> Result<(),()> {
+    let thing1 = Thing1{};
+    let mut
+        countdown = 10
+    ;
+    for
+        _
+    in
+        0..10
+    {
+        countdown
+            -= 1
+        ;
+        if
+            countdown < 5
+        {
+            thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
+            thing1
+                .
+                get_thing_2(/*return_error=*/ false)
+                ?
+                .
+                call(/*return_error=*/ true)
+                .
+                expect_err(
+                    "call should fail"
+                );
+            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
+            assert_eq!(val, 57);
+            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
+            assert_eq!(val, 57);
+        }
+        else
+        {
+            let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
+            assert_eq!(val, 57);
+            let val = thing1
+                .get_thing_2(/*return_error=*/ false)?
+                .call(/*return_error=*/ false)?;
+            assert_eq!(val, 57);
+            let val = thing1
+                .get_thing_2(/*return_error=*/ false)
+                ?
+                .call(/*return_error=*/ false)
+                ?
+                ;
+            assert_eq!(val, 57);
+        }
+    }
+    Ok(())
+}
+
+fn main() -> Result<(),()> {
+    test1().expect_err("test1 should fail");
+    test2()
+    ?
+    ;
+    Ok(())
+}
diff --git a/tests/run-coverage/unused.coverage b/tests/run-coverage/unused.coverage
new file mode 100644
index 00000000000..15fcf21c0ef
--- /dev/null
+++ b/tests/run-coverage/unused.coverage
@@ -0,0 +1,62 @@
+    1|      2|fn foo<T>(x: T) {
+    2|      2|    let mut i = 0;
+    3|     22|    while i < 10 {
+    4|     20|        i != 0 || i != 0;
+                                ^2
+    5|     20|        i += 1;
+    6|       |    }
+    7|      2|}
+  ------------------
+  | unused::foo::<f32>:
+  |    1|      1|fn foo<T>(x: T) {
+  |    2|      1|    let mut i = 0;
+  |    3|     11|    while i < 10 {
+  |    4|     10|        i != 0 || i != 0;
+  |                                ^1
+  |    5|     10|        i += 1;
+  |    6|       |    }
+  |    7|      1|}
+  ------------------
+  | unused::foo::<u32>:
+  |    1|      1|fn foo<T>(x: T) {
+  |    2|      1|    let mut i = 0;
+  |    3|     11|    while i < 10 {
+  |    4|     10|        i != 0 || i != 0;
+  |                                ^1
+  |    5|     10|        i += 1;
+  |    6|       |    }
+  |    7|      1|}
+  ------------------
+    8|       |
+    9|      0|fn unused_template_func<T>(x: T) {
+   10|      0|    let mut i = 0;
+   11|      0|    while i < 10 {
+   12|      0|        i != 0 || i != 0;
+   13|      0|        i += 1;
+   14|       |    }
+   15|      0|}
+   16|       |
+   17|      0|fn unused_func(mut a: u32) {
+   18|      0|    if a != 0 {
+   19|      0|        a += 1;
+   20|      0|    }
+   21|      0|}
+   22|       |
+   23|      0|fn unused_func2(mut a: u32) {
+   24|      0|    if a != 0 {
+   25|      0|        a += 1;
+   26|      0|    }
+   27|      0|}
+   28|       |
+   29|      0|fn unused_func3(mut a: u32) {
+   30|      0|    if a != 0 {
+   31|      0|        a += 1;
+   32|      0|    }
+   33|      0|}
+   34|       |
+   35|      1|fn main() -> Result<(), u8> {
+   36|      1|    foo::<u32>(0);
+   37|      1|    foo::<f32>(0.0);
+   38|      1|    Ok(())
+   39|      1|}
+
diff --git a/tests/run-coverage/unused.rs b/tests/run-coverage/unused.rs
new file mode 100644
index 00000000000..fb6113eb01c
--- /dev/null
+++ b/tests/run-coverage/unused.rs
@@ -0,0 +1,39 @@
+fn foo<T>(x: T) {
+    let mut i = 0;
+    while i < 10 {
+        i != 0 || i != 0;
+        i += 1;
+    }
+}
+
+fn unused_template_func<T>(x: T) {
+    let mut i = 0;
+    while i < 10 {
+        i != 0 || i != 0;
+        i += 1;
+    }
+}
+
+fn unused_func(mut a: u32) {
+    if a != 0 {
+        a += 1;
+    }
+}
+
+fn unused_func2(mut a: u32) {
+    if a != 0 {
+        a += 1;
+    }
+}
+
+fn unused_func3(mut a: u32) {
+    if a != 0 {
+        a += 1;
+    }
+}
+
+fn main() -> Result<(), u8> {
+    foo::<u32>(0);
+    foo::<f32>(0.0);
+    Ok(())
+}
diff --git a/tests/run-coverage/unused_mod.coverage b/tests/run-coverage/unused_mod.coverage
new file mode 100644
index 00000000000..e1d82f66f75
--- /dev/null
+++ b/tests/run-coverage/unused_mod.coverage
@@ -0,0 +1,13 @@
+$DIR/auxiliary/unused_mod_helper.rs:
+    1|      0|pub fn never_called_function() {
+    2|      0|    println!("I am never called");
+    3|      0|}
+
+$DIR/unused_mod.rs:
+    1|       |#[path = "auxiliary/unused_mod_helper.rs"]
+    2|       |mod unused_module;
+    3|       |
+    4|      1|fn main() {
+    5|      1|    println!("hello world!");
+    6|      1|}
+
diff --git a/tests/run-coverage/unused_mod.rs b/tests/run-coverage/unused_mod.rs
new file mode 100644
index 00000000000..6e62839c998
--- /dev/null
+++ b/tests/run-coverage/unused_mod.rs
@@ -0,0 +1,6 @@
+#[path = "auxiliary/unused_mod_helper.rs"]
+mod unused_module;
+
+fn main() {
+    println!("hello world!");
+}
diff --git a/tests/run-coverage/uses_crate.coverage b/tests/run-coverage/uses_crate.coverage
new file mode 100644
index 00000000000..a3b78e21405
--- /dev/null
+++ b/tests/run-coverage/uses_crate.coverage
@@ -0,0 +1,170 @@
+$DIR/auxiliary/used_crate.rs:
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |// compile-flags: -C opt-level=3
+    3|       |use std::fmt::Debug; // ^^ validates coverage now works with optimizations
+    4|       |
+    5|      1|pub fn used_function() {
+    6|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    7|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    8|      1|    // dependent conditions.
+    9|      1|    let is_true = std::env::args().len() == 1;
+   10|      1|    let mut countdown = 0;
+   11|      1|    if is_true {
+   12|      1|        countdown = 10;
+   13|      1|    }
+                   ^0
+   14|      1|    use_this_lib_crate();
+   15|      1|}
+   16|       |
+   17|      2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+   18|      2|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+   19|      2|}
+  ------------------
+  | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+  ------------------
+  | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
+  |   17|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+  |   18|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+  |   19|      1|}
+  ------------------
+  | used_crate::used_only_from_bin_crate_generic_function::<&str>:
+  |   17|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+  |   18|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+  |   19|      1|}
+  ------------------
+   20|       |// Expect for above function: `Unexecuted instantiation` (see below)
+   21|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+   22|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+   23|      2|}
+  ------------------
+  | used_crate::used_only_from_this_lib_crate_generic_function::<&str>:
+  |   21|      1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   22|      1|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+  |   23|      1|}
+  ------------------
+  | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+  |   21|      1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   22|      1|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+  |   23|      1|}
+  ------------------
+   24|       |
+   25|      2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+   26|      2|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+   27|      2|}
+  ------------------
+  | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
+  |   25|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   26|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   27|      1|}
+  ------------------
+  | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+  |   25|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   26|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   27|      1|}
+  ------------------
+   28|       |
+   29|      2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+   30|      2|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+   31|      2|}
+  ------------------
+  | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+  |   29|      1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   30|      1|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   31|      1|}
+  ------------------
+  | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+  |   29|      1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   30|      1|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   31|      1|}
+  ------------------
+   32|       |
+   33|      0|pub fn unused_generic_function<T: Debug>(arg: T) {
+   34|      0|    println!("unused_generic_function with {:?}", arg);
+   35|      0|}
+   36|       |
+   37|      0|pub fn unused_function() {
+   38|      0|    let is_true = std::env::args().len() == 1;
+   39|      0|    let mut countdown = 2;
+   40|      0|    if !is_true {
+   41|      0|        countdown = 20;
+   42|      0|    }
+   43|      0|}
+   44|       |
+   45|      0|fn unused_private_function() {
+   46|      0|    let is_true = std::env::args().len() == 1;
+   47|      0|    let mut countdown = 2;
+   48|      0|    if !is_true {
+   49|      0|        countdown = 20;
+   50|      0|    }
+   51|      0|}
+   52|       |
+   53|      1|fn use_this_lib_crate() {
+   54|      1|    used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+   55|      1|    used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+   56|      1|        "used from library used_crate.rs",
+   57|      1|    );
+   58|      1|    let some_vec = vec![5, 6, 7, 8];
+   59|      1|    used_only_from_this_lib_crate_generic_function(some_vec);
+   60|      1|    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+   61|      1|}
+   62|       |
+   63|       |// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results,
+   64|       |// for example:
+   65|       |//
+   66|       |// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+   67|       |//
+   68|       |// These notices appear when `llvm-cov` shows instantiations. This may be a
+   69|       |// default option, but it can be suppressed with:
+   70|       |//
+   71|       |// ```shell
+   72|       |// $ `llvm-cov show --show-instantiations=0 ...`
+   73|       |// ```
+   74|       |//
+   75|       |// The notice is triggered because the function is unused by the library itself,
+   76|       |// and when the library is compiled, a synthetic function is generated, so
+   77|       |// unused function coverage can be reported. Coverage can be skipped for unused
+   78|       |// generic functions with:
+   79|       |//
+   80|       |// ```shell
+   81|       |// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...`
+   82|       |// ```
+   83|       |//
+   84|       |// Even though this function is used by `uses_crate.rs` (and
+   85|       |// counted), with substitutions for `T`, those instantiations are only generated
+   86|       |// when the generic function is actually used (from the binary, not from this
+   87|       |// library crate). So the test result shows coverage for all instantiated
+   88|       |// versions and their generic type substitutions, plus the `Unexecuted
+   89|       |// instantiation` message for the non-substituted version. This is valid, but
+   90|       |// unfortunately a little confusing.
+   91|       |//
+   92|       |// The library crate has its own coverage map, and the only way to show unused
+   93|       |// coverage of a generic function is to include the generic function in the
+   94|       |// coverage map, marked as an "unused function". If the library were used by
+   95|       |// another binary that never used this generic function, then it would be valid
+   96|       |// to show the unused generic, with unknown substitution (`_`).
+   97|       |//
+   98|       |// The alternative is to exclude all generics from being included in the "unused
+   99|       |// functions" list, which would then omit coverage results for
+  100|       |// `unused_generic_function<T>()`, below.
+
+$DIR/uses_crate.rs:
+    1|       |// FIXME #110395
+    2|       |// ignore-linux
+    3|       |
+    4|       |// Validates coverage now works with optimizations
+    5|       |// compile-flags: -C opt-level=3
+    6|       |
+    7|       |#![allow(unused_assignments, unused_variables)]
+    8|       |
+    9|       |// aux-build:used_crate.rs
+   10|       |extern crate used_crate;
+   11|       |
+   12|      1|fn main() {
+   13|      1|    used_crate::used_function();
+   14|      1|    let some_vec = vec![1, 2, 3, 4];
+   15|      1|    used_crate::used_only_from_bin_crate_generic_function(&some_vec);
+   16|      1|    used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+   17|      1|    used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+   18|      1|    used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?");
+   19|      1|}
+
diff --git a/tests/run-coverage/uses_crate.rs b/tests/run-coverage/uses_crate.rs
new file mode 100644
index 00000000000..ab466970f8e
--- /dev/null
+++ b/tests/run-coverage/uses_crate.rs
@@ -0,0 +1,19 @@
+// FIXME #110395
+// ignore-linux
+
+// Validates coverage now works with optimizations
+// compile-flags: -C opt-level=3
+
+#![allow(unused_assignments, unused_variables)]
+
+// aux-build:used_crate.rs
+extern crate used_crate;
+
+fn main() {
+    used_crate::used_function();
+    let some_vec = vec![1, 2, 3, 4];
+    used_crate::used_only_from_bin_crate_generic_function(&some_vec);
+    used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+    used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+    used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?");
+}
diff --git a/tests/run-coverage/uses_inline_crate.coverage b/tests/run-coverage/uses_inline_crate.coverage
new file mode 100644
index 00000000000..f878d8107c5
--- /dev/null
+++ b/tests/run-coverage/uses_inline_crate.coverage
@@ -0,0 +1,164 @@
+$DIR/auxiliary/used_inline_crate.rs:
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|       |// compile-flags: -C opt-level=3
+    4|       |// ^^ validates coverage now works with optimizations
+    5|       |use std::fmt::Debug;
+    6|       |
+    7|      1|pub fn used_function() {
+    8|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    9|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   10|      1|    // dependent conditions.
+   11|      1|    let is_true = std::env::args().len() == 1;
+   12|      1|    let mut countdown = 0;
+   13|      1|    if is_true {
+   14|      1|        countdown = 10;
+   15|      1|    }
+                   ^0
+   16|      1|    use_this_lib_crate();
+   17|      1|}
+   18|       |
+   19|       |#[inline(always)]
+   20|      1|pub fn used_inline_function() {
+   21|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   22|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   23|      1|    // dependent conditions.
+   24|      1|    let is_true = std::env::args().len() == 1;
+   25|      1|    let mut countdown = 0;
+   26|      1|    if is_true {
+   27|      1|        countdown = 10;
+   28|      1|    }
+                   ^0
+   29|      1|    use_this_lib_crate();
+   30|      1|}
+   31|       |
+   32|       |
+   33|       |
+   34|       |
+   35|       |
+   36|       |
+   37|       |
+   38|       |#[inline(always)]
+   39|      2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+   40|      2|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+   41|      2|}
+  ------------------
+  | Unexecuted instantiation: used_inline_crate::used_only_from_bin_crate_generic_function::<_>
+  ------------------
+  | used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
+  |   39|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+  |   40|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+  |   41|      1|}
+  ------------------
+  | used_inline_crate::used_only_from_bin_crate_generic_function::<&str>:
+  |   39|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+  |   40|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+  |   41|      1|}
+  ------------------
+   42|       |// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`)
+   43|       |
+   44|       |#[inline(always)]
+   45|      4|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+   46|      4|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+   47|      4|}
+  ------------------
+  | used_inline_crate::used_only_from_this_lib_crate_generic_function::<&str>:
+  |   45|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   46|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+  |   47|      2|}
+  ------------------
+  | used_inline_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+  |   45|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   46|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+  |   47|      2|}
+  ------------------
+   48|       |
+   49|       |#[inline(always)]
+   50|      3|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+   51|      3|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+   52|      3|}
+  ------------------
+  | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
+  |   50|      2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   51|      2|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   52|      2|}
+  ------------------
+  | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+  |   50|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   51|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   52|      1|}
+  ------------------
+   53|       |
+   54|       |#[inline(always)]
+   55|      3|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+   56|      3|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+   57|      3|}
+  ------------------
+  | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+  |   55|      1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   56|      1|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   57|      1|}
+  ------------------
+  | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+  |   55|      2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   56|      2|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   57|      2|}
+  ------------------
+   58|       |
+   59|       |#[inline(always)]
+   60|      0|pub fn unused_generic_function<T: Debug>(arg: T) {
+   61|      0|    println!("unused_generic_function with {:?}", arg);
+   62|      0|}
+   63|       |
+   64|       |#[inline(always)]
+   65|      0|pub fn unused_function() {
+   66|      0|    let is_true = std::env::args().len() == 1;
+   67|      0|    let mut countdown = 2;
+   68|      0|    if !is_true {
+   69|      0|        countdown = 20;
+   70|      0|    }
+   71|      0|}
+   72|       |
+   73|       |#[inline(always)]
+   74|      0|fn unused_private_function() {
+   75|      0|    let is_true = std::env::args().len() == 1;
+   76|      0|    let mut countdown = 2;
+   77|      0|    if !is_true {
+   78|      0|        countdown = 20;
+   79|      0|    }
+   80|      0|}
+   81|       |
+   82|      2|fn use_this_lib_crate() {
+   83|      2|    used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+   84|      2|    used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+   85|      2|        "used from library used_crate.rs",
+   86|      2|    );
+   87|      2|    let some_vec = vec![5, 6, 7, 8];
+   88|      2|    used_only_from_this_lib_crate_generic_function(some_vec);
+   89|      2|    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+   90|      2|}
+
+$DIR/uses_inline_crate.rs:
+    1|       |// FIXME #110395
+    2|       |// ignore-linux
+    3|       |
+    4|       |// Validates coverage now works with optimizations
+    5|       |// compile-flags: -C opt-level=3
+    6|       |
+    7|       |#![allow(unused_assignments, unused_variables)]
+    8|       |
+    9|       |// aux-build:used_inline_crate.rs
+   10|       |extern crate used_inline_crate;
+   11|       |
+   12|      1|fn main() {
+   13|      1|    used_inline_crate::used_function();
+   14|      1|    used_inline_crate::used_inline_function();
+   15|      1|    let some_vec = vec![1, 2, 3, 4];
+   16|      1|    used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec);
+   17|      1|    used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+   18|      1|    used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+   19|      1|    used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+   20|      1|        "interesting?",
+   21|      1|    );
+   22|      1|}
+
diff --git a/tests/run-coverage/uses_inline_crate.rs b/tests/run-coverage/uses_inline_crate.rs
new file mode 100644
index 00000000000..4bd66d2f89c
--- /dev/null
+++ b/tests/run-coverage/uses_inline_crate.rs
@@ -0,0 +1,22 @@
+// FIXME #110395
+// ignore-linux
+
+// Validates coverage now works with optimizations
+// compile-flags: -C opt-level=3
+
+#![allow(unused_assignments, unused_variables)]
+
+// aux-build:used_inline_crate.rs
+extern crate used_inline_crate;
+
+fn main() {
+    used_inline_crate::used_function();
+    used_inline_crate::used_inline_function();
+    let some_vec = vec![1, 2, 3, 4];
+    used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec);
+    used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+    used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+    used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+        "interesting?",
+    );
+}
diff --git a/tests/run-coverage/while.coverage b/tests/run-coverage/while.coverage
new file mode 100644
index 00000000000..efa7d083f0c
--- /dev/null
+++ b/tests/run-coverage/while.coverage
@@ -0,0 +1,6 @@
+    1|      1|fn main() {
+    2|      1|    let num = 9;
+    3|      1|    while num >= 10 {
+    4|      0|    }
+    5|      1|}
+
diff --git a/tests/run-coverage/while.rs b/tests/run-coverage/while.rs
new file mode 100644
index 00000000000..781b90b3566
--- /dev/null
+++ b/tests/run-coverage/while.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let num = 9;
+    while num >= 10 {
+    }
+}
diff --git a/tests/run-coverage/while_early_ret.coverage b/tests/run-coverage/while_early_ret.coverage
new file mode 100644
index 00000000000..2ce94e0131d
--- /dev/null
+++ b/tests/run-coverage/while_early_ret.coverage
@@ -0,0 +1,43 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// failure-status: 1
+    3|       |
+    4|      1|fn main() -> Result<(),u8> {
+    5|      1|    let mut countdown = 10;
+    6|       |    while
+    7|      7|        countdown
+    8|      7|            >
+    9|      7|        0
+   10|       |    {
+   11|       |        if
+   12|      7|            countdown
+   13|      7|                <
+   14|      7|            5
+   15|       |        {
+   16|       |            return
+   17|       |                if
+   18|      1|                    countdown
+   19|      1|                        >
+   20|      1|                    8
+   21|       |                {
+   22|      0|                    Ok(())
+   23|       |                }
+   24|       |                else
+   25|       |                {
+   26|      1|                    Err(1)
+   27|       |                }
+   28|       |                ;
+   29|      6|        }
+   30|      6|        countdown
+   31|      6|            -=
+   32|      6|        1
+   33|       |        ;
+   34|       |    }
+   35|      0|    Ok(())
+   36|      1|}
+   37|       |
+   38|       |// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and
+   39|       |// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux
+   40|       |// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program
+   41|       |// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical
+   42|       |// to the coverage test for early returns, but this is a limitation that should be fixed.
+
diff --git a/tests/run-coverage/while_early_ret.rs b/tests/run-coverage/while_early_ret.rs
new file mode 100644
index 00000000000..1c83c8fc7a8
--- /dev/null
+++ b/tests/run-coverage/while_early_ret.rs
@@ -0,0 +1,42 @@
+#![allow(unused_assignments)]
+// failure-status: 1
+
+fn main() -> Result<(),u8> {
+    let mut countdown = 10;
+    while
+        countdown
+            >
+        0
+    {
+        if
+            countdown
+                <
+            5
+        {
+            return
+                if
+                    countdown
+                        >
+                    8
+                {
+                    Ok(())
+                }
+                else
+                {
+                    Err(1)
+                }
+                ;
+        }
+        countdown
+            -=
+        1
+        ;
+    }
+    Ok(())
+}
+
+// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and
+// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux
+// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program
+// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical
+// to the coverage test for early returns, but this is a limitation that should be fixed.
diff --git a/tests/run-coverage/yield.coverage b/tests/run-coverage/yield.coverage
new file mode 100644
index 00000000000..6e2f23ee77b
--- /dev/null
+++ b/tests/run-coverage/yield.coverage
@@ -0,0 +1,38 @@
+    1|       |#![feature(generators, generator_trait)]
+    2|       |#![allow(unused_assignments)]
+    3|       |
+    4|       |use std::ops::{Generator, GeneratorState};
+    5|       |use std::pin::Pin;
+    6|       |
+    7|      1|fn main() {
+    8|      1|    let mut generator = || {
+    9|      1|        yield 1;
+   10|      1|        return "foo"
+   11|      1|    };
+   12|       |
+   13|      1|    match Pin::new(&mut generator).resume(()) {
+   14|      1|        GeneratorState::Yielded(1) => {}
+   15|      0|        _ => panic!("unexpected value from resume"),
+   16|       |    }
+   17|      1|    match Pin::new(&mut generator).resume(()) {
+   18|      1|        GeneratorState::Complete("foo") => {}
+   19|      0|        _ => panic!("unexpected value from resume"),
+   20|       |    }
+   21|       |
+   22|      1|    let mut generator = || {
+   23|      1|        yield 1;
+   24|      1|        yield 2;
+   25|      0|        yield 3;
+   26|      0|        return "foo"
+   27|      0|    };
+   28|       |
+   29|      1|    match Pin::new(&mut generator).resume(()) {
+   30|      1|        GeneratorState::Yielded(1) => {}
+   31|      0|        _ => panic!("unexpected value from resume"),
+   32|       |    }
+   33|      1|    match Pin::new(&mut generator).resume(()) {
+   34|      1|        GeneratorState::Yielded(2) => {}
+   35|      0|        _ => panic!("unexpected value from resume"),
+   36|       |    }
+   37|      1|}
+
diff --git a/tests/run-coverage/yield.rs b/tests/run-coverage/yield.rs
new file mode 100644
index 00000000000..ff7616656ff
--- /dev/null
+++ b/tests/run-coverage/yield.rs
@@ -0,0 +1,37 @@
+#![feature(generators, generator_trait)]
+#![allow(unused_assignments)]
+
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
+fn main() {
+    let mut generator = || {
+        yield 1;
+        return "foo"
+    };
+
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Yielded(1) => {}
+        _ => panic!("unexpected value from resume"),
+    }
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Complete("foo") => {}
+        _ => panic!("unexpected value from resume"),
+    }
+
+    let mut generator = || {
+        yield 1;
+        yield 2;
+        yield 3;
+        return "foo"
+    };
+
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Yielded(1) => {}
+        _ => panic!("unexpected value from resume"),
+    }
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Yielded(2) => {}
+        _ => panic!("unexpected value from resume"),
+    }
+}