4
4
//!
5
5
//! As a consequence of rule 2, we consider that borrowed locals are not SSA, even if they are
6
6
//! `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.
13
7
14
8
use either:: Either ;
15
9
use rustc_data_structures:: graph:: dominators:: Dominators ;
@@ -18,7 +12,6 @@ use rustc_index::{IndexSlice, IndexVec};
18
12
use rustc_middle:: middle:: resolve_bound_vars:: Set1 ;
19
13
use rustc_middle:: mir:: visit:: * ;
20
14
use rustc_middle:: mir:: * ;
21
- use rustc_mir_dataflow:: storage:: always_storage_live_locals;
22
15
23
16
#[ derive( Debug ) ]
24
17
pub struct SsaLocals {
@@ -33,9 +26,6 @@ pub struct SsaLocals {
33
26
/// Number of "direct" uses of each local, ie. uses that are not dereferences.
34
27
/// We ignore non-uses (Storage statements, debuginfo).
35
28
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 > > ,
39
29
}
40
30
41
31
/// We often encounter MIR bodies with 1 or 2 basic blocks. In those cases, it's unnecessary to
@@ -83,18 +73,12 @@ impl SsaLocals {
83
73
let dominators = SmallDominators { inner : dominators } ;
84
74
85
75
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 } ;
89
77
90
78
for local in body. args_iter ( ) {
91
79
visitor. assignments [ local] = Set1 :: One ( LocationExtended :: Arg ) ;
92
80
}
93
81
94
- for local in always_storage_live_locals ( body) . iter ( ) {
95
- visitor. storage_live [ local] = Set1 :: One ( LocationExtended :: Arg ) ;
96
- }
97
-
98
82
if body. basic_blocks . len ( ) > 2 {
99
83
for ( bb, data) in traversal:: reverse_postorder ( body) {
100
84
visitor. visit_basic_block_data ( bb, data) ;
@@ -111,7 +95,6 @@ impl SsaLocals {
111
95
112
96
debug ! ( ?visitor. assignments) ;
113
97
debug ! ( ?visitor. direct_uses) ;
114
- debug ! ( ?visitor. storage_live) ;
115
98
116
99
visitor
117
100
. assignment_order
@@ -124,7 +107,6 @@ impl SsaLocals {
124
107
assignments : visitor. assignments ,
125
108
assignment_order : visitor. assignment_order ,
126
109
direct_uses : visitor. direct_uses ,
127
- storage_live : visitor. storage_live ,
128
110
copy_classes,
129
111
}
130
112
}
@@ -141,19 +123,6 @@ impl SsaLocals {
141
123
matches ! ( self . assignments[ local] , Set1 :: One ( _) )
142
124
}
143
125
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
-
157
126
/// Return the number of uses if a local that are not "Deref".
158
127
pub fn num_direct_uses ( & self , local : Local ) -> u32 {
159
128
self . direct_uses [ local]
@@ -233,7 +202,6 @@ struct SsaVisitor {
233
202
assignments : IndexVec < Local , Set1 < LocationExtended > > ,
234
203
assignment_order : Vec < Local > ,
235
204
direct_uses : IndexVec < Local , u32 > ,
236
- storage_live : IndexVec < Local , Set1 < LocationExtended > > ,
237
205
}
238
206
239
207
impl < ' tcx > Visitor < ' tcx > for SsaVisitor {
@@ -259,15 +227,11 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor {
259
227
)
260
228
| PlaceContext :: MutatingUse ( _) => {
261
229
self . assignments [ local] = Set1 :: Many ;
262
- self . dominators . check_dominates ( & mut self . storage_live [ local] , loc) ;
263
230
}
264
231
PlaceContext :: NonMutatingUse ( _) => {
265
232
self . dominators . check_dominates ( & mut self . assignments [ local] , loc) ;
266
233
self . direct_uses [ local] += 1 ;
267
234
}
268
- PlaceContext :: NonUse ( NonUseContext :: StorageLive ) => {
269
- self . storage_live [ local] . insert ( LocationExtended :: Plain ( loc) ) ;
270
- }
271
235
PlaceContext :: NonUse ( _) => { }
272
236
}
273
237
}
@@ -335,3 +299,37 @@ fn compute_copy_classes(ssa: &mut SsaVisitor, body: &Body<'_>) -> IndexVec<Local
335
299
336
300
copies
337
301
}
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