@@ -94,7 +94,7 @@ use rustc_const_eval::interpret::{
9494 ImmTy , Immediate , InterpCx , MemPlaceMeta , MemoryKind , OpTy , Projectable , Scalar ,
9595 intern_const_alloc_for_constprop,
9696} ;
97- use rustc_data_structures:: fx:: { FxIndexSet , MutableValues } ;
97+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexSet , MutableValues } ;
9898use rustc_data_structures:: graph:: dominators:: Dominators ;
9999use rustc_hir:: def:: DefKind ;
100100use rustc_index:: bit_set:: DenseBitSet ;
@@ -229,8 +229,10 @@ struct VnState<'body, 'a, 'tcx> {
229229 /// Value stored in each local.
230230 locals : IndexVec < Local , VnIndex > ,
231231 /// Locals that are assigned that value.
232- // This vector does not hold all the values of `VnIndex` that we create.
233- rev_locals : IndexVec < VnIndex , SmallVec < [ ( Local , Location ) ; 1 ] > > ,
232+ // This vector holds the locals that are SSA.
233+ rev_locals_ssa : IndexVec < VnIndex , SmallVec < [ ( Local , Location ) ; 1 ] > > ,
234+ // This vector holds the locals that are not SSA.
235+ rev_locals_non_ssa : FxHashMap < VnIndex , SmallVec < [ ( Local , Location ) ; 1 ] > > ,
234236 values : FxIndexSet < ( Value < ' a , ' tcx > , Ty < ' tcx > ) > ,
235237 /// Values evaluated as constants if possible.
236238 evaluated : IndexVec < VnIndex , Option < OpTy < ' tcx > > > ,
@@ -267,7 +269,8 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
267269 local_decls,
268270 is_coroutine : body. coroutine . is_some ( ) ,
269271 locals : IndexVec :: with_capacity ( body. local_decls . len ( ) ) ,
270- rev_locals : IndexVec :: with_capacity ( num_values) ,
272+ rev_locals_ssa : IndexVec :: with_capacity ( num_values) ,
273+ rev_locals_non_ssa : FxHashMap :: default ( ) ,
271274 values : FxIndexSet :: with_capacity_and_hasher ( num_values, Default :: default ( ) ) ,
272275 evaluated : IndexVec :: with_capacity ( num_values) ,
273276 next_opaque : 1 ,
@@ -281,7 +284,11 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
281284 for decl in body. local_decls . iter ( ) {
282285 let value = this. new_opaque ( decl. ty ) ;
283286 let local = this. locals . push ( value) ;
284- this. rev_locals [ value] . push ( ( local, init_loc) ) ;
287+ if ssa. is_ssa ( local) {
288+ this. rev_locals_ssa [ value] . push ( ( local, init_loc) ) ;
289+ } else {
290+ this. rev_locals_non_ssa . entry ( value) . or_default ( ) . push ( ( local, init_loc) ) ;
291+ }
285292 }
286293 this
287294 }
@@ -299,7 +306,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
299306 let evaluated = self . eval_to_const ( index) ;
300307 let _index = self . evaluated . push ( evaluated) ;
301308 debug_assert_eq ! ( index, _index) ;
302- let _index = self . rev_locals . push ( SmallVec :: new ( ) ) ;
309+ let _index = self . rev_locals_ssa . push ( Default :: default ( ) ) ;
303310 debug_assert_eq ! ( index, _index) ;
304311 }
305312 index
@@ -370,7 +377,11 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
370377 #[ instrument( level = "trace" , skip( self ) ) ]
371378 fn assign ( & mut self , local : Local , value : VnIndex , loc : Location ) {
372379 self . locals [ local] = value;
373- self . rev_locals [ value] . push ( ( local, loc) ) ;
380+ if self . ssa . is_ssa ( local) {
381+ self . rev_locals_ssa [ value] . push ( ( local, loc) ) ;
382+ } else {
383+ self . rev_locals_non_ssa . entry ( value) . or_default ( ) . push ( ( local, loc) ) ;
384+ }
374385 }
375386
376387 #[ instrument( level = "trace" , skip( self ) ) ]
@@ -380,11 +391,11 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
380391 return ;
381392 }
382393 let value = this. locals [ local] ;
383- this. rev_locals [ value] . retain ( |( l, _) | * l != local) ;
394+ this. rev_locals_non_ssa . entry ( value) . or_default ( ) . retain ( |( l, _) | * l != local) ;
384395 this. locals [ local] = this. new_opaque ( this. ty ( value) ) ;
385396 #[ cfg( debug_assertions) ]
386- for local_vec in this. rev_locals . iter ( ) {
387- for ( other, _) in local_vec {
397+ for local_vec in this. rev_locals_non_ssa . iter ( ) {
398+ for ( other, _) in local_vec. non_ssa {
388399 debug_assert_ne ! ( * other, local) ;
389400 }
390401 }
@@ -1769,9 +1780,10 @@ impl<'tcx> VnState<'_, '_, 'tcx> {
17691780 /// return it. If you used this local, add it to `reused_locals` to remove storage statements.
17701781 #[ instrument( level = "trace" , skip( self ) , ret) ]
17711782 fn try_as_local ( & mut self , index : VnIndex , loc : Location ) -> Option < Local > {
1772- let other = self . rev_locals . get ( index) ?;
1773- other
1774- . iter ( )
1783+ let ssa = self . rev_locals_ssa . get ( index) ?;
1784+ let non_ssa = self . rev_locals_non_ssa . entry ( index) . or_default ( ) ;
1785+ ssa. iter ( )
1786+ . chain ( non_ssa. iter ( ) )
17751787 . find ( |& & ( other, assign_loc) | {
17761788 self . ssa . assignment_dominates ( & self . dominators , other, loc)
17771789 || ( assign_loc. block == loc. block
@@ -1787,15 +1799,16 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> {
17871799 }
17881800
17891801 fn visit_basic_block_data ( & mut self , block : BasicBlock , bbdata : & mut BasicBlockData < ' tcx > ) {
1790- for local_set in self . rev_locals . iter_mut ( ) {
1791- local_set. retain ( |( local, _) | self . ssa . is_ssa ( * local) ) ;
1792- }
1802+ self . rev_locals_non_ssa . clear ( ) ;
17931803 for local in self . locals . indices ( ) {
17941804 if !self . ssa . is_ssa ( local) {
17951805 let current = self . locals [ local] ;
17961806 let new = self . new_opaque ( self . ty ( current) ) ;
17971807 self . locals [ local] = new;
1798- self . rev_locals [ new] . push ( ( local, Location { block, statement_index : 0 } ) ) ;
1808+ self . rev_locals_non_ssa
1809+ . entry ( new)
1810+ . or_default ( )
1811+ . push ( ( local, Location { block, statement_index : 0 } ) ) ;
17991812 }
18001813 }
18011814 self . super_basic_block_data ( block, bbdata) ;
0 commit comments