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