44//!
55//! As a consequence of rule 2, we consider that borrowed locals are not SSA, even if they are
66//! `Freeze`, as we do not track that the assignment dominates all uses of the borrow.
7- //!
8- //! We say a local has a stable address if its address has SSA-like properties:
9- //! 1/ It has a single `StorageLive` statement, or none at all (always-live);
10- //! 2/ This `StorageLive` statement dominates all statements that take this local's address.
11- //!
12- //! We do not discard borrowed locals from this analysis, as we cannot take their address' address.
137
148use either:: Either ;
159use rustc_data_structures:: graph:: dominators:: Dominators ;
@@ -18,7 +12,6 @@ use rustc_index::{IndexSlice, IndexVec};
1812use rustc_middle:: middle:: resolve_bound_vars:: Set1 ;
1913use rustc_middle:: mir:: visit:: * ;
2014use rustc_middle:: mir:: * ;
21- use rustc_mir_dataflow:: storage:: always_storage_live_locals;
2215
2316#[ derive( Debug ) ]
2417pub struct SsaLocals {
@@ -33,9 +26,6 @@ pub struct SsaLocals {
3326 /// Number of "direct" uses of each local, ie. uses that are not dereferences.
3427 /// We ignore non-uses (Storage statements, debuginfo).
3528 direct_uses : IndexVec < Local , u32 > ,
36- /// Set of "StorageLive" statements for each local. When the "StorageLive" statement does not
37- /// dominate all uses of the local, we mark it as `Set1::Many`.
38- storage_live : IndexVec < Local , Set1 < LocationExtended > > ,
3929}
4030
4131/// We often encounter MIR bodies with 1 or 2 basic blocks. In those cases, it's unnecessary to
@@ -83,18 +73,12 @@ impl SsaLocals {
8373 let dominators = SmallDominators { inner : dominators } ;
8474
8575 let direct_uses = IndexVec :: from_elem ( 0 , & body. local_decls ) ;
86- let storage_live = IndexVec :: from_elem ( Set1 :: Empty , & body. local_decls ) ;
87- let mut visitor =
88- SsaVisitor { assignments, assignment_order, dominators, direct_uses, storage_live } ;
76+ let mut visitor = SsaVisitor { assignments, assignment_order, dominators, direct_uses } ;
8977
9078 for local in body. args_iter ( ) {
9179 visitor. assignments [ local] = Set1 :: One ( LocationExtended :: Arg ) ;
9280 }
9381
94- for local in always_storage_live_locals ( body) . iter ( ) {
95- visitor. storage_live [ local] = Set1 :: One ( LocationExtended :: Arg ) ;
96- }
97-
9882 if body. basic_blocks . len ( ) > 2 {
9983 for ( bb, data) in traversal:: reverse_postorder ( body) {
10084 visitor. visit_basic_block_data ( bb, data) ;
@@ -111,7 +95,6 @@ impl SsaLocals {
11195
11296 debug ! ( ?visitor. assignments) ;
11397 debug ! ( ?visitor. direct_uses) ;
114- debug ! ( ?visitor. storage_live) ;
11598
11699 visitor
117100 . assignment_order
@@ -124,7 +107,6 @@ impl SsaLocals {
124107 assignments : visitor. assignments ,
125108 assignment_order : visitor. assignment_order ,
126109 direct_uses : visitor. direct_uses ,
127- storage_live : visitor. storage_live ,
128110 copy_classes,
129111 }
130112 }
@@ -141,19 +123,6 @@ impl SsaLocals {
141123 matches ! ( self . assignments[ local] , Set1 :: One ( _) )
142124 }
143125
144- /// Returns true iff we can use `p` as a pointee.
145- pub fn is_constant_place ( & self , p : Place < ' _ > ) -> bool {
146- // We only allow `Deref` as the first projection, to avoid surprises.
147- if p. projection . first ( ) == Some ( & PlaceElem :: Deref ) {
148- // `p == (*some_local).xxx`, it is constant only if `some_local` is constant.
149- // We approximate constness using SSAness.
150- self . is_ssa ( p. local ) && p. projection [ 1 ..] . iter ( ) . all ( PlaceElem :: is_stable_offset)
151- } else {
152- matches ! ( self . storage_live[ p. local] , Set1 :: One ( _) )
153- && p. projection [ ..] . iter ( ) . all ( PlaceElem :: is_stable_offset)
154- }
155- }
156-
157126 /// Return the number of uses if a local that are not "Deref".
158127 pub fn num_direct_uses ( & self , local : Local ) -> u32 {
159128 self . direct_uses [ local]
@@ -233,7 +202,6 @@ struct SsaVisitor {
233202 assignments : IndexVec < Local , Set1 < LocationExtended > > ,
234203 assignment_order : Vec < Local > ,
235204 direct_uses : IndexVec < Local , u32 > ,
236- storage_live : IndexVec < Local , Set1 < LocationExtended > > ,
237205}
238206
239207impl < ' tcx > Visitor < ' tcx > for SsaVisitor {
@@ -259,15 +227,11 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor {
259227 )
260228 | PlaceContext :: MutatingUse ( _) => {
261229 self . assignments [ local] = Set1 :: Many ;
262- self . dominators . check_dominates ( & mut self . storage_live [ local] , loc) ;
263230 }
264231 PlaceContext :: NonMutatingUse ( _) => {
265232 self . dominators . check_dominates ( & mut self . assignments [ local] , loc) ;
266233 self . direct_uses [ local] += 1 ;
267234 }
268- PlaceContext :: NonUse ( NonUseContext :: StorageLive ) => {
269- self . storage_live [ local] . insert ( LocationExtended :: Plain ( loc) ) ;
270- }
271235 PlaceContext :: NonUse ( _) => { }
272236 }
273237 }
@@ -335,3 +299,37 @@ fn compute_copy_classes(ssa: &mut SsaVisitor, body: &Body<'_>) -> IndexVec<Local
335299
336300 copies
337301}
302+
303+ #[ derive( Debug ) ]
304+ pub ( crate ) struct StorageLiveLocals {
305+ /// Set of "StorageLive" statements for each local. When the "StorageLive" statement does not
306+ /// dominate all address-taking uses of the local, we mark it as `Set1::Many`.
307+ storage_live : IndexVec < Local , Set1 < LocationExtended > > ,
308+ }
309+
310+ impl StorageLiveLocals {
311+ pub ( crate ) fn new (
312+ body : & Body < ' _ > ,
313+ always_storage_live_locals : & BitSet < Local > ,
314+ ) -> StorageLiveLocals {
315+ let mut storage_live = IndexVec :: from_elem ( Set1 :: Empty , & body. local_decls ) ;
316+ for local in always_storage_live_locals. iter ( ) {
317+ storage_live[ local] = Set1 :: One ( LocationExtended :: Arg ) ;
318+ }
319+ for ( block, bbdata) in body. basic_blocks . iter_enumerated ( ) {
320+ for ( statement_index, statement) in bbdata. statements . iter ( ) . enumerate ( ) {
321+ if let StatementKind :: StorageLive ( local) = statement. kind {
322+ storage_live[ local]
323+ . insert ( LocationExtended :: Plain ( Location { block, statement_index } ) ) ;
324+ }
325+ }
326+ }
327+ debug ! ( ?storage_live) ;
328+ StorageLiveLocals { storage_live }
329+ }
330+
331+ #[ inline]
332+ pub ( crate ) fn has_single_storage ( & self , local : Local ) -> bool {
333+ matches ! ( self . storage_live[ local] , Set1 :: One ( _) )
334+ }
335+ }
0 commit comments