|
1 | 1 | use rustc_data_structures::captures::Captures;
|
2 |
| -use rustc_data_structures::fx::FxIndexSet; |
3 |
| -use rustc_index::bit_set::BitSet; |
4 | 2 | use rustc_middle::mir::coverage::{
|
5 |
| - CounterId, CovTerm, CoverageIdsInfo, Expression, ExpressionId, FunctionCoverageInfo, Mapping, |
6 |
| - MappingKind, Op, SourceRegion, |
| 3 | + CovTerm, CoverageIdsInfo, Expression, FunctionCoverageInfo, Mapping, MappingKind, Op, |
| 4 | + SourceRegion, |
7 | 5 | };
|
8 | 6 | use rustc_middle::ty::Instance;
|
9 | 7 | use tracing::debug;
|
@@ -55,92 +53,17 @@ impl<'tcx> FunctionCoverageCollector<'tcx> {
|
55 | 53 | Self { function_coverage_info, ids_info, is_used }
|
56 | 54 | }
|
57 | 55 |
|
58 |
| - /// Identify expressions that will always have a value of zero, and note |
59 |
| - /// their IDs in [`ZeroExpressions`]. Mappings that refer to a zero expression |
60 |
| - /// can instead become mappings to a constant zero value. |
61 |
| - /// |
62 |
| - /// This method mainly exists to preserve the simplifications that were |
63 |
| - /// already being performed by the Rust-side expression renumbering, so that |
64 |
| - /// the resulting coverage mappings don't get worse. |
65 |
| - fn identify_zero_expressions(&self) -> ZeroExpressions { |
66 |
| - // The set of expressions that either were optimized out entirely, or |
67 |
| - // have zero as both of their operands, and will therefore always have |
68 |
| - // a value of zero. Other expressions that refer to these as operands |
69 |
| - // can have those operands replaced with `CovTerm::Zero`. |
70 |
| - let mut zero_expressions = ZeroExpressions::default(); |
71 |
| - |
72 |
| - // Simplify a copy of each expression based on lower-numbered expressions, |
73 |
| - // and then update the set of always-zero expressions if necessary. |
74 |
| - // (By construction, expressions can only refer to other expressions |
75 |
| - // that have lower IDs, so one pass is sufficient.) |
76 |
| - for (id, expression) in self.function_coverage_info.expressions.iter_enumerated() { |
77 |
| - if !self.is_used || !self.ids_info.expressions_seen.contains(id) { |
78 |
| - // If an expression was not seen, it must have been optimized away, |
79 |
| - // so any operand that refers to it can be replaced with zero. |
80 |
| - zero_expressions.insert(id); |
81 |
| - continue; |
82 |
| - } |
83 |
| - |
84 |
| - // We don't need to simplify the actual expression data in the |
85 |
| - // expressions list; we can just simplify a temporary copy and then |
86 |
| - // use that to update the set of always-zero expressions. |
87 |
| - let Expression { mut lhs, op, mut rhs } = *expression; |
88 |
| - |
89 |
| - // If an expression has an operand that is also an expression, the |
90 |
| - // operand's ID must be strictly lower. This is what lets us find |
91 |
| - // all zero expressions in one pass. |
92 |
| - let assert_operand_expression_is_lower = |operand_id: ExpressionId| { |
93 |
| - assert!( |
94 |
| - operand_id < id, |
95 |
| - "Operand {operand_id:?} should be less than {id:?} in {expression:?}", |
96 |
| - ) |
97 |
| - }; |
98 |
| - |
99 |
| - // If an operand refers to a counter or expression that is always |
100 |
| - // zero, then that operand can be replaced with `CovTerm::Zero`. |
101 |
| - let maybe_set_operand_to_zero = |operand: &mut CovTerm| { |
102 |
| - if let CovTerm::Expression(id) = *operand { |
103 |
| - assert_operand_expression_is_lower(id); |
104 |
| - } |
105 |
| - |
106 |
| - if is_zero_term(&self.ids_info.counters_seen, &zero_expressions, *operand) { |
107 |
| - *operand = CovTerm::Zero; |
108 |
| - } |
109 |
| - }; |
110 |
| - maybe_set_operand_to_zero(&mut lhs); |
111 |
| - maybe_set_operand_to_zero(&mut rhs); |
112 |
| - |
113 |
| - // Coverage counter values cannot be negative, so if an expression |
114 |
| - // involves subtraction from zero, assume that its RHS must also be zero. |
115 |
| - // (Do this after simplifications that could set the LHS to zero.) |
116 |
| - if lhs == CovTerm::Zero && op == Op::Subtract { |
117 |
| - rhs = CovTerm::Zero; |
118 |
| - } |
119 |
| - |
120 |
| - // After the above simplifications, if both operands are zero, then |
121 |
| - // we know that this expression is always zero too. |
122 |
| - if lhs == CovTerm::Zero && rhs == CovTerm::Zero { |
123 |
| - zero_expressions.insert(id); |
124 |
| - } |
125 |
| - } |
126 |
| - |
127 |
| - zero_expressions |
128 |
| - } |
129 |
| - |
130 | 56 | pub(crate) fn into_finished(self) -> FunctionCoverage<'tcx> {
|
131 |
| - let zero_expressions = self.identify_zero_expressions(); |
132 | 57 | let FunctionCoverageCollector { function_coverage_info, ids_info, is_used, .. } = self;
|
133 | 58 |
|
134 |
| - FunctionCoverage { function_coverage_info, ids_info, is_used, zero_expressions } |
| 59 | + FunctionCoverage { function_coverage_info, ids_info, is_used } |
135 | 60 | }
|
136 | 61 | }
|
137 | 62 |
|
138 | 63 | pub(crate) struct FunctionCoverage<'tcx> {
|
139 | 64 | pub(crate) function_coverage_info: &'tcx FunctionCoverageInfo,
|
140 | 65 | ids_info: &'tcx CoverageIdsInfo,
|
141 | 66 | is_used: bool,
|
142 |
| - |
143 |
| - zero_expressions: ZeroExpressions, |
144 | 67 | }
|
145 | 68 |
|
146 | 69 | impl<'tcx> FunctionCoverage<'tcx> {
|
@@ -195,37 +118,6 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
195 | 118 | }
|
196 | 119 |
|
197 | 120 | fn is_zero_term(&self, term: CovTerm) -> bool {
|
198 |
| - !self.is_used || is_zero_term(&self.ids_info.counters_seen, &self.zero_expressions, term) |
199 |
| - } |
200 |
| -} |
201 |
| - |
202 |
| -/// Set of expression IDs that are known to always evaluate to zero. |
203 |
| -/// Any mapping or expression operand that refers to these expressions can have |
204 |
| -/// that reference replaced with a constant zero value. |
205 |
| -#[derive(Default)] |
206 |
| -struct ZeroExpressions(FxIndexSet<ExpressionId>); |
207 |
| - |
208 |
| -impl ZeroExpressions { |
209 |
| - fn insert(&mut self, id: ExpressionId) { |
210 |
| - self.0.insert(id); |
211 |
| - } |
212 |
| - |
213 |
| - fn contains(&self, id: ExpressionId) -> bool { |
214 |
| - self.0.contains(&id) |
215 |
| - } |
216 |
| -} |
217 |
| - |
218 |
| -/// Returns `true` if the given term is known to have a value of zero, taking |
219 |
| -/// into account knowledge of which counters are unused and which expressions |
220 |
| -/// are always zero. |
221 |
| -fn is_zero_term( |
222 |
| - counters_seen: &BitSet<CounterId>, |
223 |
| - zero_expressions: &ZeroExpressions, |
224 |
| - term: CovTerm, |
225 |
| -) -> bool { |
226 |
| - match term { |
227 |
| - CovTerm::Zero => true, |
228 |
| - CovTerm::Counter(id) => !counters_seen.contains(id), |
229 |
| - CovTerm::Expression(id) => zero_expressions.contains(id), |
| 121 | + !self.is_used || self.ids_info.is_zero_term(term) |
230 | 122 | }
|
231 | 123 | }
|
0 commit comments