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