@@ -101,14 +101,15 @@ impl SsaLocals {
101
101
. retain ( |& local| matches ! ( visitor. assignments[ local] , Set1 :: One ( _) ) ) ;
102
102
debug ! ( ?visitor. assignment_order) ;
103
103
104
- let copy_classes = compute_copy_classes ( & mut visitor, body) ;
105
-
106
- SsaLocals {
104
+ let mut ssa = SsaLocals {
107
105
assignments : visitor. assignments ,
108
106
assignment_order : visitor. assignment_order ,
109
107
direct_uses : visitor. direct_uses ,
110
- copy_classes,
111
- }
108
+ // This is filled by `compute_copy_classes`.
109
+ copy_classes : IndexVec :: default ( ) ,
110
+ } ;
111
+ compute_copy_classes ( & mut ssa, body) ;
112
+ ssa
112
113
}
113
114
114
115
pub fn num_locals ( & self ) -> usize {
@@ -261,49 +262,54 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor {
261
262
}
262
263
263
264
#[ instrument( level = "trace" , skip( ssa, body) ) ]
264
- fn compute_copy_classes ( ssa : & mut SsaVisitor , body : & Body < ' _ > ) -> IndexVec < Local , Local > {
265
+ fn compute_copy_classes ( ssa : & mut SsaLocals , body : & Body < ' _ > ) {
266
+ let mut direct_uses = std:: mem:: take ( & mut ssa. direct_uses ) ;
265
267
let mut copies = IndexVec :: from_fn_n ( |l| l, body. local_decls . len ( ) ) ;
266
268
267
- for & local in & ssa. assignment_order {
268
- debug ! ( ?local) ;
269
-
270
- if local == RETURN_PLACE {
271
- // `_0` is special, we cannot rename it.
272
- continue ;
273
- }
274
-
275
- // This is not SSA: mark that we don't know the value.
276
- debug ! ( assignments = ?ssa. assignments[ local] ) ;
277
- let Set1 :: One ( LocationExtended :: Plain ( loc) ) = ssa. assignments [ local] else { continue } ;
278
-
279
- // `loc` must point to a direct assignment to `local`.
280
- let Either :: Left ( stmt) = body. stmt_at ( loc) else { bug ! ( ) } ;
281
- let Some ( ( _target, rvalue) ) = stmt. kind . as_assign ( ) else { bug ! ( ) } ;
282
- assert_eq ! ( _target. as_local( ) , Some ( local) ) ;
283
-
269
+ for ( local, rvalue, _) in ssa. assignments ( body) {
284
270
let ( Rvalue :: Use ( Operand :: Copy ( place) | Operand :: Move ( place) ) | Rvalue :: CopyForDeref ( place) )
285
271
= rvalue
286
272
else { continue } ;
287
273
288
274
let Some ( rhs) = place. as_local ( ) else { continue } ;
289
- let Set1 :: One ( _) = ssa. assignments [ rhs] else { continue } ;
275
+ if !ssa. is_ssa ( rhs) {
276
+ continue ;
277
+ }
290
278
291
279
// We visit in `assignment_order`, ie. reverse post-order, so `rhs` has been
292
280
// visited before `local`, and we just have to copy the representing local.
293
- copies[ local] = copies[ rhs] ;
294
- ssa. direct_uses [ rhs] -= 1 ;
281
+ let head = copies[ rhs] ;
282
+
283
+ if local == RETURN_PLACE {
284
+ // `_0` is special, we cannot rename it. Instead, rename the class of `rhs` to
285
+ // `RETURN_PLACE`. This is only possible if the class head is a temporary, not an
286
+ // argument.
287
+ if body. local_kind ( head) != LocalKind :: Temp {
288
+ continue ;
289
+ }
290
+ for h in copies. iter_mut ( ) {
291
+ if * h == head {
292
+ * h = RETURN_PLACE ;
293
+ }
294
+ }
295
+ } else {
296
+ copies[ local] = head;
297
+ }
298
+ direct_uses[ rhs] -= 1 ;
295
299
}
296
300
297
301
debug ! ( ?copies) ;
298
- debug ! ( ?ssa . direct_uses) ;
302
+ debug ! ( ?direct_uses) ;
299
303
300
304
// Invariant: `copies` must point to the head of an equivalence class.
301
305
#[ cfg( debug_assertions) ]
302
306
for & head in copies. iter ( ) {
303
307
assert_eq ! ( copies[ head] , head) ;
304
308
}
309
+ debug_assert_eq ! ( copies[ RETURN_PLACE ] , RETURN_PLACE ) ;
305
310
306
- copies
311
+ ssa. direct_uses = direct_uses;
312
+ ssa. copy_classes = copies;
307
313
}
308
314
309
315
#[ derive( Debug ) ]
0 commit comments