@@ -50,9 +50,13 @@ impl SmallDominators<'_> {
50
50
let assign_dominates = match * set {
51
51
Set1 :: Empty | Set1 :: Many => false ,
52
52
Set1 :: One ( LocationExtended :: Arg ) => true ,
53
- Set1 :: One ( LocationExtended :: Plain ( assign) ) => {
53
+ Set1 :: One ( LocationExtended :: Assign ( assign) ) => {
54
54
self . dominates ( assign. successor_within_block ( ) , loc)
55
55
}
56
+ Set1 :: One ( LocationExtended :: Terminator ( _, effect_bb) ) => {
57
+ let effect_loc = Location { block : effect_bb, statement_index : 0 } ;
58
+ self . dominates ( effect_loc, loc)
59
+ }
56
60
} ;
57
61
// We are visiting a use that is not dominated by an assignment.
58
62
// Either there is a cycle involved, or we are reading for uninitialized local.
@@ -73,7 +77,8 @@ impl SsaLocals {
73
77
let dominators = SmallDominators { inner : dominators } ;
74
78
75
79
let direct_uses = IndexVec :: from_elem ( 0 , & body. local_decls ) ;
76
- let mut visitor = SsaVisitor { assignments, assignment_order, dominators, direct_uses } ;
80
+ let mut visitor =
81
+ SsaVisitor { body, assignments, assignment_order, dominators, direct_uses } ;
77
82
78
83
for local in body. args_iter ( ) {
79
84
visitor. assignments [ local] = Set1 :: One ( LocationExtended :: Arg ) ;
@@ -134,12 +139,9 @@ impl SsaLocals {
134
139
body : & ' a Body < ' tcx > ,
135
140
) -> impl Iterator < Item = ( Local , & ' a Rvalue < ' tcx > , Location ) > + ' a {
136
141
self . assignment_order . iter ( ) . filter_map ( |& local| {
137
- if let Set1 :: One ( LocationExtended :: Plain ( loc) ) = self . assignments [ local]
138
- // `loc` must point to:
139
- // - a direct assignment to `local`;
140
- // - a call or a yield terminator.
141
- && let Either :: Left ( stmt) = body. stmt_at ( loc)
142
- {
142
+ if let Set1 :: One ( LocationExtended :: Assign ( loc) ) = self . assignments [ local] {
143
+ // `loc` must point to a direct assignment to `local`.
144
+ let Either :: Left ( stmt) = body. stmt_at ( loc) else { bug ! ( ) } ;
143
145
let Some ( ( target, rvalue) ) = stmt. kind . as_assign ( ) else { bug ! ( ) } ;
144
146
assert_eq ! ( target. as_local( ) , Some ( local) ) ;
145
147
Some ( ( local, rvalue, loc) )
@@ -197,18 +199,24 @@ impl SsaLocals {
197
199
198
200
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
199
201
enum LocationExtended {
200
- Plain ( Location ) ,
202
+ /// This local was assigned as a function parameter, before any execution.
201
203
Arg ,
204
+ /// `Location` points to the `Assign` statement.
205
+ Assign ( Location ) ,
206
+ /// The blocks are respectively the bb which contains the assignment,
207
+ /// and the bb in which the assignment effect is complete.
208
+ Terminator ( BasicBlock , BasicBlock ) ,
202
209
}
203
210
204
- struct SsaVisitor < ' a > {
211
+ struct SsaVisitor < ' a , ' tcx > {
212
+ body : & ' a Body < ' tcx > ,
205
213
dominators : SmallDominators < ' a > ,
206
214
assignments : IndexVec < Local , Set1 < LocationExtended > > ,
207
215
assignment_order : Vec < Local > ,
208
216
direct_uses : IndexVec < Local , u32 > ,
209
217
}
210
218
211
- impl < ' tcx > Visitor < ' tcx > for SsaVisitor < ' _ > {
219
+ impl < ' tcx > Visitor < ' tcx > for SsaVisitor < ' _ , ' tcx > {
212
220
fn visit_local ( & mut self , local : Local , ctxt : PlaceContext , loc : Location ) {
213
221
match ctxt {
214
222
PlaceContext :: MutatingUse ( MutatingUseContext :: Projection )
@@ -233,10 +241,20 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> {
233
241
}
234
242
235
243
fn visit_place ( & mut self , place : & Place < ' tcx > , ctxt : PlaceContext , loc : Location ) {
236
- if let PlaceContext :: MutatingUse ( MutatingUseContext :: Store | MutatingUseContext :: Call | MutatingUseContext :: Yield ) = ctxt
244
+ let location = match ctxt {
245
+ PlaceContext :: MutatingUse ( MutatingUseContext :: Store ) => {
246
+ Some ( LocationExtended :: Assign ( loc) )
247
+ }
248
+ PlaceContext :: MutatingUse ( MutatingUseContext :: Call | MutatingUseContext :: Yield ) => {
249
+ let target = self . body . basic_blocks [ loc. block ] . terminator ( ) . successors ( ) . next ( ) ;
250
+ target. map ( |target| LocationExtended :: Terminator ( loc. block , target) )
251
+ }
252
+ _ => None ,
253
+ } ;
254
+ if let Some ( location) = location
237
255
&& let Some ( local) = place. as_local ( )
238
256
{
239
- self . assignments [ local] . insert ( LocationExtended :: Plain ( loc ) ) ;
257
+ self . assignments [ local] . insert ( location ) ;
240
258
if let Set1 :: One ( _) = self . assignments [ local] {
241
259
// Only record if SSA-like, to avoid growing the vector needlessly.
242
260
self . assignment_order . push ( local) ;
@@ -337,7 +355,7 @@ impl StorageLiveLocals {
337
355
for ( statement_index, statement) in bbdata. statements . iter ( ) . enumerate ( ) {
338
356
if let StatementKind :: StorageLive ( local) = statement. kind {
339
357
storage_live[ local]
340
- . insert ( LocationExtended :: Plain ( Location { block, statement_index } ) ) ;
358
+ . insert ( LocationExtended :: Assign ( Location { block, statement_index } ) ) ;
341
359
}
342
360
}
343
361
}
0 commit comments