@@ -94,7 +94,7 @@ use rustc_const_eval::interpret::{
94
94
ImmTy , Immediate , InterpCx , MemPlaceMeta , MemoryKind , OpTy , Projectable , Scalar ,
95
95
intern_const_alloc_for_constprop,
96
96
} ;
97
- use rustc_data_structures:: fx:: { FxIndexSet , MutableValues } ;
97
+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexSet , MutableValues } ;
98
98
use rustc_data_structures:: graph:: dominators:: Dominators ;
99
99
use rustc_hir:: def:: DefKind ;
100
100
use rustc_index:: bit_set:: DenseBitSet ;
@@ -229,8 +229,10 @@ struct VnState<'body, 'a, 'tcx> {
229
229
/// Value stored in each local.
230
230
locals : IndexVec < Local , VnIndex > ,
231
231
/// 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 ] > > ,
234
236
values : FxIndexSet < ( Value < ' a , ' tcx > , Ty < ' tcx > ) > ,
235
237
/// Values evaluated as constants if possible.
236
238
evaluated : IndexVec < VnIndex , Option < OpTy < ' tcx > > > ,
@@ -267,7 +269,8 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
267
269
local_decls,
268
270
is_coroutine : body. coroutine . is_some ( ) ,
269
271
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 ( ) ,
271
274
values : FxIndexSet :: with_capacity_and_hasher ( num_values, Default :: default ( ) ) ,
272
275
evaluated : IndexVec :: with_capacity ( num_values) ,
273
276
next_opaque : 1 ,
@@ -281,7 +284,11 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
281
284
for decl in body. local_decls . iter ( ) {
282
285
let value = this. new_opaque ( decl. ty ) ;
283
286
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
+ }
285
292
}
286
293
this
287
294
}
@@ -299,7 +306,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
299
306
let evaluated = self . eval_to_const ( index) ;
300
307
let _index = self . evaluated . push ( evaluated) ;
301
308
debug_assert_eq ! ( index, _index) ;
302
- let _index = self . rev_locals . push ( SmallVec :: new ( ) ) ;
309
+ let _index = self . rev_locals_ssa . push ( Default :: default ( ) ) ;
303
310
debug_assert_eq ! ( index, _index) ;
304
311
}
305
312
index
@@ -370,7 +377,11 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
370
377
#[ instrument( level = "trace" , skip( self ) ) ]
371
378
fn assign ( & mut self , local : Local , value : VnIndex , loc : Location ) {
372
379
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
+ }
374
385
}
375
386
376
387
#[ instrument( level = "trace" , skip( self ) ) ]
@@ -380,11 +391,11 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
380
391
return ;
381
392
}
382
393
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) ;
384
395
this. locals [ local] = this. new_opaque ( this. ty ( value) ) ;
385
396
#[ 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 {
388
399
debug_assert_ne ! ( * other, local) ;
389
400
}
390
401
}
@@ -1769,9 +1780,10 @@ impl<'tcx> VnState<'_, '_, 'tcx> {
1769
1780
/// return it. If you used this local, add it to `reused_locals` to remove storage statements.
1770
1781
#[ instrument( level = "trace" , skip( self ) , ret) ]
1771
1782
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 ( ) )
1775
1787
. find ( |& & ( other, assign_loc) | {
1776
1788
self . ssa . assignment_dominates ( & self . dominators , other, loc)
1777
1789
|| ( assign_loc. block == loc. block
@@ -1787,15 +1799,16 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> {
1787
1799
}
1788
1800
1789
1801
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 ( ) ;
1793
1803
for local in self . locals . indices ( ) {
1794
1804
if !self . ssa . is_ssa ( local) {
1795
1805
let current = self . locals [ local] ;
1796
1806
let new = self . new_opaque ( self . ty ( current) ) ;
1797
1807
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 } ) ) ;
1799
1812
}
1800
1813
}
1801
1814
self . super_basic_block_data ( block, bbdata) ;
0 commit comments