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 ;
@@ -151,9 +153,15 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
151153}
152154
153155newtype_index ! {
156+ #[ debug_format = "_v{}" ]
154157 struct VnIndex { }
155158}
156159
160+ newtype_index ! {
161+ #[ debug_format = "_o{}" ]
162+ struct VnOpaque { }
163+ }
164+
157165#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
158166enum AddressKind {
159167 Ref ( BorrowKind ) ,
@@ -165,7 +173,7 @@ enum Value<'tcx> {
165173 // Root values.
166174 /// Used to represent values we know nothing about.
167175 /// The `usize` is a counter incremented by `new_opaque`.
168- Opaque ( usize ) ,
176+ Opaque ( VnOpaque ) ,
169177 /// Evaluated or unevaluated constant value.
170178 Constant {
171179 value : Const < ' tcx > ,
@@ -212,6 +220,85 @@ enum Value<'tcx> {
212220 } ,
213221}
214222
223+ struct ValueSet < ' tcx > {
224+ indices : HashTable < VnIndex > ,
225+ hashes : IndexVec < VnIndex , u64 > ,
226+ values : IndexVec < VnIndex , Value < ' tcx > > ,
227+ types : IndexVec < VnIndex , Ty < ' tcx > > ,
228+ opaques : IndexVec < VnOpaque , VnIndex > ,
229+ }
230+
231+ impl < ' tcx > ValueSet < ' tcx > {
232+ fn new ( num_values : usize ) -> ValueSet < ' tcx > {
233+ ValueSet {
234+ indices : HashTable :: with_capacity ( num_values) ,
235+ hashes : IndexVec :: with_capacity ( num_values) ,
236+ values : IndexVec :: with_capacity ( num_values) ,
237+ types : IndexVec :: with_capacity ( num_values) ,
238+ opaques : IndexVec :: with_capacity ( num_values) ,
239+ }
240+ }
241+
242+ #[ allow( rustc:: pass_by_value) ]
243+ fn insert ( & mut self , value : Value < ' tcx > , ty : Ty < ' tcx > ) -> ( VnIndex , bool ) {
244+ if let Value :: Opaque ( opaque) = value {
245+ return ( self . opaques [ opaque] , false ) ;
246+ }
247+
248+ let hash: u64 = {
249+ let mut h = FxHasher :: default ( ) ;
250+ value. hash ( & mut h) ;
251+ ty. hash ( & mut h) ;
252+ h. finish ( )
253+ } ;
254+
255+ let eq = |index : & VnIndex | self . values [ * index] == value && self . types [ * index] == ty;
256+ let hasher = |index : & VnIndex | self . hashes [ * index] ;
257+ match self . indices . entry ( hash, eq, hasher) {
258+ Entry :: Occupied ( entry) => {
259+ let index = * entry. get ( ) ;
260+ ( index, false )
261+ }
262+ Entry :: Vacant ( entry) => {
263+ let index = self . hashes . push ( hash) ;
264+ entry. insert ( index) ;
265+ let _index = self . values . push ( value) ;
266+ debug_assert_eq ! ( index, _index) ;
267+ let _index = self . types . push ( ty) ;
268+ debug_assert_eq ! ( index, _index) ;
269+ ( index, true )
270+ }
271+ }
272+ }
273+
274+ #[ inline]
275+ fn new_opaque ( & mut self , ty : Ty < ' tcx > ) -> VnIndex {
276+ let index = self . hashes . push ( 0 ) ;
277+ let _index = self . types . push ( ty) ;
278+ debug_assert_eq ! ( index, _index) ;
279+ let opaque = self . opaques . push ( index) ;
280+ let _index = self . values . push ( Value :: Opaque ( opaque) ) ;
281+ debug_assert_eq ! ( index, _index) ;
282+ index
283+ }
284+
285+ #[ inline]
286+ fn value ( & self , index : VnIndex ) -> & Value < ' tcx > {
287+ & self . values [ index]
288+ }
289+
290+ #[ inline]
291+ fn ty ( & self , index : VnIndex ) -> Ty < ' tcx > {
292+ self . types [ index]
293+ }
294+
295+ #[ inline]
296+ fn forget ( & mut self , index : VnIndex ) {
297+ let opaque = self . opaques . push ( index) ;
298+ self . values [ index] = Value :: Opaque ( opaque) ;
299+ }
300+ }
301+
215302struct VnState < ' body , ' tcx > {
216303 tcx : TyCtxt < ' tcx > ,
217304 ecx : InterpCx < ' tcx , DummyMachine > ,
@@ -222,11 +309,11 @@ struct VnState<'body, 'tcx> {
222309 /// Locals that are assigned that value.
223310 // This vector does not hold all the values of `VnIndex` that we create.
224311 rev_locals : IndexVec < VnIndex , SmallVec < [ Local ; 1 ] > > ,
225- values : FxIndexSet < ( Value < ' tcx > , Ty < ' tcx > ) > ,
312+ values : ValueSet < ' tcx > ,
226313 /// Values evaluated as constants if possible.
227314 evaluated : IndexVec < VnIndex , Option < OpTy < ' tcx > > > ,
228315 /// Counter to generate different values.
229- next_opaque : usize ,
316+ next_disambiguator : usize ,
230317 /// Cache the deref values.
231318 derefs : Vec < VnIndex > ,
232319 ssa : & ' body SsaLocals ,
@@ -257,9 +344,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
257344 is_coroutine : body. coroutine . is_some ( ) ,
258345 locals : IndexVec :: from_elem ( None , local_decls) ,
259346 rev_locals : IndexVec :: with_capacity ( num_values) ,
260- values : FxIndexSet :: with_capacity_and_hasher ( num_values, Default :: default ( ) ) ,
347+ values : ValueSet :: new ( num_values) ,
261348 evaluated : IndexVec :: with_capacity ( num_values) ,
262- next_opaque : 1 ,
349+ next_disambiguator : 1 ,
263350 derefs : Vec :: new ( ) ,
264351 ssa,
265352 dominators,
@@ -273,8 +360,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
273360
274361 #[ instrument( level = "trace" , skip( self ) , ret) ]
275362 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) ;
363+ let ( index, new) = self . values . insert ( value, ty) ;
278364 if new {
279365 // Grow `evaluated` and `rev_locals` here to amortize the allocations.
280366 let evaluated = self . eval_to_const ( index) ;
@@ -286,18 +372,23 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
286372 index
287373 }
288374
289- fn next_opaque ( & mut self ) -> usize {
290- let next_opaque = self . next_opaque ;
291- self . next_opaque += 1 ;
292- next_opaque
293- }
294-
295375 /// Create a new `Value` for which we have no information at all, except that it is distinct
296376 /// from all the others.
297377 #[ instrument( level = "trace" , skip( self ) , ret) ]
298378 fn new_opaque ( & mut self , ty : Ty < ' tcx > ) -> VnIndex {
299- let value = Value :: Opaque ( self . next_opaque ( ) ) ;
300- self . insert ( ty, value)
379+ let index = self . values . new_opaque ( ty) ;
380+ let _index = self . evaluated . push ( None ) ;
381+ debug_assert_eq ! ( index, _index) ;
382+ let _index = self . rev_locals . push ( SmallVec :: new ( ) ) ;
383+ debug_assert_eq ! ( index, _index) ;
384+ index
385+ }
386+
387+ #[ inline]
388+ fn next_disambiguator ( & mut self ) -> usize {
389+ let next_disambiguator = self . next_disambiguator ;
390+ self . next_disambiguator += 1 ;
391+ next_disambiguator
301392 }
302393
303394 /// Create a new `Value::Address` distinct from all the others.
@@ -310,18 +401,18 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
310401 }
311402 AddressKind :: Address ( mutbl) => Ty :: new_ptr ( self . tcx , pty, mutbl. to_mutbl_lossy ( ) ) ,
312403 } ;
313- let value = Value :: Address { place, kind, provenance : self . next_opaque ( ) } ;
404+ let value = Value :: Address { place, kind, provenance : self . next_disambiguator ( ) } ;
314405 self . insert ( ty, value)
315406 }
316407
317408 #[ inline]
318409 fn get ( & self , index : VnIndex ) -> & Value < ' tcx > {
319- & self . values . get_index ( index. as_usize ( ) ) . unwrap ( ) . 0
410+ self . values . value ( index)
320411 }
321412
322413 #[ inline]
323414 fn ty ( & self , index : VnIndex ) -> Ty < ' tcx > {
324- self . values . get_index ( index. as_usize ( ) ) . unwrap ( ) . 1
415+ self . values . ty ( index)
325416 }
326417
327418 /// Record that `local` is assigned `value`. `local` must be SSA.
@@ -339,7 +430,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
339430 } else {
340431 // Multiple mentions of this constant will yield different values,
341432 // so assign a different `disambiguator` to ensure they do not get the same `VnIndex`.
342- let disambiguator = self . next_opaque ( ) ;
433+ let disambiguator = self . next_disambiguator ( ) ;
343434 // `disambiguator: 0` means deterministic.
344435 debug_assert_ne ! ( disambiguator, 0 ) ;
345436 disambiguator
@@ -373,8 +464,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
373464
374465 fn invalidate_derefs ( & mut self ) {
375466 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) ;
467+ self . values . forget ( deref) ;
378468 }
379469 }
380470
0 commit comments