@@ -100,7 +100,7 @@ use rustc_data_structures::fx::FxHasher;
100
100
use rustc_data_structures:: graph:: dominators:: Dominators ;
101
101
use rustc_hir:: def:: DefKind ;
102
102
use rustc_index:: bit_set:: DenseBitSet ;
103
- use rustc_index:: { IndexVec , newtype_index} ;
103
+ use rustc_index:: { Idx , IndexVec , newtype_index} ;
104
104
use rustc_middle:: bug;
105
105
use rustc_middle:: mir:: interpret:: GlobalAlloc ;
106
106
use rustc_middle:: mir:: visit:: * ;
@@ -158,6 +158,14 @@ newtype_index! {
158
158
struct VnIndex { }
159
159
}
160
160
161
+ newtype_index ! {
162
+ /// Counter type to ensure that all unique values are created using `insert_unique`.
163
+ #[ debug_format = "_o{}" ]
164
+ struct VnOpaque {
165
+ const DETERMINISTIC = 0 ;
166
+ }
167
+ }
168
+
161
169
#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
162
170
enum AddressKind {
163
171
Ref ( BorrowKind ) ,
@@ -169,14 +177,14 @@ enum Value<'tcx> {
169
177
// Root values.
170
178
/// Used to represent values we know nothing about.
171
179
/// The `usize` is a counter incremented by `new_opaque`.
172
- Opaque ( usize ) ,
180
+ Opaque ( VnOpaque ) ,
173
181
/// Evaluated or unevaluated constant value.
174
182
Constant {
175
183
value : Const < ' tcx > ,
176
184
/// Some constants do not have a deterministic value. To avoid merging two instances of the
177
185
/// same `Const`, we assign them an additional integer index.
178
- // `disambiguator` is 0 iff the constant is deterministic.
179
- disambiguator : usize ,
186
+ // `disambiguator` is `DETERMINISTIC` iff the constant is deterministic.
187
+ disambiguator : VnOpaque ,
180
188
} ,
181
189
/// An aggregate value, either tuple/closure/struct/enum.
182
190
/// This does not contain unions, as we cannot reason with the value.
@@ -195,7 +203,7 @@ enum Value<'tcx> {
195
203
place : Place < ' tcx > ,
196
204
kind : AddressKind ,
197
205
/// Give each borrow and pointer a different provenance, so we don't merge them.
198
- provenance : usize ,
206
+ provenance : VnOpaque ,
199
207
} ,
200
208
201
209
// Extractions.
@@ -227,7 +235,7 @@ struct ValueSet<'tcx> {
227
235
values : IndexVec < VnIndex , Value < ' tcx > > ,
228
236
types : IndexVec < VnIndex , Ty < ' tcx > > ,
229
237
/// Counter to generate different values.
230
- next_opaque : usize ,
238
+ next_opaque : VnOpaque ,
231
239
}
232
240
233
241
impl < ' tcx > ValueSet < ' tcx > {
@@ -237,14 +245,45 @@ impl<'tcx> ValueSet<'tcx> {
237
245
hashes : IndexVec :: with_capacity ( num_values) ,
238
246
values : IndexVec :: with_capacity ( num_values) ,
239
247
types : IndexVec :: with_capacity ( num_values) ,
240
- next_opaque : 1 ,
248
+ // The first opaque is 1, as 0 means deterministic constant.
249
+ next_opaque : VnOpaque :: from_u32 ( 1 ) ,
241
250
}
242
251
}
243
252
253
+ /// Insert a `(Value, Ty)` pair without hashing or deduplication.
254
+ #[ inline]
255
+ fn insert_unique (
256
+ & mut self ,
257
+ ty : Ty < ' tcx > ,
258
+ value : impl FnOnce ( VnOpaque ) -> Value < ' tcx > ,
259
+ ) -> VnIndex {
260
+ let value = value ( self . next_opaque ) ;
261
+ self . next_opaque . increment_by ( 1 ) ;
262
+
263
+ debug_assert ! ( match value {
264
+ Value :: Opaque ( _) | Value :: Address { .. } => true ,
265
+ Value :: Constant { disambiguator, .. } => disambiguator != DETERMINISTIC ,
266
+ _ => false ,
267
+ } ) ;
268
+
269
+ let index = self . hashes . push ( 0 ) ;
270
+ let _index = self . types . push ( ty) ;
271
+ debug_assert_eq ! ( index, _index) ;
272
+ let _index = self . values . push ( value) ;
273
+ debug_assert_eq ! ( index, _index) ;
274
+ index
275
+ }
276
+
244
277
/// Insert a `(Value, Ty)` pair to be deduplicated.
245
278
/// Returns `true` as second tuple field if this value did not exist previously.
246
279
#[ allow( rustc:: pass_by_value) ] // closures take `&VnIndex`
247
280
fn insert ( & mut self , ty : Ty < ' tcx > , value : Value < ' tcx > ) -> ( VnIndex , bool ) {
281
+ debug_assert ! ( match value {
282
+ Value :: Opaque ( _) | Value :: Address { .. } => false ,
283
+ Value :: Constant { disambiguator, .. } => disambiguator == DETERMINISTIC ,
284
+ _ => true ,
285
+ } ) ;
286
+
248
287
let hash: u64 = {
249
288
let mut h = FxHasher :: default ( ) ;
250
289
value. hash ( & mut h) ;
@@ -271,14 +310,6 @@ impl<'tcx> ValueSet<'tcx> {
271
310
}
272
311
}
273
312
274
- /// Increment the opaque index counter return a new unique value.
275
- #[ inline]
276
- fn next_opaque ( & mut self ) -> usize {
277
- let next_opaque = self . next_opaque ;
278
- self . next_opaque += 1 ;
279
- next_opaque
280
- }
281
-
282
313
/// Return the `Value` associated with the given `VnIndex`.
283
314
#[ inline]
284
315
fn value ( & self , index : VnIndex ) -> & Value < ' tcx > {
@@ -294,8 +325,8 @@ impl<'tcx> ValueSet<'tcx> {
294
325
/// Replace the value associated with `index` with an opaque value.
295
326
#[ inline]
296
327
fn forget ( & mut self , index : VnIndex ) {
297
- let opaque = self . next_opaque ( ) ;
298
- self . values [ index ] = Value :: Opaque ( opaque ) ;
328
+ self . values [ index ] = Value :: Opaque ( self . next_opaque ) ;
329
+ self . next_opaque . increment_by ( 1 ) ;
299
330
}
300
331
}
301
332
@@ -373,8 +404,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
373
404
/// from all the others.
374
405
#[ instrument( level = "trace" , skip( self ) , ret) ]
375
406
fn new_opaque ( & mut self , ty : Ty < ' tcx > ) -> VnIndex {
376
- let value = Value :: Opaque ( self . values . next_opaque ( ) ) ;
377
- self . insert ( ty, value)
407
+ let index = self . values . insert_unique ( ty, Value :: Opaque ) ;
408
+ let _index = self . evaluated . push ( None ) ;
409
+ debug_assert_eq ! ( index, _index) ;
410
+ let _index = self . rev_locals . push ( SmallVec :: new ( ) ) ;
411
+ debug_assert_eq ! ( index, _index) ;
412
+ index
378
413
}
379
414
380
415
/// Create a new `Value::Address` distinct from all the others.
@@ -387,8 +422,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
387
422
}
388
423
AddressKind :: Address ( mutbl) => Ty :: new_ptr ( self . tcx , pty, mutbl. to_mutbl_lossy ( ) ) ,
389
424
} ;
390
- let value = Value :: Address { place, kind, provenance : self . values . next_opaque ( ) } ;
391
- self . insert ( ty, value)
425
+ let index =
426
+ self . values . insert_unique ( ty, |provenance| Value :: Address { place, kind, provenance } ) ;
427
+ let evaluated = self . eval_to_const ( index) ;
428
+ let _index = self . evaluated . push ( evaluated) ;
429
+ debug_assert_eq ! ( index, _index) ;
430
+ let _index = self . rev_locals . push ( SmallVec :: new ( ) ) ;
431
+ debug_assert_eq ! ( index, _index) ;
432
+ index
433
+ }
434
+
435
+ #[ instrument( level = "trace" , skip( self ) , ret) ]
436
+ fn insert_constant ( & mut self , value : Const < ' tcx > ) -> VnIndex {
437
+ let ( index, new) = if value. is_deterministic ( ) {
438
+ // The constant is deterministic, no need to disambiguate.
439
+ let constant = Value :: Constant { value, disambiguator : DETERMINISTIC } ;
440
+ self . values . insert ( value. ty ( ) , constant)
441
+ } else {
442
+ // Multiple mentions of this constant will yield different values,
443
+ // so assign a different `disambiguator` to ensure they do not get the same `VnIndex`.
444
+ let index = self . values . insert_unique ( value. ty ( ) , |disambiguator| {
445
+ debug_assert_ne ! ( disambiguator, DETERMINISTIC ) ;
446
+ Value :: Constant { value, disambiguator }
447
+ } ) ;
448
+ ( index, true )
449
+ } ;
450
+ if new {
451
+ let evaluated = self . eval_to_const ( index) ;
452
+ let _index = self . evaluated . push ( evaluated) ;
453
+ debug_assert_eq ! ( index, _index) ;
454
+ let _index = self . rev_locals . push ( SmallVec :: new ( ) ) ;
455
+ debug_assert_eq ! ( index, _index) ;
456
+ }
457
+ index
392
458
}
393
459
394
460
#[ inline]
@@ -409,33 +475,18 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
409
475
self . rev_locals [ value] . push ( local) ;
410
476
}
411
477
412
- fn insert_constant ( & mut self , value : Const < ' tcx > ) -> VnIndex {
413
- let disambiguator = if value. is_deterministic ( ) {
414
- // The constant is deterministic, no need to disambiguate.
415
- 0
416
- } else {
417
- // Multiple mentions of this constant will yield different values,
418
- // so assign a different `disambiguator` to ensure they do not get the same `VnIndex`.
419
- let disambiguator = self . values . next_opaque ( ) ;
420
- // `disambiguator: 0` means deterministic.
421
- debug_assert_ne ! ( disambiguator, 0 ) ;
422
- disambiguator
423
- } ;
424
- self . insert ( value. ty ( ) , Value :: Constant { value, disambiguator } )
425
- }
426
-
427
478
fn insert_bool ( & mut self , flag : bool ) -> VnIndex {
428
479
// Booleans are deterministic.
429
480
let value = Const :: from_bool ( self . tcx , flag) ;
430
481
debug_assert ! ( value. is_deterministic( ) ) ;
431
- self . insert ( self . tcx . types . bool , Value :: Constant { value, disambiguator : 0 } )
482
+ self . insert ( self . tcx . types . bool , Value :: Constant { value, disambiguator : DETERMINISTIC } )
432
483
}
433
484
434
485
fn insert_scalar ( & mut self , ty : Ty < ' tcx > , scalar : Scalar ) -> VnIndex {
435
486
// Scalars are deterministic.
436
487
let value = Const :: from_scalar ( self . tcx , scalar, ty) ;
437
488
debug_assert ! ( value. is_deterministic( ) ) ;
438
- self . insert ( ty, Value :: Constant { value, disambiguator : 0 } )
489
+ self . insert ( ty, Value :: Constant { value, disambiguator : DETERMINISTIC } )
439
490
}
440
491
441
492
fn insert_tuple ( & mut self , ty : Ty < ' tcx > , values : Vec < VnIndex > ) -> VnIndex {
@@ -1680,7 +1731,7 @@ impl<'tcx> VnState<'_, 'tcx> {
1680
1731
// This was already constant in MIR, do not change it. If the constant is not
1681
1732
// deterministic, adding an additional mention of it in MIR will not give the same value as
1682
1733
// the former mention.
1683
- if let Value :: Constant { value, disambiguator : 0 } = * self . get ( index) {
1734
+ if let Value :: Constant { value, disambiguator : DETERMINISTIC } = * self . get ( index) {
1684
1735
debug_assert ! ( value. is_deterministic( ) ) ;
1685
1736
return Some ( ConstOperand { span : DUMMY_SP , user_ty : None , const_ : value } ) ;
1686
1737
}
0 commit comments