@@ -27,6 +27,9 @@ pub struct FunctionCoverage<'tcx> {
2727 /// that might be introduced by MIR inlining.
2828 counters_seen : BitSet < CounterId > ,
2929 expressions : IndexVec < ExpressionId , Option < Expression > > ,
30+ /// Tracks which expressions are known to always have a value of zero.
31+ /// Only updated during the finalize step.
32+ zero_expressions : FxIndexSet < ExpressionId > ,
3033 mappings : Vec < Mapping > ,
3134}
3235
@@ -63,6 +66,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
6366 is_used,
6467 counters_seen : BitSet :: new_empty ( num_counters) ,
6568 expressions : IndexVec :: from_elem_n ( None , num_expressions) ,
69+ zero_expressions : FxIndexSet :: default ( ) ,
6670 mappings : Vec :: new ( ) ,
6771 }
6872 }
@@ -134,39 +138,44 @@ impl<'tcx> FunctionCoverage<'tcx> {
134138 }
135139
136140 pub ( crate ) fn finalize ( & mut self ) {
137- self . simplify_expressions ( ) ;
141+ self . update_zero_expressions ( ) ;
138142
139143 // Sort all of the collected mappings into a predictable order.
140144 // (Mappings have a total order, so an unstable sort should be fine.)
141145 self . mappings . sort_unstable ( ) ;
142146 }
143147
144- /// Perform some simplifications to make the final coverage mappings
145- /// slightly smaller.
148+ /// Identify expressions that will always have a value of zero, and note
149+ /// their IDs in `zero_expressions`. Mappings that refer to a zero expression
150+ /// can instead become mappings to a constant zero value.
146151 ///
147152 /// This method mainly exists to preserve the simplifications that were
148153 /// already being performed by the Rust-side expression renumbering, so that
149154 /// the resulting coverage mappings don't get worse.
150- fn simplify_expressions ( & mut self ) {
155+ fn update_zero_expressions ( & mut self ) {
151156 // The set of expressions that either were optimized out entirely, or
152157 // have zero as both of their operands, and will therefore always have
153158 // a value of zero. Other expressions that refer to these as operands
154159 // can have those operands replaced with `CovTerm::Zero`.
155- let mut zero_expressions = FxIndexSet :: default ( ) ;
160+ let zero_expressions = & mut self . zero_expressions ;
156161
157- // For each expression, perform simplifications based on lower-numbered
158- // expressions, and then update the set of always-zero expressions if
159- // necessary.
162+ // Simplify a copy of each expression based on lower-numbered expressions,
163+ // and then update the set of always-zero expressions if necessary.
160164 // (By construction, expressions can only refer to other expressions
161- // that have lower IDs, so one simplification pass is sufficient.)
162- for ( id, maybe_expression) in self . expressions . iter_enumerated_mut ( ) {
165+ // that have lower IDs, so one pass is sufficient.)
166+ for ( id, maybe_expression) in self . expressions . iter_enumerated ( ) {
163167 let Some ( expression) = maybe_expression else {
164168 // If an expression is missing, it must have been optimized away,
165169 // so any operand that refers to it can be replaced with zero.
166170 zero_expressions. insert ( id) ;
167171 continue ;
168172 } ;
169173
174+ // We don't need to simplify the actual expression data in the
175+ // expressions list; we can just simplify a temporary copy and then
176+ // use that to update the set of always-zero expressions.
177+ let mut expression = expression. clone ( ) ;
178+
170179 // If an operand refers to an expression that is always zero, then
171180 // that operand can be replaced with `CovTerm::Zero`.
172181 let maybe_set_operand_to_zero = |operand : & mut CovTerm | match & * operand {
@@ -207,6 +216,11 @@ impl<'tcx> FunctionCoverage<'tcx> {
207216 // thing on the Rust side unless we're confident we can do much better.
208217 // (See `CounterExpressionsMinimizer` in `CoverageMappingWriter.cpp`.)
209218
219+ let counter_from_operand = |operand : CovTerm | match operand {
220+ CovTerm :: Expression ( id) if self . zero_expressions . contains ( & id) => Counter :: ZERO ,
221+ _ => Counter :: from_term ( operand) ,
222+ } ;
223+
210224 self . expressions
211225 . iter ( )
212226 . map ( |expression| match expression {
@@ -220,12 +234,12 @@ impl<'tcx> FunctionCoverage<'tcx> {
220234 & Some ( Expression { lhs, op, rhs, .. } ) => {
221235 // Convert the operands and operator as normal.
222236 CounterExpression :: new (
223- Counter :: from_term ( lhs) ,
237+ counter_from_operand ( lhs) ,
224238 match op {
225239 Op :: Add => ExprKind :: Add ,
226240 Op :: Subtract => ExprKind :: Subtract ,
227241 } ,
228- Counter :: from_term ( rhs) ,
242+ counter_from_operand ( rhs) ,
229243 )
230244 }
231245 } )
0 commit comments