8585//! that contain `AllocId`s.
8686
8787use std:: borrow:: Cow ;
88+ use std:: hash:: { Hash , Hasher } ;
8889
8990use either:: Either ;
91+ use hashbrown:: hash_table:: { Entry , HashTable } ;
9092use rustc_abi:: { self as abi, BackendRepr , FIRST_VARIANT , FieldIdx , Primitive , Size , VariantIdx } ;
9193use rustc_const_eval:: const_eval:: DummyMachine ;
9294use rustc_const_eval:: interpret:: {
9395 ImmTy , Immediate , InterpCx , MemPlaceMeta , MemoryKind , OpTy , Projectable , Scalar ,
9496 intern_const_alloc_for_constprop,
9597} ;
96- use rustc_data_structures:: fx:: { FxIndexSet , MutableValues } ;
98+ use rustc_data_structures:: fx:: FxHasher ;
9799use rustc_data_structures:: graph:: dominators:: Dominators ;
98100use rustc_hir:: def:: DefKind ;
99101use rustc_index:: bit_set:: DenseBitSet ;
@@ -212,6 +214,78 @@ enum Value<'tcx> {
212214 } ,
213215}
214216
217+ struct ValueSet < ' tcx > {
218+ indices : HashTable < VnIndex > ,
219+ hashes : IndexVec < VnIndex , u64 > ,
220+ values : IndexVec < VnIndex , Value < ' tcx > > ,
221+ types : IndexVec < VnIndex , Ty < ' tcx > > ,
222+ /// Counter to generate different values.
223+ next_opaque : usize ,
224+ }
225+
226+ impl < ' tcx > ValueSet < ' tcx > {
227+ fn new ( num_values : usize ) -> ValueSet < ' tcx > {
228+ ValueSet {
229+ indices : HashTable :: with_capacity ( num_values) ,
230+ hashes : IndexVec :: with_capacity ( num_values) ,
231+ values : IndexVec :: with_capacity ( num_values) ,
232+ types : IndexVec :: with_capacity ( num_values) ,
233+ next_opaque : 1 ,
234+ }
235+ }
236+
237+ #[ allow( rustc:: pass_by_value) ]
238+ fn insert ( & mut self , value : Value < ' tcx > , ty : Ty < ' tcx > ) -> ( VnIndex , bool ) {
239+ let hash: u64 = {
240+ let mut h = FxHasher :: default ( ) ;
241+ value. hash ( & mut h) ;
242+ ty. hash ( & mut h) ;
243+ h. finish ( )
244+ } ;
245+
246+ let eq = |index : & VnIndex | self . values [ * index] == value && self . types [ * index] == ty;
247+ let hasher = |index : & VnIndex | self . hashes [ * index] ;
248+ match self . indices . entry ( hash, eq, hasher) {
249+ Entry :: Occupied ( entry) => {
250+ let index = * entry. get ( ) ;
251+ ( index, false )
252+ }
253+ Entry :: Vacant ( entry) => {
254+ let index = self . hashes . push ( hash) ;
255+ entry. insert ( index) ;
256+ let _index = self . values . push ( value) ;
257+ debug_assert_eq ! ( index, _index) ;
258+ let _index = self . types . push ( ty) ;
259+ debug_assert_eq ! ( index, _index) ;
260+ ( index, true )
261+ }
262+ }
263+ }
264+
265+ #[ inline]
266+ fn next_opaque ( & mut self ) -> usize {
267+ let next_opaque = self . next_opaque ;
268+ self . next_opaque += 1 ;
269+ next_opaque
270+ }
271+
272+ #[ inline]
273+ fn value ( & self , index : VnIndex ) -> & Value < ' tcx > {
274+ & self . values [ index]
275+ }
276+
277+ #[ inline]
278+ fn ty ( & self , index : VnIndex ) -> Ty < ' tcx > {
279+ self . types [ index]
280+ }
281+
282+ #[ inline]
283+ fn forget ( & mut self , index : VnIndex ) {
284+ let opaque = self . next_opaque ( ) ;
285+ self . values [ index] = Value :: Opaque ( opaque) ;
286+ }
287+ }
288+
215289struct VnState < ' body , ' tcx > {
216290 tcx : TyCtxt < ' tcx > ,
217291 ecx : InterpCx < ' tcx , DummyMachine > ,
@@ -222,11 +296,9 @@ struct VnState<'body, 'tcx> {
222296 /// Locals that are assigned that value.
223297 // This vector does not hold all the values of `VnIndex` that we create.
224298 rev_locals : IndexVec < VnIndex , SmallVec < [ Local ; 1 ] > > ,
225- values : FxIndexSet < ( Value < ' tcx > , Ty < ' tcx > ) > ,
299+ values : ValueSet < ' tcx > ,
226300 /// Values evaluated as constants if possible.
227301 evaluated : IndexVec < VnIndex , Option < OpTy < ' tcx > > > ,
228- /// Counter to generate different values.
229- next_opaque : usize ,
230302 /// Cache the deref values.
231303 derefs : Vec < VnIndex > ,
232304 ssa : & ' body SsaLocals ,
@@ -257,9 +329,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
257329 is_coroutine : body. coroutine . is_some ( ) ,
258330 locals : IndexVec :: from_elem ( None , local_decls) ,
259331 rev_locals : IndexVec :: with_capacity ( num_values) ,
260- values : FxIndexSet :: with_capacity_and_hasher ( num_values, Default :: default ( ) ) ,
332+ values : ValueSet :: new ( num_values) ,
261333 evaluated : IndexVec :: with_capacity ( num_values) ,
262- next_opaque : 1 ,
263334 derefs : Vec :: new ( ) ,
264335 ssa,
265336 dominators,
@@ -273,8 +344,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
273344
274345 #[ instrument( level = "trace" , skip( self ) , ret) ]
275346 fn insert ( & mut self , ty : Ty < ' tcx > , value : Value < ' tcx > ) -> VnIndex {
276- let ( index, new) = self . values . insert_full ( ( value, ty) ) ;
277- let index = VnIndex :: from_usize ( index) ;
347+ let ( index, new) = self . values . insert ( value, ty) ;
278348 if new {
279349 // Grow `evaluated` and `rev_locals` here to amortize the allocations.
280350 let evaluated = self . eval_to_const ( index) ;
@@ -286,17 +356,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
286356 index
287357 }
288358
289- fn next_opaque ( & mut self ) -> usize {
290- let next_opaque = self . next_opaque ;
291- self . next_opaque += 1 ;
292- next_opaque
293- }
294-
295359 /// Create a new `Value` for which we have no information at all, except that it is distinct
296360 /// from all the others.
297361 #[ instrument( level = "trace" , skip( self ) , ret) ]
298362 fn new_opaque ( & mut self , ty : Ty < ' tcx > ) -> VnIndex {
299- let value = Value :: Opaque ( self . next_opaque ( ) ) ;
363+ let value = Value :: Opaque ( self . values . next_opaque ( ) ) ;
300364 self . insert ( ty, value)
301365 }
302366
@@ -310,18 +374,18 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
310374 }
311375 AddressKind :: Address ( mutbl) => Ty :: new_ptr ( self . tcx , pty, mutbl. to_mutbl_lossy ( ) ) ,
312376 } ;
313- let value = Value :: Address { place, kind, provenance : self . next_opaque ( ) } ;
377+ let value = Value :: Address { place, kind, provenance : self . values . next_opaque ( ) } ;
314378 self . insert ( ty, value)
315379 }
316380
317381 #[ inline]
318382 fn get ( & self , index : VnIndex ) -> & Value < ' tcx > {
319- & self . values . get_index ( index. as_usize ( ) ) . unwrap ( ) . 0
383+ self . values . value ( index)
320384 }
321385
322386 #[ inline]
323387 fn ty ( & self , index : VnIndex ) -> Ty < ' tcx > {
324- self . values . get_index ( index. as_usize ( ) ) . unwrap ( ) . 1
388+ self . values . ty ( index)
325389 }
326390
327391 /// Record that `local` is assigned `value`. `local` must be SSA.
@@ -339,7 +403,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
339403 } else {
340404 // Multiple mentions of this constant will yield different values,
341405 // so assign a different `disambiguator` to ensure they do not get the same `VnIndex`.
342- let disambiguator = self . next_opaque ( ) ;
406+ let disambiguator = self . values . next_opaque ( ) ;
343407 // `disambiguator: 0` means deterministic.
344408 debug_assert_ne ! ( disambiguator, 0 ) ;
345409 disambiguator
@@ -373,8 +437,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
373437
374438 fn invalidate_derefs ( & mut self ) {
375439 for deref in std:: mem:: take ( & mut self . derefs ) {
376- let opaque = self . next_opaque ( ) ;
377- self . values . get_index_mut2 ( deref. index ( ) ) . unwrap ( ) . 0 = Value :: Opaque ( opaque) ;
440+ self . values . forget ( deref) ;
378441 }
379442 }
380443
0 commit comments