1
1
use rustc_data_structures:: captures:: Captures ;
2
- use rustc_index:: IndexSlice ;
3
2
use rustc_index:: bit_set:: DenseBitSet ;
4
3
use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
5
- use rustc_middle:: mir:: coverage:: {
6
- BasicCoverageBlock , CounterId , CovTerm , CoverageIdsInfo , CoverageKind , Expression ,
7
- ExpressionId , MappingKind , Op ,
8
- } ;
4
+ use rustc_middle:: mir:: coverage:: { BasicCoverageBlock , CoverageIdsInfo , CoverageKind , MappingKind } ;
9
5
use rustc_middle:: mir:: { Body , Statement , StatementKind } ;
10
6
use rustc_middle:: query:: TyCtxtAt ;
11
7
use rustc_middle:: ty:: { self , TyCtxt } ;
@@ -136,44 +132,12 @@ fn coverage_ids_info<'tcx>(
136
132
let node_counters = make_node_counters ( & fn_cov_info. node_flow_data , & fn_cov_info. priority_list ) ;
137
133
let coverage_counters = transcribe_counters ( & node_counters, & bcb_needs_counter, & bcbs_seen) ;
138
134
139
- let mut counters_seen = DenseBitSet :: new_empty ( coverage_counters. node_counters . len ( ) ) ;
140
- let mut expressions_seen = DenseBitSet :: new_filled ( coverage_counters. expressions . len ( ) ) ;
141
-
142
- // For each expression ID that is directly used by one or more mappings,
143
- // mark it as not-yet-seen. This indicates that we expect to see a
144
- // corresponding `VirtualCounter` statement during MIR traversal.
145
- for mapping in fn_cov_info. mappings . iter ( ) {
146
- // Currently we only worry about ordinary code mappings.
147
- // For branch and MC/DC mappings, expressions might not correspond
148
- // to any particular point in the control-flow graph.
149
- if let MappingKind :: Code { bcb } = mapping. kind
150
- && let Some ( CovTerm :: Expression ( id) ) = coverage_counters. node_counters [ bcb]
151
- {
152
- expressions_seen. remove ( id) ;
153
- }
154
- }
155
-
156
- for bcb in bcbs_seen. iter ( ) {
157
- if let Some ( & id) = coverage_counters. phys_counter_for_node . get ( & bcb) {
158
- counters_seen. insert ( id) ;
159
- }
160
- if let Some ( CovTerm :: Expression ( id) ) = coverage_counters. node_counters [ bcb] {
161
- expressions_seen. insert ( id) ;
162
- }
163
- }
164
-
165
- let zero_expressions = identify_zero_expressions (
166
- & coverage_counters. expressions ,
167
- & counters_seen,
168
- & expressions_seen,
169
- ) ;
170
-
171
- let CoverageCounters { phys_counter_for_node, node_counters, expressions, .. } =
172
- coverage_counters;
135
+ let CoverageCounters {
136
+ phys_counter_for_node, next_counter_id, node_counters, expressions, ..
137
+ } = coverage_counters;
173
138
174
139
Some ( CoverageIdsInfo {
175
- counters_seen,
176
- zero_expressions,
140
+ num_counters : next_counter_id. as_u32 ( ) ,
177
141
phys_counter_for_node,
178
142
term_for_bcb : node_counters,
179
143
expressions,
@@ -195,94 +159,3 @@ fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool {
195
159
let scope_data = & body. source_scopes [ statement. source_info . scope ] ;
196
160
scope_data. inlined . is_some ( ) || scope_data. inlined_parent_scope . is_some ( )
197
161
}
198
-
199
- /// Identify expressions that will always have a value of zero, and note their
200
- /// IDs in a `DenseBitSet`. Mappings that refer to a zero expression can instead
201
- /// become mappings to a constant zero value.
202
- ///
203
- /// This function mainly exists to preserve the simplifications that were
204
- /// already being performed by the Rust-side expression renumbering, so that
205
- /// the resulting coverage mappings don't get worse.
206
- fn identify_zero_expressions (
207
- expressions : & IndexSlice < ExpressionId , Expression > ,
208
- counters_seen : & DenseBitSet < CounterId > ,
209
- expressions_seen : & DenseBitSet < ExpressionId > ,
210
- ) -> DenseBitSet < ExpressionId > {
211
- // The set of expressions that either were optimized out entirely, or
212
- // have zero as both of their operands, and will therefore always have
213
- // a value of zero. Other expressions that refer to these as operands
214
- // can have those operands replaced with `CovTerm::Zero`.
215
- let mut zero_expressions = DenseBitSet :: new_empty ( expressions. len ( ) ) ;
216
-
217
- // Simplify a copy of each expression based on lower-numbered expressions,
218
- // and then update the set of always-zero expressions if necessary.
219
- // (By construction, expressions can only refer to other expressions
220
- // that have lower IDs, so one pass is sufficient.)
221
- for ( id, expression) in expressions. iter_enumerated ( ) {
222
- if !expressions_seen. contains ( id) {
223
- // If an expression was not seen, it must have been optimized away,
224
- // so any operand that refers to it can be replaced with zero.
225
- zero_expressions. insert ( id) ;
226
- continue ;
227
- }
228
-
229
- // We don't need to simplify the actual expression data in the
230
- // expressions list; we can just simplify a temporary copy and then
231
- // use that to update the set of always-zero expressions.
232
- let Expression { mut lhs, op, mut rhs } = * expression;
233
-
234
- // If an expression has an operand that is also an expression, the
235
- // operand's ID must be strictly lower. This is what lets us find
236
- // all zero expressions in one pass.
237
- let assert_operand_expression_is_lower = |operand_id : ExpressionId | {
238
- assert ! (
239
- operand_id < id,
240
- "Operand {operand_id:?} should be less than {id:?} in {expression:?}" ,
241
- )
242
- } ;
243
-
244
- // If an operand refers to a counter or expression that is always
245
- // zero, then that operand can be replaced with `CovTerm::Zero`.
246
- let maybe_set_operand_to_zero = |operand : & mut CovTerm | {
247
- if let CovTerm :: Expression ( id) = * operand {
248
- assert_operand_expression_is_lower ( id) ;
249
- }
250
-
251
- if is_zero_term ( & counters_seen, & zero_expressions, * operand) {
252
- * operand = CovTerm :: Zero ;
253
- }
254
- } ;
255
- maybe_set_operand_to_zero ( & mut lhs) ;
256
- maybe_set_operand_to_zero ( & mut rhs) ;
257
-
258
- // Coverage counter values cannot be negative, so if an expression
259
- // involves subtraction from zero, assume that its RHS must also be zero.
260
- // (Do this after simplifications that could set the LHS to zero.)
261
- if lhs == CovTerm :: Zero && op == Op :: Subtract {
262
- rhs = CovTerm :: Zero ;
263
- }
264
-
265
- // After the above simplifications, if both operands are zero, then
266
- // we know that this expression is always zero too.
267
- if lhs == CovTerm :: Zero && rhs == CovTerm :: Zero {
268
- zero_expressions. insert ( id) ;
269
- }
270
- }
271
-
272
- zero_expressions
273
- }
274
-
275
- /// Returns `true` if the given term is known to have a value of zero, taking
276
- /// into account knowledge of which counters are unused and which expressions
277
- /// are always zero.
278
- fn is_zero_term (
279
- counters_seen : & DenseBitSet < CounterId > ,
280
- zero_expressions : & DenseBitSet < ExpressionId > ,
281
- term : CovTerm ,
282
- ) -> bool {
283
- match term {
284
- CovTerm :: Zero => true ,
285
- CovTerm :: Counter ( id) => !counters_seen. contains ( id) ,
286
- CovTerm :: Expression ( id) => zero_expressions. contains ( id) ,
287
- }
288
- }
0 commit comments