@@ -101,14 +101,15 @@ impl SsaLocals {
101101 . retain ( |& local| matches ! ( visitor. assignments[ local] , Set1 :: One ( _) ) ) ;
102102 debug ! ( ?visitor. assignment_order) ;
103103
104- let copy_classes = compute_copy_classes ( & mut visitor, body) ;
105-
106- SsaLocals {
104+ let mut ssa = SsaLocals {
107105 assignments : visitor. assignments ,
108106 assignment_order : visitor. assignment_order ,
109107 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
112113 }
113114
114115 pub fn num_locals ( & self ) -> usize {
@@ -261,27 +262,19 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor {
261262}
262263
263264#[ 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 ) ;
265267 let mut copies = IndexVec :: from_fn_n ( |l| l, body. local_decls . len ( ) ) ;
266268
267- for & local in & ssa. assignment_order {
268- debug ! ( ?local) ;
269-
270- // This is not SSA: mark that we don't know the value.
271- debug ! ( assignments = ?ssa. assignments[ local] ) ;
272- let Set1 :: One ( LocationExtended :: Plain ( loc) ) = ssa. assignments [ local] else { continue } ;
273-
274- // `loc` must point to a direct assignment to `local`.
275- let Either :: Left ( stmt) = body. stmt_at ( loc) else { bug ! ( ) } ;
276- let Some ( ( _target, rvalue) ) = stmt. kind . as_assign ( ) else { bug ! ( ) } ;
277- assert_eq ! ( _target. as_local( ) , Some ( local) ) ;
278-
269+ for ( local, rvalue, _) in ssa. assignments ( body) {
279270 let ( Rvalue :: Use ( Operand :: Copy ( place) | Operand :: Move ( place) ) | Rvalue :: CopyForDeref ( place) )
280271 = rvalue
281272 else { continue } ;
282273
283274 let Some ( rhs) = place. as_local ( ) else { continue } ;
284- let Set1 :: One ( _) = ssa. assignments [ rhs] else { continue } ;
275+ if !ssa. is_ssa ( rhs) {
276+ continue ;
277+ }
285278
286279 // We visit in `assignment_order`, ie. reverse post-order, so `rhs` has been
287280 // visited before `local`, and we just have to copy the representing local.
@@ -302,11 +295,11 @@ fn compute_copy_classes(ssa: &mut SsaVisitor, body: &Body<'_>) -> IndexVec<Local
302295 } else {
303296 copies[ local] = head;
304297 }
305- ssa . direct_uses [ rhs] -= 1 ;
298+ direct_uses[ rhs] -= 1 ;
306299 }
307300
308301 debug ! ( ?copies) ;
309- debug ! ( ?ssa . direct_uses) ;
302+ debug ! ( ?direct_uses) ;
310303
311304 // Invariant: `copies` must point to the head of an equivalence class.
312305 #[ cfg( debug_assertions) ]
@@ -315,7 +308,8 @@ fn compute_copy_classes(ssa: &mut SsaVisitor, body: &Body<'_>) -> IndexVec<Local
315308 }
316309 debug_assert_eq ! ( copies[ RETURN_PLACE ] , RETURN_PLACE ) ;
317310
318- copies
311+ ssa. direct_uses = direct_uses;
312+ ssa. copy_classes = copies;
319313}
320314
321315#[ derive( Debug ) ]
0 commit comments