11use crate :: borrow_check:: nll:: region_infer:: values:: { PointIndex , RegionValueElements } ;
2- use crate :: borrow_check:: nll:: type_check:: liveness:: liveness_map:: { LiveVar , NllLivenessMap } ;
3- use crate :: util:: liveness:: { categorize, DefUse , LiveVariableMap } ;
2+ use crate :: util:: liveness:: { categorize, DefUse } ;
43use rustc:: mir:: visit:: { PlaceContext , Visitor } ;
54use rustc:: mir:: { Local , Location , Mir } ;
65use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
@@ -9,26 +8,33 @@ use rustc_data_structures::vec_linked_list as vll;
98/// A map that cross references each local with the locations where it
109/// is defined (assigned), used, or dropped. Used during liveness
1110/// computation.
12- crate struct LocalUseMap < ' me > {
13- liveness_map : & ' me NllLivenessMap ,
14-
11+ ///
12+ /// We keep track only of `Local`s we'll do the liveness analysis later,
13+ /// this means that our internal `IndexVec`s will only be sparsely populated.
14+ /// In the time-memory trade-off between keeping compact vectors with new
15+ /// indexes (and needing to continuously map the `Local` index to its compact
16+ /// counterpart) and having `IndexVec`s that we only use a fraction of, time
17+ /// (and code simplicity) was favored. The rationale is that we only keep
18+ /// a small number of `IndexVec`s throughout the entire analysis while, in
19+ /// contrast, we're accessing each `Local` *many* times.
20+ crate struct LocalUseMap {
1521 /// Head of a linked list of **definitions** of each variable --
1622 /// definition in this context means assignment, e.g., `x` is
1723 /// defined in `x = y` but not `y`; that first def is the head of
1824 /// a linked list that lets you enumerate all places the variable
1925 /// is assigned.
20- first_def_at : IndexVec < LiveVar , Option < AppearanceIndex > > ,
26+ first_def_at : IndexVec < Local , Option < AppearanceIndex > > ,
2127
2228 /// Head of a linked list of **uses** of each variable -- use in
2329 /// this context means that the existing value of the variable is
2430 /// read or modified. e.g., `y` is used in `x = y` but not `x`.
2531 /// Note that `DROP(x)` terminators are excluded from this list.
26- first_use_at : IndexVec < LiveVar , Option < AppearanceIndex > > ,
32+ first_use_at : IndexVec < Local , Option < AppearanceIndex > > ,
2733
2834 /// Head of a linked list of **drops** of each variable -- these
2935 /// are a special category of uses corresponding to the drop that
3036 /// we add for each local variable.
31- first_drop_at : IndexVec < LiveVar , Option < AppearanceIndex > > ,
37+ first_drop_at : IndexVec < Local , Option < AppearanceIndex > > ,
3238
3339 appearances : IndexVec < AppearanceIndex , Appearance > ,
3440}
@@ -50,55 +56,68 @@ impl vll::LinkElem for Appearance {
5056 }
5157}
5258
53- impl LocalUseMap < ' me > {
59+ impl LocalUseMap {
5460 crate fn build (
55- liveness_map : & ' me NllLivenessMap ,
61+ live_locals : & Vec < Local > ,
5662 elements : & RegionValueElements ,
5763 mir : & Mir < ' _ > ,
5864 ) -> Self {
59- let nones = IndexVec :: from_elem_n ( None , liveness_map . num_variables ( ) ) ;
65+ let nones = IndexVec :: from_elem_n ( None , mir . local_decls . len ( ) ) ;
6066 let mut local_use_map = LocalUseMap {
61- liveness_map,
6267 first_def_at : nones. clone ( ) ,
6368 first_use_at : nones. clone ( ) ,
6469 first_drop_at : nones,
6570 appearances : IndexVec :: new ( ) ,
6671 } ;
6772
73+ let mut locals_with_use_data: IndexVec < Local , bool > =
74+ IndexVec :: from_elem_n ( false , mir. local_decls . len ( ) ) ;
75+ live_locals
76+ . iter ( )
77+ . for_each ( |& local| locals_with_use_data[ local] = true ) ;
78+
6879 LocalUseMapBuild {
6980 local_use_map : & mut local_use_map,
7081 elements,
71- } . visit_mir ( mir) ;
82+ locals_with_use_data,
83+ }
84+ . visit_mir ( mir) ;
7285
7386 local_use_map
7487 }
7588
7689 crate fn defs ( & self , local : Local ) -> impl Iterator < Item = PointIndex > + ' _ {
77- let live_var = self . liveness_map . from_local ( local) . unwrap ( ) ;
78- vll:: iter ( self . first_def_at [ live_var] , & self . appearances )
90+ vll:: iter ( self . first_def_at [ local] , & self . appearances )
7991 . map ( move |aa| self . appearances [ aa] . point_index )
8092 }
8193
8294 crate fn uses ( & self , local : Local ) -> impl Iterator < Item = PointIndex > + ' _ {
83- let live_var = self . liveness_map . from_local ( local) . unwrap ( ) ;
84- vll:: iter ( self . first_use_at [ live_var] , & self . appearances )
95+ vll:: iter ( self . first_use_at [ local] , & self . appearances )
8596 . map ( move |aa| self . appearances [ aa] . point_index )
8697 }
8798
8899 crate fn drops ( & self , local : Local ) -> impl Iterator < Item = PointIndex > + ' _ {
89- let live_var = self . liveness_map . from_local ( local) . unwrap ( ) ;
90- vll:: iter ( self . first_drop_at [ live_var] , & self . appearances )
100+ vll:: iter ( self . first_drop_at [ local] , & self . appearances )
91101 . map ( move |aa| self . appearances [ aa] . point_index )
92102 }
93103}
94104
95- struct LocalUseMapBuild < ' me , ' map : ' me > {
96- local_use_map : & ' me mut LocalUseMap < ' map > ,
105+ struct LocalUseMapBuild < ' me > {
106+ local_use_map : & ' me mut LocalUseMap ,
97107 elements : & ' me RegionValueElements ,
108+
109+ // Vector used in `visit_local` to signal which `Local`s do we need
110+ // def/use/drop information on, constructed from `live_locals` (that
111+ // contains the variables we'll do the liveness analysis for).
112+ // This vector serves optimization purposes only: we could have
113+ // obtained the same information from `live_locals` but we want to
114+ // avoid repeatedly calling `Vec::contains()` (see `LocalUseMap` for
115+ // the rationale on the time-memory trade-off we're favoring here).
116+ locals_with_use_data : IndexVec < Local , bool > ,
98117}
99118
100- impl LocalUseMapBuild < ' _ , ' _ > {
101- fn insert_def ( & mut self , local : LiveVar , location : Location ) {
119+ impl LocalUseMapBuild < ' _ > {
120+ fn insert_def ( & mut self , local : Local , location : Location ) {
102121 Self :: insert (
103122 self . elements ,
104123 & mut self . local_use_map . first_def_at [ local] ,
@@ -107,7 +126,7 @@ impl LocalUseMapBuild<'_, '_> {
107126 ) ;
108127 }
109128
110- fn insert_use ( & mut self , local : LiveVar , location : Location ) {
129+ fn insert_use ( & mut self , local : Local , location : Location ) {
111130 Self :: insert (
112131 self . elements ,
113132 & mut self . local_use_map . first_use_at [ local] ,
@@ -116,7 +135,7 @@ impl LocalUseMapBuild<'_, '_> {
116135 ) ;
117136 }
118137
119- fn insert_drop ( & mut self , local : LiveVar , location : Location ) {
138+ fn insert_drop ( & mut self , local : Local , location : Location ) {
120139 Self :: insert (
121140 self . elements ,
122141 & mut self . local_use_map . first_drop_at [ local] ,
@@ -140,13 +159,13 @@ impl LocalUseMapBuild<'_, '_> {
140159 }
141160}
142161
143- impl Visitor < ' tcx > for LocalUseMapBuild < ' _ , ' _ > {
162+ impl Visitor < ' tcx > for LocalUseMapBuild < ' _ > {
144163 fn visit_local ( & mut self , & local: & Local , context : PlaceContext < ' tcx > , location : Location ) {
145- if let Some ( local_with_region ) = self . local_use_map . liveness_map . from_local ( local) {
164+ if self . locals_with_use_data [ local] {
146165 match categorize ( context) {
147- Some ( DefUse :: Def ) => self . insert_def ( local_with_region , location) ,
148- Some ( DefUse :: Use ) => self . insert_use ( local_with_region , location) ,
149- Some ( DefUse :: Drop ) => self . insert_drop ( local_with_region , location) ,
166+ Some ( DefUse :: Def ) => self . insert_def ( local , location) ,
167+ Some ( DefUse :: Use ) => self . insert_use ( local , location) ,
168+ Some ( DefUse :: Drop ) => self . insert_drop ( local , location) ,
150169 _ => ( ) ,
151170 }
152171 }
0 commit comments