@@ -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