about summary refs log tree commit diff
path: root/src/test/run-make
diff options
context:
space:
mode:
authorTomasz Miąsko <tomasz.miasko@gmail.com>2022-07-25 00:00:00 +0000
committerTomasz Miąsko <tomasz.miasko@gmail.com>2022-07-28 14:33:29 +0200
commit866d5c621c9b87f82a5aa53c3dfc1e477181f33b (patch)
tree6b2c45b45140bbc8ee3925ec1ddc52e88b23c86a /src/test/run-make
parent48316dfea1914d25189fa441e7310449ed76a446 (diff)
downloadrust-866d5c621c9b87f82a5aa53c3dfc1e477181f33b.tar.gz
rust-866d5c621c9b87f82a5aa53c3dfc1e477181f33b.zip
Move coverage tests from run-make-fulldeps to run-make
Diffstat (limited to 'src/test/run-make')
-rw-r--r--src/test/run-make/coverage-llvmir/Makefile64
-rw-r--r--src/test/run-make/coverage-llvmir/filecheck.testprog.txt50
-rw-r--r--src/test/run-make/coverage-llvmir/testprog.rs38
-rw-r--r--src/test/run-make/coverage-reports/Makefile180
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.abort.txt69
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.assert.txt34
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.async.txt139
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.async2.txt116
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.closure.txt222
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.closure_macro.txt42
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt83
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.conditions.txt94
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.continue.txt70
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.dead_code.txt39
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.doctest.txt121
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.drop_trait.txt34
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.generator.txt32
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.generics.txt71
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.if.txt30
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.if_else.txt41
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.inline-dead.txt28
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.inline.txt54
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.inner_items.txt60
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.issue-83601.txt22
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.issue-84561.txt195
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.issue-85461.txt36
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.issue-93054.txt29
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt64
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt14
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.loops_branches.txt68
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt50
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.nested_loops.txt26
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt87
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.overflow.txt64
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt32
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.partial_eq.txt53
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.simple_loop.txt37
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.simple_match.txt45
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt6
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.try_error_result.txt125
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.unused.txt62
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.unused_mod.txt4
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.uses_crate.txt148
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt139
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.while.txt6
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt43
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.yield.txt38
-rwxr-xr-xsrc/test/run-make/coverage-reports/normalize_paths.py12
-rw-r--r--src/test/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt10
-rw-r--r--src/test/run-make/coverage/abort.rs66
-rw-r--r--src/test/run-make/coverage/assert.rs32
-rw-r--r--src/test/run-make/coverage/async.rs128
-rw-r--r--src/test/run-make/coverage/async2.rs69
-rw-r--r--src/test/run-make/coverage/closure.rs215
-rw-r--r--src/test/run-make/coverage/closure_macro.rs40
-rw-r--r--src/test/run-make/coverage/closure_macro_async.rs81
-rw-r--r--src/test/run-make/coverage/compiletest-ignore-dir3
-rw-r--r--src/test/run-make/coverage/conditions.rs87
-rw-r--r--src/test/run-make/coverage/continue.rs69
-rw-r--r--src/test/run-make/coverage/coverage_tools.mk6
-rw-r--r--src/test/run-make/coverage/dead_code.rs37
-rw-r--r--src/test/run-make/coverage/doctest.rs99
-rw-r--r--src/test/run-make/coverage/drop_trait.rs33
-rw-r--r--src/test/run-make/coverage/generator.rs30
-rw-r--r--src/test/run-make/coverage/generics.rs48
-rw-r--r--src/test/run-make/coverage/if.rs28
-rw-r--r--src/test/run-make/coverage/if_else.rs40
-rw-r--r--src/test/run-make/coverage/inline-dead.rs27
-rw-r--r--src/test/run-make/coverage/inline.rs51
-rw-r--r--src/test/run-make/coverage/inner_items.rs57
-rw-r--r--src/test/run-make/coverage/issue-83601.rs14
-rw-r--r--src/test/run-make/coverage/issue-84561.rs182
-rw-r--r--src/test/run-make/coverage/issue-85461.rs10
-rw-r--r--src/test/run-make/coverage/issue-93054.rs28
-rw-r--r--src/test/run-make/coverage/lazy_boolean.rs61
-rw-r--r--src/test/run-make/coverage/lib/doctest_crate.rs9
-rw-r--r--src/test/run-make/coverage/lib/inline_always_with_dead_code.rs22
-rw-r--r--src/test/run-make/coverage/lib/unused_mod_helper.rs3
-rw-r--r--src/test/run-make/coverage/lib/used_crate.rs100
-rw-r--r--src/test/run-make/coverage/lib/used_inline_crate.rs90
-rw-r--r--src/test/run-make/coverage/loop_break_value.rs13
-rw-r--r--src/test/run-make/coverage/loops_branches.rs61
-rw-r--r--src/test/run-make/coverage/match_or_pattern.rs45
-rw-r--r--src/test/run-make/coverage/nested_loops.rs25
-rw-r--r--src/test/run-make/coverage/no_cov_crate.rs86
-rw-r--r--src/test/run-make/coverage/overflow.rs63
-rw-r--r--src/test/run-make/coverage/panic_unwind.rs31
-rw-r--r--src/test/run-make/coverage/partial_eq.rs46
-rw-r--r--src/test/run-make/coverage/simple_loop.rs35
-rw-r--r--src/test/run-make/coverage/simple_match.rs43
-rw-r--r--src/test/run-make/coverage/tight_inf_loop.rs5
-rw-r--r--src/test/run-make/coverage/try_error_result.rs118
-rw-r--r--src/test/run-make/coverage/unused.rs39
-rw-r--r--src/test/run-make/coverage/unused_mod.rs6
-rw-r--r--src/test/run-make/coverage/uses_crate.rs12
-rw-r--r--src/test/run-make/coverage/uses_inline_crate.rs17
-rw-r--r--src/test/run-make/coverage/while.rs5
-rw-r--r--src/test/run-make/coverage/while_early_ret.rs42
-rw-r--r--src/test/run-make/coverage/yield.rs37
99 files changed, 5620 insertions, 0 deletions
diff --git a/src/test/run-make/coverage-llvmir/Makefile b/src/test/run-make/coverage-llvmir/Makefile
new file mode 100644
index 00000000000..fbe0a5cb1bb
--- /dev/null
+++ b/src/test/run-make/coverage-llvmir/Makefile
@@ -0,0 +1,64 @@
+# needs-profiler-support
+
+# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
+# corresponding with LLVM versions 12 and 13, respectively.
+# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
+# version during testing, with an additional directive at the top of this file
+# that sets, for example: `min-llvm-version: 12.0`
+
+-include ../coverage/coverage_tools.mk
+
+BASEDIR=../coverage-llvmir
+
+ifeq ($(UNAME),Darwin)
+	INSTR_PROF_DATA_SUFFIX=,regular,live_support
+	DATA_SECTION_PREFIX=__DATA,
+	LLVM_COV_SECTION_PREFIX=__LLVM_COV,
+	COMDAT_IF_SUPPORTED=
+else
+	INSTR_PROF_DATA_SUFFIX=
+	DATA_SECTION_PREFIX=
+	LLVM_COV_SECTION_PREFIX=
+	COMDAT_IF_SUPPORTED=, comdat
+endif
+
+DEFINE_INTERNAL=define internal
+
+ifdef IS_WINDOWS
+	LLVM_FILECHECK_OPTIONS=\
+		-check-prefixes=CHECK,WINDOWS \
+		-DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
+		-DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
+		-DINSTR_PROF_DATA='.lprfd$$M' \
+		-DINSTR_PROF_NAME='.lprfn$$M' \
+		-DINSTR_PROF_CNTS='.lprfc$$M' \
+		-DINSTR_PROF_VALS='.lprfv$$M' \
+		-DINSTR_PROF_VNODES='.lprfnd$$M' \
+		-DINSTR_PROF_COVMAP='.lcovmap$$M' \
+		-DINSTR_PROF_COVFUN='.lcovfun$$M' \
+		-DINSTR_PROF_ORDERFILE='.lorderfile$$M'
+else
+	LLVM_FILECHECK_OPTIONS=\
+		-check-prefixes=CHECK \
+		-DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
+		-DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
+		-DINSTR_PROF_DATA='$(DATA_SECTION_PREFIX)__llvm_prf_data$(INSTR_PROF_DATA_SUFFIX)' \
+		-DINSTR_PROF_NAME='$(DATA_SECTION_PREFIX)__llvm_prf_names' \
+		-DINSTR_PROF_CNTS='$(DATA_SECTION_PREFIX)__llvm_prf_cnts' \
+		-DINSTR_PROF_VALS='$(DATA_SECTION_PREFIX)__llvm_prf_vals' \
+		-DINSTR_PROF_VNODES='$(DATA_SECTION_PREFIX)__llvm_prf_vnds' \
+		-DINSTR_PROF_COVMAP='$(LLVM_COV_SECTION_PREFIX)__llvm_covmap' \
+		-DINSTR_PROF_COVFUN='$(LLVM_COV_SECTION_PREFIX)__llvm_covfun' \
+		-DINSTR_PROF_ORDERFILE='$(DATA_SECTION_PREFIX)__llvm_orderfile'
+endif
+
+all: test_llvm_ir
+
+test_llvm_ir:
+	# Compile the test program with non-experimental coverage instrumentation, and generate LLVM IR
+	$(RUSTC) $(BASEDIR)/testprog.rs \
+			-Cinstrument-coverage \
+			--emit=llvm-ir
+
+	cat "$(TMPDIR)"/testprog.ll | \
+			"$(LLVM_FILECHECK)" $(BASEDIR)/filecheck.testprog.txt $(LLVM_FILECHECK_OPTIONS)
diff --git a/src/test/run-make/coverage-llvmir/filecheck.testprog.txt b/src/test/run-make/coverage-llvmir/filecheck.testprog.txt
new file mode 100644
index 00000000000..7a5f2192277
--- /dev/null
+++ b/src/test/run-make/coverage-llvmir/filecheck.testprog.txt
@@ -0,0 +1,50 @@
+# Check for metadata, variables, declarations, and function definitions injected
+# into LLVM IR when compiling with -Cinstrument-coverage.
+
+WINDOWS:      $__llvm_profile_runtime_user = comdat any
+
+CHECK:        @__covrec_{{[A-F0-9]+}}u = linkonce_odr hidden constant
+CHECK-SAME:   section "[[INSTR_PROF_COVFUN]]"[[COMDAT_IF_SUPPORTED]], align 8
+
+CHECK:        @__llvm_coverage_mapping = private constant
+CHECK-SAME:   section "[[INSTR_PROF_COVMAP]]", align 8
+
+WINDOWS:      @__llvm_profile_runtime = external global i32
+
+CHECK:        @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global
+CHECK-SAME:   section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8
+
+CHECK:        @__profd__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global
+CHECK-SAME:   @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called
+CHECK-SAME:   section "[[INSTR_PROF_DATA]]"{{.*}}, align 8
+
+CHECK:        @__profc__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global
+CHECK-SAME:   section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8
+
+CHECK:        @__profd__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global
+CHECK-SAME:   @__profc__R{{[a-zA-Z0-9_]+}}testprog4main
+CHECK-SAME:   section "[[INSTR_PROF_DATA]]"{{.*}}, align 8
+
+CHECK:        @__llvm_prf_nm = private constant
+CHECK-SAME:   section "[[INSTR_PROF_NAME]]", align 1
+
+CHECK:        @llvm.used = appending global
+CHECK-SAME:   @__llvm_coverage_mapping
+CHECK-SAME:   @__llvm_prf_nm
+CHECK-SAME:   section "llvm.metadata"
+
+CHECK:        [[DEFINE_INTERNAL]] { {{.*}} } @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called() unnamed_addr #{{[0-9]+}} {
+CHECK-NEXT:   start:
+CHECK-NOT:    [[DEFINE_INTERNAL]]
+CHECK:        %pgocount = load i64, {{i64\*|ptr}}
+CHECK-SAME:   @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
+
+CHECK:        declare void @llvm.instrprof.increment({{i8\*|ptr}}, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
+
+WINDOWS:      define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {
+WINDOWS-NEXT: %1 = load i32, {{i32\*|ptr}} @__llvm_profile_runtime
+WINDOWS-NEXT: ret i32 %1
+WINDOWS-NEXT: }
+
+CHECK:        attributes #[[LLVM_INSTRPROF_INCREMENT_ATTR]] = { nounwind }
+WINDOWS:      attributes #[[LLVM_PROFILE_RUNTIME_USER_ATTR]] = { noinline }
diff --git a/src/test/run-make/coverage-llvmir/testprog.rs b/src/test/run-make/coverage-llvmir/testprog.rs
new file mode 100644
index 00000000000..358c25677ae
--- /dev/null
+++ b/src/test/run-make/coverage-llvmir/testprog.rs
@@ -0,0 +1,38 @@
+pub fn will_be_called() -> &'static str {
+    let val = "called";
+    println!("{}", val);
+    val
+}
+
+pub fn will_not_be_called() -> bool {
+    println!("should not have been called");
+    false
+}
+
+pub fn print<T>(left: &str, value: T, right: &str)
+where
+    T: std::fmt::Display,
+{
+    println!("{}{}{}", left, value, right);
+}
+
+pub fn wrap_with<F, T>(inner: T, should_wrap: bool, wrapper: F)
+where
+    F: FnOnce(&T)
+{
+    if should_wrap {
+        wrapper(&inner)
+    }
+}
+
+fn main() {
+    let less = 1;
+    let more = 100;
+
+    if less < more {
+        wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** "));
+        wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** "));
+    } else {
+        wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, ""));
+    }
+}
diff --git a/src/test/run-make/coverage-reports/Makefile b/src/test/run-make/coverage-reports/Makefile
new file mode 100644
index 00000000000..78723e78e77
--- /dev/null
+++ b/src/test/run-make/coverage-reports/Makefile
@@ -0,0 +1,180 @@
+# needs-profiler-support
+# ignore-windows-gnu
+
+# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
+# corresponding with LLVM versions 12 and 13, respectively.
+# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
+# version during testing, with an additional directive at the top of this file
+# that sets, for example: `min-llvm-version: 12.0`
+
+# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
+# properly. Since we only have GCC on the CI ignore the test for now.
+
+-include ../coverage/coverage_tools.mk
+
+BASEDIR=../coverage-reports
+SOURCEDIR=../coverage
+
+# The `llvm-cov show` flag `--debug`, used to generate the `counters` output files, is only
+# enabled if LLVM assertions are enabled. This requires Rust config `llvm/optimize` and not
+# `llvm/release_debuginfo`. Note that some CI builds disable debug assertions (by setting
+# `NO_LLVM_ASSERTIONS=1`), so the tests must still pass even if the `--debug` flag is
+# not supported. (Note that `counters` files are only produced in the `$(TMPDIR)`
+# directory, for inspection and debugging support. They are *not* copied to `expected_*`
+# files when `--bless`ed.)
+LLVM_COV_DEBUG := $(shell \
+		"$(LLVM_BIN_DIR)"/llvm-cov show --debug 2>&1 | \
+		grep -q "Unknown command line argument '--debug'"; \
+		echo $$?)
+ifeq ($(LLVM_COV_DEBUG), 1)
+DEBUG_FLAG=--debug
+endif
+
+# FIXME(richkadel): I'm adding `--ignore-filename-regex=` line(s) for specific test(s) that produce
+# `llvm-cov` results for multiple files (for example `uses_crate.rs` and `used_crate/mod.rs`) as a
+# workaround for two problems causing tests to fail on Windows:
+#
+# 1. When multiple files appear in the `llvm-cov show` results, each file's coverage results can
+#    appear in different a different order. Whether this is random or, somehow, platform-specific,
+#    the Windows output flips the order of the files, compared to Linux. In the `uses_crate.rs`
+#    test, the only test-unique (interesting) results we care about are the results for only one
+#    of the two files, `mod/uses_crate.rs`, so the workaround is to ignore all but this one file.
+#    In the future, we may want a more sophisticated solution that splits apart `llvm-cov show`
+#    results into separate results files for each result (taking care not to create new file
+#    paths that might be too long for Windows MAX_PATH limits when creating these new sub-results,
+#    as well).
+# 2. When multiple files appear in the `llvm-cov show` results, the results for each file are
+#    prefixed with their filename, including platform-specific path separators (`\` for Windows,
+#    and `/` everywhere else). This could be filtered or normalized of course, but by ignoring
+#    coverage results for all but one of the file, the filenames are no longer included anyway.
+#    If this changes (if/when we decide to support `llvm-cov show` results for multiple files),
+#    the file path separator differences may need to be addressed.
+#
+# Since this is only a workaround, I decided to implement the override by adding an option for
+# each file to be ignored, using a `--ignore-filename-regex=` entry for each one, rather than
+# implement some more sophisticated solution with a new custom test directive in the test file
+# itself (similar to `expect-exit-status`) because that would add a lot of complexity and still
+# be a workaround, with the same result, with no benefit.
+#
+# Yes these `--ignore-filename-regex=` options are included in all invocations of `llvm-cov show`
+# for now, but it is effectively ignored for all tests that don't include this file anyway.
+#
+# (Note that it's also possible the `_counters.<test>.txt` and `<test>.json` files (if generated)
+# may order results from multiple files inconsistently, which might also have to be accomodated
+# if and when we allow `llvm-cov` to produce results for multiple files. Note, the path separators
+# appear to be normalized to `/` in those files, thankfully.)
+LLVM_COV_IGNORE_FILES=\
+	--ignore-filename-regex='(uses_crate.rs|uses_inline_crate.rs|unused_mod.rs)'
+
+all: $(patsubst $(SOURCEDIR)/lib/%.rs,%,$(wildcard $(SOURCEDIR)/lib/*.rs)) $(patsubst $(SOURCEDIR)/%.rs,%,$(wildcard $(SOURCEDIR)/*.rs))
+
+# Ensure there are no `expected` results for tests that may have been removed or renamed
+.PHONY: clear_expected_if_blessed
+clear_expected_if_blessed:
+ifdef RUSTC_BLESS_TEST
+	rm -f expected_*
+endif
+
+-include clear_expected_if_blessed
+
+%: $(SOURCEDIR)/lib/%.rs
+	# Compile the test library with coverage instrumentation
+	$(RUSTC) $(SOURCEDIR)/lib/$@.rs \
+			$$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/lib/$@.rs ) \
+			--crate-type rlib -Cinstrument-coverage
+
+%: $(SOURCEDIR)/%.rs
+	# Compile the test program with coverage instrumentation
+	$(RUSTC) $(SOURCEDIR)/$@.rs \
+			$$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
+			-L "$(TMPDIR)" -Cinstrument-coverage
+
+	# Run it in order to generate some profiling data,
+	# with `LLVM_PROFILE_FILE=<profdata_file>` environment variable set to
+	# output the coverage stats for this run.
+	LLVM_PROFILE_FILE="$(TMPDIR)"/$@.profraw \
+			$(call RUN,$@) || \
+			( \
+				status=$$?; \
+				grep -q "^\/\/ expect-exit-status-$$status" $(SOURCEDIR)/$@.rs || \
+				( >&2 echo "program exited with an unexpected exit status: $$status"; \
+					false \
+				) \
+			)
+
+	# Run it through rustdoc as well to cover doctests.
+	# `%p` is the pid, and `%m` the binary signature. We suspect that the pid alone
+	# might result in overwritten files and failed tests, as rustdoc spawns each
+	# doctest as its own process, so make sure the filename is as unique as possible.
+	LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p-%m.profraw \
+			$(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \
+			$$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
+			-L "$(TMPDIR)" -Cinstrument-coverage \
+			-Z unstable-options --persist-doctests=$(TMPDIR)/rustdoc-$@
+
+	# Postprocess the profiling data so it can be used by the llvm-cov tool
+	"$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \
+			"$(TMPDIR)"/$@*.profraw \
+			-o "$(TMPDIR)"/$@.profdata
+
+	# Generate a coverage report using `llvm-cov show`.
+	"$(LLVM_BIN_DIR)"/llvm-cov show \
+			$(DEBUG_FLAG) \
+			$(LLVM_COV_IGNORE_FILES) \
+			--compilation-dir=. \
+			--Xdemangler="$(RUST_DEMANGLER)" \
+			--show-line-counts-or-regions \
+			--instr-profile="$(TMPDIR)"/$@.profdata \
+			$(call BIN,"$(TMPDIR)"/$@) \
+			$$( \
+				for file in $(TMPDIR)/rustdoc-$@/*/rust_out; do \
+				[ -x "$$file" ] && printf "%s %s " -object $$file; \
+				done \
+			) \
+		2> "$(TMPDIR)"/show_coverage_stderr.$@.txt \
+		| "$(PYTHON)" $(BASEDIR)/normalize_paths.py \
+		> "$(TMPDIR)"/actual_show_coverage.$@.txt || \
+	( status=$$? ; \
+		>&2 cat "$(TMPDIR)"/show_coverage_stderr.$@.txt ; \
+		exit $$status \
+	)
+
+ifdef DEBUG_FLAG
+	# The first line (beginning with "Args:" contains hard-coded, build-specific
+	# file paths. Strip that line and keep the remaining lines with counter debug
+	# data.
+	tail -n +2 "$(TMPDIR)"/show_coverage_stderr.$@.txt \
+		> "$(TMPDIR)"/actual_show_coverage_counters.$@.txt
+endif
+
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/actual_show_coverage.$@.txt \
+			expected_show_coverage.$@.txt
+else
+	# Compare the show coverage output (`--bless` refreshes `typical` files).
+	#
+	# FIXME(richkadel): None of the Rust test source samples have the
+	# `// ignore-llvm-cov-show-diffs` anymore. This directive exists to work around a limitation
+	# with `llvm-cov show`. When reporting coverage for multiple instantiations of a generic function,
+	# with different type substitutions, `llvm-cov show` prints these in a non-deterministic order,
+	# breaking the `diff` comparision.
+	#
+	# A partial workaround is implemented below, with `diff --ignore-matching-lines=RE`
+	# to ignore each line prefixing each generic instantiation coverage code region.
+	#
+	# This workaround only works if the coverage counts are identical across all reported
+	# instantiations. If there is no way to ensure this, you may need to apply the
+	# `// ignore-llvm-cov-show-diffs` directive, and check for differences using the
+	# `.json` files to validate that results have not changed. (Until then, the JSON
+	# files are redundant, so there is no need to generate `expected_*.json` files or
+	# compare actual JSON results.)
+
+	$(DIFF) --ignore-matching-lines='^  | .*::<.*>.*:$$' --ignore-matching-lines='^  | <.*>::.*:$$' \
+		expected_show_coverage.$@.txt "$(TMPDIR)"/actual_show_coverage.$@.txt || \
+		( grep -q '^\/\/ ignore-llvm-cov-show-diffs' $(SOURCEDIR)/$@.rs && \
+			>&2 echo 'diff failed, but suppressed with `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs' \
+		) || \
+		( >&2 echo 'diff failed, and not suppressed without `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs'; \
+			false \
+		)
+endif
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.abort.txt b/src/test/run-make/coverage-reports/expected_show_coverage.abort.txt
new file mode 100644
index 00000000000..00f46f42a07
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.abort.txt
@@ -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 `TerminatorKind::Abort`.
+   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/src/test/run-make/coverage-reports/expected_show_coverage.assert.txt b/src/test/run-make/coverage-reports/expected_show_coverage.assert.txt
new file mode 100644
index 00000000000..405688806ea
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.assert.txt
@@ -0,0 +1,34 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-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/src/test/run-make/coverage-reports/expected_show_coverage.async.txt b/src/test/run-make/coverage-reports/expected_show_coverage.async.txt
new file mode 100644
index 00000000000..2f69adbd81c
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.async.txt
@@ -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 funciton 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/src/test/run-make/coverage-reports/expected_show_coverage.async2.txt b/src/test/run-make/coverage-reports/expected_show_coverage.async2.txt
new file mode 100644
index 00000000000..dc06a485a8f
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.async2.txt
@@ -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::<core::future::from_generator::GenFuture<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::<core::future::from_generator::GenFuture<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/src/test/run-make/coverage-reports/expected_show_coverage.closure.txt b/src/test/run-make/coverage-reports/expected_show_coverage.closure.txt
new file mode 100644
index 00000000000..09ad276aa45
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.closure.txt
@@ -0,0 +1,222 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs
+    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|    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|      1|    =
+   33|      1|        ||
+   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|       |    };
+   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|       |    };
+   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|       |    };
+  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|       |    };
+  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|       |            )
+  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|       |        }
+  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|       |            )
+  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|       |        }
+  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/src/test/run-make/coverage-reports/expected_show_coverage.closure_macro.txt b/src/test/run-make/coverage-reports/expected_show_coverage.closure_macro.txt
new file mode 100644
index 00000000000..87f7014760e
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.closure_macro.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt b/src/test/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt
new file mode 100644
index 00000000000..2b5418132c3
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.conditions.txt b/src/test/run-make/coverage-reports/expected_show_coverage.conditions.txt
new file mode 100644
index 00000000000..2d8a98a5d0c
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.conditions.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.continue.txt b/src/test/run-make/coverage-reports/expected_show_coverage.continue.txt
new file mode 100644
index 00000000000..1c64ead9f26
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.continue.txt
@@ -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|       |    let _ = x;
+   69|      1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.dead_code.txt b/src/test/run-make/coverage-reports/expected_show_coverage.dead_code.txt
new file mode 100644
index 00000000000..09ff14c6f27
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.dead_code.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.doctest.txt b/src/test/run-make/coverage-reports/expected_show_coverage.doctest.txt
new file mode 100644
index 00000000000..7ae0e978808
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.doctest.txt
@@ -0,0 +1,121 @@
+../coverage/doctest.rs:
+    1|       |//! This test ensures that code from doctests is properly re-mapped.
+    2|       |//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
+    3|       |//!
+    4|       |//! Just some random code:
+    5|      1|//! ```
+    6|      1|//! if true {
+    7|       |//!     // this is executed!
+    8|      1|//!     assert_eq!(1, 1);
+    9|       |//! } else {
+   10|       |//!     // this is not!
+   11|      0|//!     assert_eq!(1, 2);
+   12|       |//! }
+   13|      1|//! ```
+   14|       |//!
+   15|       |//! doctest testing external code:
+   16|       |//! ```
+   17|      1|//! extern crate doctest_crate;
+   18|      1|//! doctest_crate::fn_run_in_doctests(1);
+   19|      1|//! ```
+   20|       |//!
+   21|       |//! doctest returning a result:
+   22|      1|//! ```
+   23|      2|//! #[derive(Debug, PartialEq)]
+                       ^1
+  ------------------
+  | Unexecuted instantiation: <rust_out::main::_doctest_main____coverage_doctest_rs_22_0::SomeError as core::cmp::PartialEq>::ne
+  ------------------
+  | <rust_out::main::_doctest_main____coverage_doctest_rs_22_0::SomeError as core::cmp::PartialEq>::eq:
+  |   23|      2|//! #[derive(Debug, PartialEq)]
+  ------------------
+   24|      1|//! struct SomeError {
+   25|      1|//!     msg: String,
+   26|      1|//! }
+   27|      1|//! let mut res = Err(SomeError { msg: String::from("a message") });
+   28|      1|//! if res.is_ok() {
+   29|      0|//!     res?;
+   30|       |//! } else {
+   31|      1|//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+   32|      1|//!         println!("{:?}", res);
+   33|      1|//!     }
+                   ^0
+   34|      1|//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+   35|      1|//!         res = Ok(1);
+   36|      1|//!     }
+                   ^0
+   37|      1|//!     res = Ok(0);
+   38|       |//! }
+   39|       |//! // need to be explicit because rustdoc cant infer the return type
+   40|      1|//! Ok::<(), SomeError>(())
+   41|      1|//! ```
+   42|       |//!
+   43|       |//! doctest with custom main:
+   44|       |//! ```
+   45|      1|//! fn some_func() {
+   46|      1|//!     println!("called some_func()");
+   47|      1|//! }
+   48|       |//!
+   49|      0|//! #[derive(Debug)]
+   50|       |//! struct SomeError;
+   51|       |//!
+   52|       |//! extern crate doctest_crate;
+   53|       |//!
+   54|      1|//! fn doctest_main() -> Result<(), SomeError> {
+   55|      1|//!     some_func();
+   56|      1|//!     doctest_crate::fn_run_in_doctests(2);
+   57|      1|//!     Ok(())
+   58|      1|//! }
+   59|       |//!
+   60|       |//! // this `main` is not shown as covered, as it clashes with all the other
+   61|       |//! // `main` functions that were automatically generated for doctests
+   62|       |//! fn main() -> Result<(), SomeError> {
+   63|       |//!     doctest_main()
+   64|       |//! }
+   65|       |//! ```
+   66|       |
+   67|       |/// doctest attached to fn testing external code:
+   68|       |/// ```
+   69|      1|/// extern crate doctest_crate;
+   70|      1|/// doctest_crate::fn_run_in_doctests(3);
+   71|      1|/// ```
+   72|       |///
+   73|      1|fn main() {
+   74|      1|    if true {
+   75|      1|        assert_eq!(1, 1);
+   76|       |    } else {
+   77|      0|        assert_eq!(1, 2);
+   78|       |    }
+   79|      1|}
+   80|       |
+   81|       |// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
+   82|       |// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
+   83|       |// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
+   84|       |//
+   85|       |// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
+   86|       |// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
+   87|       |// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
+   88|       |// one character past, the `if` block's closing brace. In both cases, these are most likely off
+   89|       |// by the number of characters stripped from the beginning of each doc comment line: indent
+   90|       |// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
+   91|       |// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
+   92|       |// more pronounced, and show up in more places, with background color used to show some distinct
+   93|       |// code regions with different coverage counts.
+   94|       |//
+   95|       |// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
+   96|       |// character stripped from the beginning of doc comment lines with a space. This will give coverage
+   97|       |// results the correct column offsets, and I think it should compile correctly, but I don't know
+   98|       |// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
+   99|       |// if the indentation changed. I don't know if there is a more viable solution.
+
+../coverage/lib/doctest_crate.rs:
+    1|       |/// A function run only from within doctests
+    2|      3|pub fn fn_run_in_doctests(conditional: usize) {
+    3|      3|    match conditional {
+    4|      1|        1 => assert_eq!(1, 1), // this is run,
+    5|      1|        2 => assert_eq!(1, 1), // this,
+    6|      1|        3 => assert_eq!(1, 1), // and this too
+    7|      0|        _ => assert_eq!(1, 2), // however this is not
+    8|       |    }
+    9|      3|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.drop_trait.txt b/src/test/run-make/coverage-reports/expected_show_coverage.drop_trait.txt
new file mode 100644
index 00000000000..fe6a9e93cbf
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.drop_trait.txt
@@ -0,0 +1,34 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-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/src/test/run-make/coverage-reports/expected_show_coverage.generator.txt b/src/test/run-make/coverage-reports/expected_show_coverage.generator.txt
new file mode 100644
index 00000000000..d70e12e4128
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.generator.txt
@@ -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|       |    };
+   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/src/test/run-make/coverage-reports/expected_show_coverage.generics.txt b/src/test/run-make/coverage-reports/expected_show_coverage.generics.txt
new file mode 100644
index 00000000000..48983ba4358
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.generics.txt
@@ -0,0 +1,71 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-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<i32>>::set_strength:
+  |   10|      1|    fn set_strength(&mut self, new_strength: T) {
+  |   11|      1|        self.strength = new_strength;
+  |   12|      1|    }
+  ------------------
+  | <generics::Firework<f64>>::set_strength:
+  |   10|      2|    fn set_strength(&mut self, new_strength: T) {
+  |   11|      2|        self.strength = new_strength;
+  |   12|      2|    }
+  ------------------
+   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/src/test/run-make/coverage-reports/expected_show_coverage.if.txt b/src/test/run-make/coverage-reports/expected_show_coverage.if.txt
new file mode 100644
index 00000000000..0c9eff227ed
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.if.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.if_else.txt b/src/test/run-make/coverage-reports/expected_show_coverage.if_else.txt
new file mode 100644
index 00000000000..4285d318686
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.if_else.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.inline-dead.txt b/src/test/run-make/coverage-reports/expected_show_coverage.inline-dead.txt
new file mode 100644
index 00000000000..effdef80e8e
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.inline-dead.txt
@@ -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|       |            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/src/test/run-make/coverage-reports/expected_show_coverage.inline.txt b/src/test/run-make/coverage-reports/expected_show_coverage.inline.txt
new file mode 100644
index 00000000000..6f5d1544fa0
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.inline.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.inner_items.txt b/src/test/run-make/coverage-reports/expected_show_coverage.inner_items.txt
new file mode 100644
index 00000000000..883254a09ba
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.inner_items.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.issue-83601.txt b/src/test/run-make/coverage-reports/expected_show_coverage.issue-83601.txt
new file mode 100644
index 00000000000..de32c88b725
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.issue-83601.txt
@@ -0,0 +1,22 @@
+    1|       |// Shows that rust-lang/rust/83601 is resolved
+    2|       |
+    3|      3|#[derive(Debug, PartialEq, Eq)]
+                              ^2
+  ------------------
+  | <issue_83601::Foo as core::cmp::PartialEq>::eq:
+  |    3|      2|#[derive(Debug, PartialEq, Eq)]
+  ------------------
+  | Unexecuted instantiation: <issue_83601::Foo as core::cmp::PartialEq>::ne
+  ------------------
+    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/src/test/run-make/coverage-reports/expected_show_coverage.issue-84561.txt b/src/test/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
new file mode 100644
index 00000000000..f24f7c69404
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
@@ -0,0 +1,195 @@
+    1|       |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
+    2|       |
+    3|       |// expect-exit-status-101
+    4|     21|#[derive(PartialEq, Eq)]
+  ------------------
+  | <issue_84561::Foo as core::cmp::PartialEq>::eq:
+  |    4|     21|#[derive(PartialEq, Eq)]
+  ------------------
+  | Unexecuted instantiation: <issue_84561::Foo as core::cmp::PartialEq>::ne
+  ------------------
+    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/src/test/run-make/coverage-reports/expected_show_coverage.issue-85461.txt b/src/test/run-make/coverage-reports/expected_show_coverage.issue-85461.txt
new file mode 100644
index 00000000000..1aa4a22c33e
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.issue-85461.txt
@@ -0,0 +1,36 @@
+../coverage/issue-85461.rs:
+    1|       |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+    2|       |
+    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|}
+
+../coverage/lib/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|       |}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.issue-93054.txt b/src/test/run-make/coverage-reports/expected_show_coverage.issue-93054.txt
new file mode 100644
index 00000000000..a1655adedd4
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.issue-93054.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt b/src/test/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt
new file mode 100644
index 00000000000..bd349df2fbc
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt b/src/test/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt
new file mode 100644
index 00000000000..022fe4c5962
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.loops_branches.txt b/src/test/run-make/coverage-reports/expected_show_coverage.loops_branches.txt
new file mode 100644
index 00000000000..b7ad79a2484
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.loops_branches.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt b/src/test/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt
new file mode 100644
index 00000000000..a0fccb24f99
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.nested_loops.txt b/src/test/run-make/coverage-reports/expected_show_coverage.nested_loops.txt
new file mode 100644
index 00000000000..0dbd6bcf313
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.nested_loops.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt b/src/test/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt
new file mode 100644
index 00000000000..83a9204136f
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.overflow.txt b/src/test/run-make/coverage-reports/expected_show_coverage.overflow.txt
new file mode 100644
index 00000000000..25e822bffd1
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.overflow.txt
@@ -0,0 +1,64 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-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/src/test/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt b/src/test/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt
new file mode 100644
index 00000000000..114507dc9fd
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt
@@ -0,0 +1,32 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-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/src/test/run-make/coverage-reports/expected_show_coverage.partial_eq.txt b/src/test/run-make/coverage-reports/expected_show_coverage.partial_eq.txt
new file mode 100644
index 00000000000..fc266653349
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.partial_eq.txt
@@ -0,0 +1,53 @@
+    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
+  ------------------
+  | Unexecuted instantiation: <partial_eq::Version as core::cmp::PartialEq>::ne
+  ------------------
+  | Unexecuted instantiation: <partial_eq::Version as core::cmp::PartialEq>::eq
+  ------------------
+    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/src/test/run-make/coverage-reports/expected_show_coverage.simple_loop.txt b/src/test/run-make/coverage-reports/expected_show_coverage.simple_loop.txt
new file mode 100644
index 00000000000..feb83bad674
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.simple_loop.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.simple_match.txt b/src/test/run-make/coverage-reports/expected_show_coverage.simple_match.txt
new file mode 100644
index 00000000000..b9298213111
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.simple_match.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt b/src/test/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt
new file mode 100644
index 00000000000..2d4c57f451a
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt
@@ -0,0 +1,6 @@
+    1|      1|fn main() {
+    2|      1|    if false {
+    3|      0|        loop {}
+    4|      1|    }
+    5|      1|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.try_error_result.txt b/src/test/run-make/coverage-reports/expected_show_coverage.try_error_result.txt
new file mode 100644
index 00000000000..0ad0180b761
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.try_error_result.txt
@@ -0,0 +1,125 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-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/src/test/run-make/coverage-reports/expected_show_coverage.unused.txt b/src/test/run-make/coverage-reports/expected_show_coverage.unused.txt
new file mode 100644
index 00000000000..15fcf21c0ef
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.unused.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.unused_mod.txt b/src/test/run-make/coverage-reports/expected_show_coverage.unused_mod.txt
new file mode 100644
index 00000000000..82d6fccc271
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.unused_mod.txt
@@ -0,0 +1,4 @@
+    1|      0|pub fn never_called_function() {
+    2|      0|    println!("I am never called");
+    3|      0|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.uses_crate.txt b/src/test/run-make/coverage-reports/expected_show_coverage.uses_crate.txt
new file mode 100644
index 00000000000..65eb1008dd8
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.uses_crate.txt
@@ -0,0 +1,148 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+    3|       |use std::fmt::Debug;
+    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|}
+  ------------------
+  | 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|}
+  ------------------
+  | 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|}
+  ------------------
+  | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+  ------------------
+   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::<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|}
+  ------------------
+  | 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|}
+  ------------------
+   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::<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|}
+  ------------------
+  | 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|}
+  ------------------
+   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.
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt b/src/test/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt
new file mode 100644
index 00000000000..dab31cbf4ac
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt
@@ -0,0 +1,139 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    3|       |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+    4|       |
+    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|}
+  ------------------
+  | 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|}
+  ------------------
+  | Unexecuted instantiation: used_inline_crate::used_only_from_bin_crate_generic_function::<_>
+  ------------------
+   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::<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|}
+  ------------------
+  | 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|}
+  ------------------
+   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::<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|}
+  ------------------
+  | 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|}
+  ------------------
+   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|}
+
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.while.txt b/src/test/run-make/coverage-reports/expected_show_coverage.while.txt
new file mode 100644
index 00000000000..efa7d083f0c
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.while.txt
@@ -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/src/test/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt b/src/test/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt
new file mode 100644
index 00000000000..d19afc0de61
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt
@@ -0,0 +1,43 @@
+    1|       |#![allow(unused_assignments)]
+    2|       |// expect-exit-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/src/test/run-make/coverage-reports/expected_show_coverage.yield.txt b/src/test/run-make/coverage-reports/expected_show_coverage.yield.txt
new file mode 100644
index 00000000000..60a8d943f1f
--- /dev/null
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.yield.txt
@@ -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|       |    };
+   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|       |    };
+   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/src/test/run-make/coverage-reports/normalize_paths.py b/src/test/run-make/coverage-reports/normalize_paths.py
new file mode 100755
index 00000000000..e5777ad2512
--- /dev/null
+++ b/src/test/run-make/coverage-reports/normalize_paths.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+import sys
+
+# Normalize file paths in output
+for line in sys.stdin:
+    if line.startswith("..") and line.rstrip().endswith(".rs:"):
+        print(line.replace("\\", "/"), end='')
+    else:
+        print(line, end='')
diff --git a/src/test/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt b/src/test/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt
new file mode 100644
index 00000000000..6a1403b8a00
--- /dev/null
+++ b/src/test/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt
@@ -0,0 +1,10 @@
+IMPORTANT: The Rust test programs in this directory generate various output
+files in the `../coverage*` directories (`expected` and `actual` files).
+
+Microsoft Windows has a relatively short limit on file paths (not individual
+path components, but the entire path). The files generated by these
+`../coverage*` tests typically have file paths that include the program
+source file name plus function and type names (depending on the program).
+
+Keep the test file names short, and keep function names and other symbols
+short as well, to avoid hitting the Windows limits.
diff --git a/src/test/run-make/coverage/abort.rs b/src/test/run-make/coverage/abort.rs
new file mode 100644
index 00000000000..3dac43df8f3
--- /dev/null
+++ b/src/test/run-make/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 `TerminatorKind::Abort`.
+//   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/src/test/run-make/coverage/assert.rs b/src/test/run-make/coverage/assert.rs
new file mode 100644
index 00000000000..c85f2748eb9
--- /dev/null
+++ b/src/test/run-make/coverage/assert.rs
@@ -0,0 +1,32 @@
+#![allow(unused_assignments)]
+// expect-exit-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/src/test/run-make/coverage/async.rs b/src/test/run-make/coverage/async.rs
new file mode 100644
index 00000000000..a6e38774706
--- /dev/null
+++ b/src/test/run-make/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 funciton 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/src/test/run-make/coverage/async2.rs b/src/test/run-make/coverage/async2.rs
new file mode 100644
index 00000000000..959d48ce9db
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/closure.rs b/src/test/run-make/coverage/closure.rs
new file mode 100644
index 00000000000..32ec0bcdf8c
--- /dev/null
+++ b/src/test/run-make/coverage/closure.rs
@@ -0,0 +1,215 @@
+#![allow(unused_assignments, unused_variables)]
+// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs
+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 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/src/test/run-make/coverage/closure_macro.rs b/src/test/run-make/coverage/closure_macro.rs
new file mode 100644
index 00000000000..5e3b00d1ef5
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/closure_macro_async.rs b/src/test/run-make/coverage/closure_macro_async.rs
new file mode 100644
index 00000000000..e3e89e9c8b3
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/compiletest-ignore-dir b/src/test/run-make/coverage/compiletest-ignore-dir
new file mode 100644
index 00000000000..b533b272d38
--- /dev/null
+++ b/src/test/run-make/coverage/compiletest-ignore-dir
@@ -0,0 +1,3 @@
+# Directory "coverage" supports the tests at prefix ../coverage-*
+
+# Use ./x.py [options] test src/test/run-make/coverage to run all related tests.
diff --git a/src/test/run-make/coverage/conditions.rs b/src/test/run-make/coverage/conditions.rs
new file mode 100644
index 00000000000..057599d1b47
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/continue.rs b/src/test/run-make/coverage/continue.rs
new file mode 100644
index 00000000000..624aa98341b
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/coverage_tools.mk b/src/test/run-make/coverage/coverage_tools.mk
new file mode 100644
index 00000000000..a578e085efe
--- /dev/null
+++ b/src/test/run-make/coverage/coverage_tools.mk
@@ -0,0 +1,6 @@
+# Common Makefile include for Rust `run-make/coverage-* tests. Include this
+# file with the line:
+#
+# -include ../coverage/coverage_tools.mk
+
+-include ../tools.mk
diff --git a/src/test/run-make/coverage/dead_code.rs b/src/test/run-make/coverage/dead_code.rs
new file mode 100644
index 00000000000..a1285df0ec6
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/doctest.rs b/src/test/run-make/coverage/doctest.rs
new file mode 100644
index 00000000000..ec04ea57063
--- /dev/null
+++ b/src/test/run-make/coverage/doctest.rs
@@ -0,0 +1,99 @@
+//! This test ensures that code from doctests is properly re-mapped.
+//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
+//!
+//! Just some random code:
+//! ```
+//! if true {
+//!     // this is executed!
+//!     assert_eq!(1, 1);
+//! } else {
+//!     // this is not!
+//!     assert_eq!(1, 2);
+//! }
+//! ```
+//!
+//! doctest testing external code:
+//! ```
+//! extern crate doctest_crate;
+//! doctest_crate::fn_run_in_doctests(1);
+//! ```
+//!
+//! doctest returning a result:
+//! ```
+//! #[derive(Debug, PartialEq)]
+//! struct SomeError {
+//!     msg: String,
+//! }
+//! let mut res = Err(SomeError { msg: String::from("a message") });
+//! if res.is_ok() {
+//!     res?;
+//! } else {
+//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+//!         println!("{:?}", res);
+//!     }
+//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+//!         res = Ok(1);
+//!     }
+//!     res = Ok(0);
+//! }
+//! // need to be explicit because rustdoc cant infer the return type
+//! Ok::<(), SomeError>(())
+//! ```
+//!
+//! doctest with custom main:
+//! ```
+//! fn some_func() {
+//!     println!("called some_func()");
+//! }
+//!
+//! #[derive(Debug)]
+//! struct SomeError;
+//!
+//! extern crate doctest_crate;
+//!
+//! fn doctest_main() -> Result<(), SomeError> {
+//!     some_func();
+//!     doctest_crate::fn_run_in_doctests(2);
+//!     Ok(())
+//! }
+//!
+//! // this `main` is not shown as covered, as it clashes with all the other
+//! // `main` functions that were automatically generated for doctests
+//! fn main() -> Result<(), SomeError> {
+//!     doctest_main()
+//! }
+//! ```
+
+/// doctest attached to fn testing external code:
+/// ```
+/// extern crate doctest_crate;
+/// doctest_crate::fn_run_in_doctests(3);
+/// ```
+///
+fn main() {
+    if true {
+        assert_eq!(1, 1);
+    } else {
+        assert_eq!(1, 2);
+    }
+}
+
+// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
+// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
+// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
+//
+// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
+// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
+// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
+// one character past, the `if` block's closing brace. In both cases, these are most likely off
+// by the number of characters stripped from the beginning of each doc comment line: indent
+// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
+// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
+// more pronounced, and show up in more places, with background color used to show some distinct
+// code regions with different coverage counts.
+//
+// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
+// character stripped from the beginning of doc comment lines with a space. This will give coverage
+// results the correct column offsets, and I think it should compile correctly, but I don't know
+// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
+// if the indentation changed. I don't know if there is a more viable solution.
diff --git a/src/test/run-make/coverage/drop_trait.rs b/src/test/run-make/coverage/drop_trait.rs
new file mode 100644
index 00000000000..d15bfc0f877
--- /dev/null
+++ b/src/test/run-make/coverage/drop_trait.rs
@@ -0,0 +1,33 @@
+#![allow(unused_assignments)]
+// expect-exit-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/src/test/run-make/coverage/generator.rs b/src/test/run-make/coverage/generator.rs
new file mode 100644
index 00000000000..4319991021e
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/generics.rs b/src/test/run-make/coverage/generics.rs
new file mode 100644
index 00000000000..18b38868496
--- /dev/null
+++ b/src/test/run-make/coverage/generics.rs
@@ -0,0 +1,48 @@
+#![allow(unused_assignments)]
+// expect-exit-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/src/test/run-make/coverage/if.rs b/src/test/run-make/coverage/if.rs
new file mode 100644
index 00000000000..8ad5042ff7b
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/if_else.rs b/src/test/run-make/coverage/if_else.rs
new file mode 100644
index 00000000000..3244e1e3afd
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/inline-dead.rs b/src/test/run-make/coverage/inline-dead.rs
new file mode 100644
index 00000000000..854fa062967
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/inline.rs b/src/test/run-make/coverage/inline.rs
new file mode 100644
index 00000000000..9cfab9ddbad
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/inner_items.rs b/src/test/run-make/coverage/inner_items.rs
new file mode 100644
index 00000000000..bcb62b3031c
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/issue-83601.rs b/src/test/run-make/coverage/issue-83601.rs
new file mode 100644
index 00000000000..0b72a81947c
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/issue-84561.rs b/src/test/run-make/coverage/issue-84561.rs
new file mode 100644
index 00000000000..b39a289c45e
--- /dev/null
+++ b/src/test/run-make/coverage/issue-84561.rs
@@ -0,0 +1,182 @@
+// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
+
+// expect-exit-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/src/test/run-make/coverage/issue-85461.rs b/src/test/run-make/coverage/issue-85461.rs
new file mode 100644
index 00000000000..a1b9ebb1ed3
--- /dev/null
+++ b/src/test/run-make/coverage/issue-85461.rs
@@ -0,0 +1,10 @@
+// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+
+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/src/test/run-make/coverage/issue-93054.rs b/src/test/run-make/coverage/issue-93054.rs
new file mode 100644
index 00000000000..c160b3db03f
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/lazy_boolean.rs b/src/test/run-make/coverage/lazy_boolean.rs
new file mode 100644
index 00000000000..bb6219e851c
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/lib/doctest_crate.rs b/src/test/run-make/coverage/lib/doctest_crate.rs
new file mode 100644
index 00000000000..c3210146d69
--- /dev/null
+++ b/src/test/run-make/coverage/lib/doctest_crate.rs
@@ -0,0 +1,9 @@
+/// A function run only from within doctests
+pub fn fn_run_in_doctests(conditional: usize) {
+    match conditional {
+        1 => assert_eq!(1, 1), // this is run,
+        2 => assert_eq!(1, 1), // this,
+        3 => assert_eq!(1, 1), // and this too
+        _ => assert_eq!(1, 2), // however this is not
+    }
+}
diff --git a/src/test/run-make/coverage/lib/inline_always_with_dead_code.rs b/src/test/run-make/coverage/lib/inline_always_with_dead_code.rs
new file mode 100644
index 00000000000..2b21dee6ccf
--- /dev/null
+++ b/src/test/run-make/coverage/lib/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/src/test/run-make/coverage/lib/unused_mod_helper.rs b/src/test/run-make/coverage/lib/unused_mod_helper.rs
new file mode 100644
index 00000000000..ae1cc1531ed
--- /dev/null
+++ b/src/test/run-make/coverage/lib/unused_mod_helper.rs
@@ -0,0 +1,3 @@
+pub fn never_called_function() {
+    println!("I am never called");
+}
diff --git a/src/test/run-make/coverage/lib/used_crate.rs b/src/test/run-make/coverage/lib/used_crate.rs
new file mode 100644
index 00000000000..8b8b1f7f351
--- /dev/null
+++ b/src/test/run-make/coverage/lib/used_crate.rs
@@ -0,0 +1,100 @@
+#![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();
+}
+
+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/src/test/run-make/coverage/lib/used_inline_crate.rs b/src/test/run-make/coverage/lib/used_inline_crate.rs
new file mode 100644
index 00000000000..4a052756d4e
--- /dev/null
+++ b/src/test/run-make/coverage/lib/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/src/test/run-make/coverage/loop_break_value.rs b/src/test/run-make/coverage/loop_break_value.rs
new file mode 100644
index 00000000000..dbc4fad7a23
--- /dev/null
+++ b/src/test/run-make/coverage/loop_break_value.rs
@@ -0,0 +1,13 @@
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+    let result
+        =
+            loop
+        {
+            break
+            10
+            ;
+        }
+    ;
+}
diff --git a/src/test/run-make/coverage/loops_branches.rs b/src/test/run-make/coverage/loops_branches.rs
new file mode 100644
index 00000000000..7116ce47f4b
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/match_or_pattern.rs b/src/test/run-make/coverage/match_or_pattern.rs
new file mode 100644
index 00000000000..4c6a8a9b703
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/nested_loops.rs b/src/test/run-make/coverage/nested_loops.rs
new file mode 100644
index 00000000000..4c7c7842796
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/no_cov_crate.rs b/src/test/run-make/coverage/no_cov_crate.rs
new file mode 100644
index 00000000000..0bfbdda2cab
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/overflow.rs b/src/test/run-make/coverage/overflow.rs
new file mode 100644
index 00000000000..e537b0e95c3
--- /dev/null
+++ b/src/test/run-make/coverage/overflow.rs
@@ -0,0 +1,63 @@
+#![allow(unused_assignments)]
+// expect-exit-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/src/test/run-make/coverage/panic_unwind.rs b/src/test/run-make/coverage/panic_unwind.rs
new file mode 100644
index 00000000000..03128c2cce6
--- /dev/null
+++ b/src/test/run-make/coverage/panic_unwind.rs
@@ -0,0 +1,31 @@
+#![allow(unused_assignments)]
+// expect-exit-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/src/test/run-make/coverage/partial_eq.rs b/src/test/run-make/coverage/partial_eq.rs
new file mode 100644
index 00000000000..4ceaba9b111
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/simple_loop.rs b/src/test/run-make/coverage/simple_loop.rs
new file mode 100644
index 00000000000..6f7f23475b8
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/simple_match.rs b/src/test/run-make/coverage/simple_match.rs
new file mode 100644
index 00000000000..be99e59a826
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/tight_inf_loop.rs b/src/test/run-make/coverage/tight_inf_loop.rs
new file mode 100644
index 00000000000..cef99027aaa
--- /dev/null
+++ b/src/test/run-make/coverage/tight_inf_loop.rs
@@ -0,0 +1,5 @@
+fn main() {
+    if false {
+        loop {}
+    }
+}
diff --git a/src/test/run-make/coverage/try_error_result.rs b/src/test/run-make/coverage/try_error_result.rs
new file mode 100644
index 00000000000..cd0acf72302
--- /dev/null
+++ b/src/test/run-make/coverage/try_error_result.rs
@@ -0,0 +1,118 @@
+#![allow(unused_assignments)]
+// expect-exit-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/src/test/run-make/coverage/unused.rs b/src/test/run-make/coverage/unused.rs
new file mode 100644
index 00000000000..fb6113eb01c
--- /dev/null
+++ b/src/test/run-make/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/src/test/run-make/coverage/unused_mod.rs b/src/test/run-make/coverage/unused_mod.rs
new file mode 100644
index 00000000000..679b4e53188
--- /dev/null
+++ b/src/test/run-make/coverage/unused_mod.rs
@@ -0,0 +1,6 @@
+#[path = "lib/unused_mod_helper.rs"]
+mod unused_module;
+
+fn main() {
+    println!("hello world!");
+}
diff --git a/src/test/run-make/coverage/uses_crate.rs b/src/test/run-make/coverage/uses_crate.rs
new file mode 100644
index 00000000000..20cb05fe5b0
--- /dev/null
+++ b/src/test/run-make/coverage/uses_crate.rs
@@ -0,0 +1,12 @@
+#![allow(unused_assignments, unused_variables)]
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+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/src/test/run-make/coverage/uses_inline_crate.rs b/src/test/run-make/coverage/uses_inline_crate.rs
new file mode 100644
index 00000000000..a7fe8532be3
--- /dev/null
+++ b/src/test/run-make/coverage/uses_inline_crate.rs
@@ -0,0 +1,17 @@
+#![allow(unused_assignments, unused_variables)]
+
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+
+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/src/test/run-make/coverage/while.rs b/src/test/run-make/coverage/while.rs
new file mode 100644
index 00000000000..781b90b3566
--- /dev/null
+++ b/src/test/run-make/coverage/while.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let num = 9;
+    while num >= 10 {
+    }
+}
diff --git a/src/test/run-make/coverage/while_early_ret.rs b/src/test/run-make/coverage/while_early_ret.rs
new file mode 100644
index 00000000000..1fcea9c85c4
--- /dev/null
+++ b/src/test/run-make/coverage/while_early_ret.rs
@@ -0,0 +1,42 @@
+#![allow(unused_assignments)]
+// expect-exit-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/src/test/run-make/coverage/yield.rs b/src/test/run-make/coverage/yield.rs
new file mode 100644
index 00000000000..ff7616656ff
--- /dev/null
+++ b/src/test/run-make/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"),
+    }
+}