@@ -364,7 +364,9 @@ struct VnState<'body, 'a, 'tcx> {
364
364
local_decls : & ' body LocalDecls < ' tcx > ,
365
365
is_coroutine : bool ,
366
366
/// 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 > ,
368
370
/// Locals that are assigned that value.
369
371
// This vector holds the locals that are SSA.
370
372
rev_locals_ssa : IndexVec < VnIndex , SmallVec < [ Local ; 1 ] > > ,
@@ -404,7 +406,11 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
404
406
ecx : InterpCx :: new ( tcx, DUMMY_SP , typing_env, DummyMachine ) ,
405
407
local_decls,
406
408
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
+ ) ,
408
414
rev_locals_ssa : IndexVec :: with_capacity ( num_values) ,
409
415
rev_locals_non_ssa : FxHashMap :: default ( ) ,
410
416
values : ValueSet :: new ( num_values) ,
@@ -527,22 +533,28 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
527
533
/// Record that `local` is assigned `value`.
528
534
#[ instrument( level = "trace" , skip( self ) ) ]
529
535
fn assign ( & mut self , local : Local , value : VnIndex ) {
530
- self . locals [ local] = Some ( value) ;
531
536
if self . ssa . is_ssa ( local) {
537
+ self . locals_ssa . insert ( local, value) ;
532
538
self . rev_locals_ssa [ value] . push ( local) ;
533
539
} else {
540
+ self . locals_non_ssa . insert ( local, value) ;
534
541
self . rev_locals_non_ssa . entry ( value) . or_default ( ) . push ( local) ;
535
542
}
536
543
}
537
544
538
545
/// Return the value assigned to a local, or assign an opaque value and return it.
539
546
#[ instrument( level = "trace" , skip( self ) , ret) ]
540
547
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;
543
553
}
544
554
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) ;
546
558
self . rev_locals_non_ssa . entry ( value) . or_default ( ) . push ( local) ;
547
559
value
548
560
}
@@ -553,7 +565,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
553
565
if this. ssa . is_ssa ( local) {
554
566
return ;
555
567
}
556
- if let Some ( value) = this. locals [ local ] . take ( ) {
568
+ if let Some ( value) = this. locals_non_ssa . remove ( & local ) {
557
569
this. rev_locals_non_ssa . entry ( value) . or_default ( ) . retain ( |l| * l != local) ;
558
570
}
559
571
} ;
@@ -1879,12 +1891,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> {
1879
1891
}
1880
1892
1881
1893
fn visit_basic_block_data ( & mut self , block : BasicBlock , bbdata : & mut BasicBlockData < ' tcx > ) {
1894
+ self . locals_non_ssa . clear ( ) ;
1882
1895
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
- }
1888
1896
self . super_basic_block_data ( block, bbdata) ;
1889
1897
}
1890
1898
0 commit comments