about summary refs log tree commit diff
path: root/compiler/rustc_middle/src/mir/coverage.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/mir/coverage.rs')
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs39
1 files changed, 39 insertions, 0 deletions
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index b7410ca5f18..962176290df 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -3,6 +3,7 @@
 use std::fmt::{self, Debug, Formatter};
 
 use rustc_index::IndexVec;
+use rustc_index::bit_set::BitSet;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
 use rustc_span::Span;
 
@@ -310,3 +311,41 @@ pub struct MCDCDecisionSpan {
     pub decision_depth: u16,
     pub num_conditions: usize,
 }
+
+/// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass
+/// (for compiler option `-Cinstrument-coverage`), after MIR optimizations
+/// have had a chance to potentially remove some of them.
+///
+/// Used by the `coverage_ids_info` query.
+#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)]
+pub struct CoverageIdsInfo {
+    pub counters_seen: BitSet<CounterId>,
+    pub zero_expressions: BitSet<ExpressionId>,
+}
+
+impl CoverageIdsInfo {
+    /// Coverage codegen needs to know how many coverage counters are ever
+    /// incremented within a function, so that it can set the `num-counters`
+    /// argument of the `llvm.instrprof.increment` intrinsic.
+    ///
+    /// This may be less than the highest counter ID emitted by the
+    /// InstrumentCoverage MIR pass, if the highest-numbered counter increments
+    /// were removed by MIR optimizations.
+    pub fn num_counters_after_mir_opts(&self) -> u32 {
+        // FIXME(Zalathar): Currently this treats an unused counter as "used"
+        // if its ID is less than that of the highest counter that really is
+        // used. Fixing this would require adding a renumbering step somewhere.
+        self.counters_seen.last_set_in(..).map_or(0, |max| max.as_u32() + 1)
+    }
+
+    /// Returns `true` if the given term is known to have a value of zero, taking
+    /// into account knowledge of which counters are unused and which expressions
+    /// are always zero.
+    pub fn is_zero_term(&self, term: CovTerm) -> bool {
+        match term {
+            CovTerm::Zero => true,
+            CovTerm::Counter(id) => !self.counters_seen.contains(id),
+            CovTerm::Expression(id) => self.zero_expressions.contains(id),
+        }
+    }
+}