@@ -3,7 +3,7 @@ use rustc_index::interval::SparseIntervalMatrix;
33use rustc_index::{Idx, IndexVec};
44use rustc_middle::mir::{self, BasicBlock, Body, Location};
55
6- use crate::framework::{Analysis, Results, ResultsVisitor, visit_results};
6+ use crate::framework::{Analysis, Direction, Results, ResultsVisitor, visit_results};
77
88/// Maps between a `Location` and a `PointIndex` (and vice versa).
99pub struct DenseLocationMap {
@@ -105,27 +105,47 @@ where
105105 N: Idx,
106106 A: Analysis<'tcx, Domain = DenseBitSet<N>>,
107107{
108- let values = SparseIntervalMatrix::new(elements.num_points());
109- let mut visitor = Visitor { elements, values };
110- visit_results(
111- body,
112- body.basic_blocks.reverse_postorder().iter().copied(),
113- &mut analysis,
114- &results,
115- &mut visitor,
116- );
117- visitor.values
108+ let mut values = SparseIntervalMatrix::new(elements.num_points());
109+ let reachable_blocks = mir::traversal::reachable_as_bitset(body);
110+ if A::Direction::IS_BACKWARD {
111+ // Iterate blocks in decreasing order, to visit locations in decreasing order. This
112+ // allows to use the more efficient `prepend` method to interval sets.
113+ let callback = |state: &DenseBitSet<N>, location| {
114+ let point = elements.point_from_location(location);
115+ // Use internal iterator manually as it is much more efficient.
116+ state.iter().for_each(|node| values.prepend(node, point));
117+ };
118+ let mut visitor = Visitor { callback };
119+ visit_results(
120+ body,
121+ // Note the `.rev()`.
122+ body.basic_blocks.indices().filter(|&bb| reachable_blocks.contains(bb)).rev(),
123+ &mut analysis,
124+ &results,
125+ &mut visitor,
126+ );
127+ } else {
128+ // Iterate blocks in increasing order, to visit locations in increasing order. This
129+ // allows to use the more efficient `append` method to interval sets.
130+ let callback = |state: &DenseBitSet<N>, location| {
131+ let point = elements.point_from_location(location);
132+ // Use internal iterator manually as it is much more efficient.
133+ state.iter().for_each(|node| values.append(node, point));
134+ };
135+ let mut visitor = Visitor { callback };
136+ visit_results(body, reachable_blocks.iter(), &mut analysis, &results, &mut visitor);
137+ }
138+ values
118139}
119140
120- struct Visitor<'a, N: Idx> {
121- elements: &'a DenseLocationMap,
122- values: SparseIntervalMatrix<N, PointIndex>,
141+ struct Visitor<F> {
142+ callback: F,
123143}
124144
125- impl<'tcx, A, N > ResultsVisitor<'tcx, A> for Visitor<'_, N >
145+ impl<'tcx, A, F > ResultsVisitor<'tcx, A> for Visitor<F >
126146where
127- A: Analysis<'tcx, Domain = DenseBitSet<N> >,
128- N: Idx ,
147+ A: Analysis<'tcx>,
148+ F: FnMut(&A::Domain, Location) ,
129149{
130150 fn visit_after_primary_statement_effect<'mir>(
131151 &mut self,
@@ -134,11 +154,7 @@ where
134154 _statement: &'mir mir::Statement<'tcx>,
135155 location: Location,
136156 ) {
137- let point = self.elements.point_from_location(location);
138- // Use internal iterator manually as it is much more efficient.
139- state.iter().for_each(|node| {
140- self.values.insert(node, point);
141- });
157+ (self.callback)(state, location);
142158 }
143159
144160 fn visit_after_primary_terminator_effect<'mir>(
@@ -148,10 +164,6 @@ where
148164 _terminator: &'mir mir::Terminator<'tcx>,
149165 location: Location,
150166 ) {
151- let point = self.elements.point_from_location(location);
152- // Use internal iterator manually as it is much more efficient.
153- state.iter().for_each(|node| {
154- self.values.insert(node, point);
155- });
167+ (self.callback)(state, location);
156168 }
157169}
0 commit comments