@@ -364,7 +364,9 @@ struct VnState<'body, 'a, 'tcx> {
364364 local_decls : & ' body LocalDecls < ' tcx > ,
365365 is_coroutine : bool ,
366366 /// Value stored in each local.
367- locals : IndexVec < Local , Option < VnIndex > > ,
367+ locals_ssa : FxHashMap < Local , VnIndex > ,
368+ // Keep two separate maps to efficiently clear non-SSA locals.
369+ locals_non_ssa : FxHashMap < Local , VnIndex > ,
368370 /// Locals that are assigned that value.
369371 // This vector holds the locals that are SSA.
370372 rev_locals_ssa : IndexVec < VnIndex , SmallVec < [ Local ; 1 ] > > ,
@@ -404,7 +406,11 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
404406 ecx : InterpCx :: new ( tcx, DUMMY_SP , typing_env, DummyMachine ) ,
405407 local_decls,
406408 is_coroutine : body. coroutine . is_some ( ) ,
407- locals : IndexVec :: from_elem ( None , local_decls) ,
409+ locals_ssa : FxHashMap :: with_capacity_and_hasher ( local_decls. len ( ) , Default :: default ( ) ) ,
410+ locals_non_ssa : FxHashMap :: with_capacity_and_hasher (
411+ local_decls. len ( ) ,
412+ Default :: default ( ) ,
413+ ) ,
408414 rev_locals_ssa : IndexVec :: with_capacity ( num_values) ,
409415 rev_locals_non_ssa : FxHashMap :: default ( ) ,
410416 values : ValueSet :: new ( num_values) ,
@@ -527,22 +533,28 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
527533 /// Record that `local` is assigned `value`.
528534 #[ instrument( level = "trace" , skip( self ) ) ]
529535 fn assign ( & mut self , local : Local , value : VnIndex ) {
530- self . locals [ local] = Some ( value) ;
531536 if self . ssa . is_ssa ( local) {
537+ self . locals_ssa . insert ( local, value) ;
532538 self . rev_locals_ssa [ value] . push ( local) ;
533539 } else {
540+ self . locals_non_ssa . insert ( local, value) ;
534541 self . rev_locals_non_ssa . entry ( value) . or_default ( ) . push ( local) ;
535542 }
536543 }
537544
538545 /// Return the value assigned to a local, or assign an opaque value and return it.
539546 #[ instrument( level = "trace" , skip( self ) , ret) ]
540547 fn local ( & mut self , local : Local ) -> VnIndex {
541- if let Some ( value) = self . locals [ local] {
542- return value;
548+ if let Some ( value) = self . locals_ssa . get ( & local) {
549+ return * value;
550+ }
551+ if let Some ( value) = self . locals_non_ssa . get ( & local) {
552+ return * value;
543553 }
544554 let value = self . new_opaque ( self . local_decls [ local] . ty ) ;
545- self . locals [ local] = Some ( value) ;
555+ // For SSA locals, the assignment dominates all uses.
556+ // If we are here, this means the locals is not SSA.
557+ self . locals_non_ssa . insert ( local, value) ;
546558 self . rev_locals_non_ssa . entry ( value) . or_default ( ) . push ( local) ;
547559 value
548560 }
@@ -553,7 +565,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
553565 if this. ssa . is_ssa ( local) {
554566 return ;
555567 }
556- if let Some ( value) = this. locals [ local ] . take ( ) {
568+ if let Some ( value) = this. locals_non_ssa . remove ( & local ) {
557569 this. rev_locals_non_ssa . entry ( value) . or_default ( ) . retain ( |l| * l != local) ;
558570 }
559571 } ;
@@ -1879,12 +1891,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> {
18791891 }
18801892
18811893 fn visit_basic_block_data ( & mut self , block : BasicBlock , bbdata : & mut BasicBlockData < ' tcx > ) {
1894+ self . locals_non_ssa . clear ( ) ;
18821895 self . rev_locals_non_ssa . clear ( ) ;
1883- for local in self . locals . indices ( ) {
1884- if !self . ssa . is_ssa ( local) {
1885- self . locals [ local] = None ;
1886- }
1887- }
18881896 self . super_basic_block_data ( block, bbdata) ;
18891897 }
18901898
0 commit comments