85
85
//! that contain `AllocId`s.
86
86
87
87
use std:: borrow:: Cow ;
88
+ use std:: hash:: { Hash , Hasher } ;
88
89
89
90
use either:: Either ;
91
+ use hashbrown:: hash_table:: { Entry , HashTable } ;
90
92
use rustc_abi:: { self as abi, BackendRepr , FIRST_VARIANT , FieldIdx , Primitive , Size , VariantIdx } ;
91
93
use rustc_const_eval:: const_eval:: DummyMachine ;
92
94
use rustc_const_eval:: interpret:: {
93
95
ImmTy , Immediate , InterpCx , MemPlaceMeta , MemoryKind , OpTy , Projectable , Scalar ,
94
96
intern_const_alloc_for_constprop,
95
97
} ;
96
- use rustc_data_structures:: fx:: { FxIndexSet , MutableValues } ;
98
+ use rustc_data_structures:: fx:: FxHasher ;
97
99
use rustc_data_structures:: graph:: dominators:: Dominators ;
98
100
use rustc_hir:: def:: DefKind ;
99
101
use rustc_index:: bit_set:: DenseBitSet ;
@@ -212,6 +214,78 @@ enum Value<'tcx> {
212
214
} ,
213
215
}
214
216
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
+
215
289
struct VnState < ' body , ' tcx > {
216
290
tcx : TyCtxt < ' tcx > ,
217
291
ecx : InterpCx < ' tcx , DummyMachine > ,
@@ -222,11 +296,9 @@ struct VnState<'body, 'tcx> {
222
296
/// Locals that are assigned that value.
223
297
// This vector does not hold all the values of `VnIndex` that we create.
224
298
rev_locals : IndexVec < VnIndex , SmallVec < [ Local ; 1 ] > > ,
225
- values : FxIndexSet < ( Value < ' tcx > , Ty < ' tcx > ) > ,
299
+ values : ValueSet < ' tcx > ,
226
300
/// Values evaluated as constants if possible.
227
301
evaluated : IndexVec < VnIndex , Option < OpTy < ' tcx > > > ,
228
- /// Counter to generate different values.
229
- next_opaque : usize ,
230
302
/// Cache the deref values.
231
303
derefs : Vec < VnIndex > ,
232
304
ssa : & ' body SsaLocals ,
@@ -257,9 +329,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
257
329
is_coroutine : body. coroutine . is_some ( ) ,
258
330
locals : IndexVec :: from_elem ( None , local_decls) ,
259
331
rev_locals : IndexVec :: with_capacity ( num_values) ,
260
- values : FxIndexSet :: with_capacity_and_hasher ( num_values, Default :: default ( ) ) ,
332
+ values : ValueSet :: new ( num_values) ,
261
333
evaluated : IndexVec :: with_capacity ( num_values) ,
262
- next_opaque : 1 ,
263
334
derefs : Vec :: new ( ) ,
264
335
ssa,
265
336
dominators,
@@ -273,8 +344,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
273
344
274
345
#[ instrument( level = "trace" , skip( self ) , ret) ]
275
346
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) ;
278
348
if new {
279
349
// Grow `evaluated` and `rev_locals` here to amortize the allocations.
280
350
let evaluated = self . eval_to_const ( index) ;
@@ -286,17 +356,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
286
356
index
287
357
}
288
358
289
- fn next_opaque ( & mut self ) -> usize {
290
- let next_opaque = self . next_opaque ;
291
- self . next_opaque += 1 ;
292
- next_opaque
293
- }
294
-
295
359
/// Create a new `Value` for which we have no information at all, except that it is distinct
296
360
/// from all the others.
297
361
#[ instrument( level = "trace" , skip( self ) , ret) ]
298
362
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 ( ) ) ;
300
364
self . insert ( ty, value)
301
365
}
302
366
@@ -310,18 +374,18 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
310
374
}
311
375
AddressKind :: Address ( mutbl) => Ty :: new_ptr ( self . tcx , pty, mutbl. to_mutbl_lossy ( ) ) ,
312
376
} ;
313
- let value = Value :: Address { place, kind, provenance : self . next_opaque ( ) } ;
377
+ let value = Value :: Address { place, kind, provenance : self . values . next_opaque ( ) } ;
314
378
self . insert ( ty, value)
315
379
}
316
380
317
381
#[ inline]
318
382
fn get ( & self , index : VnIndex ) -> & Value < ' tcx > {
319
- & self . values . get_index ( index. as_usize ( ) ) . unwrap ( ) . 0
383
+ self . values . value ( index)
320
384
}
321
385
322
386
#[ inline]
323
387
fn ty ( & self , index : VnIndex ) -> Ty < ' tcx > {
324
- self . values . get_index ( index. as_usize ( ) ) . unwrap ( ) . 1
388
+ self . values . ty ( index)
325
389
}
326
390
327
391
/// Record that `local` is assigned `value`. `local` must be SSA.
@@ -339,7 +403,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
339
403
} else {
340
404
// Multiple mentions of this constant will yield different values,
341
405
// 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 ( ) ;
343
407
// `disambiguator: 0` means deterministic.
344
408
debug_assert_ne ! ( disambiguator, 0 ) ;
345
409
disambiguator
@@ -373,8 +437,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
373
437
374
438
fn invalidate_derefs ( & mut self ) {
375
439
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) ;
378
441
}
379
442
}
380
443
0 commit comments