@@ -99,7 +99,7 @@ use rustc_data_structures::fx::FxHasher;
9999use rustc_data_structures:: graph:: dominators:: Dominators ;
100100use rustc_hir:: def:: DefKind ;
101101use rustc_index:: bit_set:: DenseBitSet ;
102- use rustc_index:: { IndexVec , newtype_index} ;
102+ use rustc_index:: { Idx , IndexVec , newtype_index} ;
103103use rustc_middle:: bug;
104104use rustc_middle:: mir:: interpret:: GlobalAlloc ;
105105use rustc_middle:: mir:: visit:: * ;
@@ -157,6 +157,14 @@ newtype_index! {
157157 struct VnIndex { }
158158}
159159
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+
160168#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
161169enum AddressKind {
162170 Ref ( BorrowKind ) ,
@@ -168,14 +176,14 @@ enum Value<'tcx> {
168176 // Root values.
169177 /// Used to represent values we know nothing about.
170178 /// The `usize` is a counter incremented by `new_opaque`.
171- Opaque ( usize ) ,
179+ Opaque ( VnOpaque ) ,
172180 /// Evaluated or unevaluated constant value.
173181 Constant {
174182 value : Const < ' tcx > ,
175183 /// Some constants do not have a deterministic value. To avoid merging two instances of the
176184 /// 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 ,
179187 } ,
180188 /// An aggregate value, either tuple/closure/struct/enum.
181189 /// This does not contain unions, as we cannot reason with the value.
@@ -194,7 +202,7 @@ enum Value<'tcx> {
194202 place : Place < ' tcx > ,
195203 kind : AddressKind ,
196204 /// Give each borrow and pointer a different provenance, so we don't merge them.
197- provenance : usize ,
205+ provenance : VnOpaque ,
198206 } ,
199207
200208 // Extractions.
@@ -226,7 +234,7 @@ struct ValueSet<'tcx> {
226234 values : IndexVec < VnIndex , Value < ' tcx > > ,
227235 types : IndexVec < VnIndex , Ty < ' tcx > > ,
228236 /// Counter to generate different values.
229- next_opaque : usize ,
237+ next_opaque : VnOpaque ,
230238}
231239
232240impl < ' tcx > ValueSet < ' tcx > {
@@ -236,14 +244,45 @@ impl<'tcx> ValueSet<'tcx> {
236244 hashes : IndexVec :: with_capacity ( num_values) ,
237245 values : IndexVec :: with_capacity ( num_values) ,
238246 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 ) ,
240249 }
241250 }
242251
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+
243276 /// Insert a `(Value, Ty)` pair to be deduplicated.
244277 /// Returns `true` as second tuple field if this value did not exist previously.
245278 #[ allow( rustc:: pass_by_value) ] // closures take `&VnIndex`
246279 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+
247286 let hash: u64 = {
248287 let mut h = FxHasher :: default ( ) ;
249288 value. hash ( & mut h) ;
@@ -270,14 +309,6 @@ impl<'tcx> ValueSet<'tcx> {
270309 }
271310 }
272311
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-
281312 /// Return the `Value` associated with the given `VnIndex`.
282313 #[ inline]
283314 fn value ( & self , index : VnIndex ) -> & Value < ' tcx > {
@@ -293,8 +324,8 @@ impl<'tcx> ValueSet<'tcx> {
293324 /// Replace the value associated with `index` with an opaque value.
294325 #[ inline]
295326 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 ) ;
298329 }
299330}
300331
@@ -372,8 +403,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
372403 /// from all the others.
373404 #[ instrument( level = "trace" , skip( self ) , ret) ]
374405 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
377412 }
378413
379414 /// Create a new `Value::Address` distinct from all the others.
@@ -386,8 +421,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
386421 }
387422 AddressKind :: Address ( mutbl) => Ty :: new_ptr ( self . tcx , pty, mutbl. to_mutbl_lossy ( ) ) ,
388423 } ;
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
391457 }
392458
393459 #[ inline]
@@ -408,33 +474,18 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
408474 self . rev_locals [ value] . push ( local) ;
409475 }
410476
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-
426477 fn insert_bool ( & mut self , flag : bool ) -> VnIndex {
427478 // Booleans are deterministic.
428479 let value = Const :: from_bool ( self . tcx , flag) ;
429480 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 } )
431482 }
432483
433484 fn insert_scalar ( & mut self , ty : Ty < ' tcx > , scalar : Scalar ) -> VnIndex {
434485 // Scalars are deterministic.
435486 let value = Const :: from_scalar ( self . tcx , scalar, ty) ;
436487 debug_assert ! ( value. is_deterministic( ) ) ;
437- self . insert ( ty, Value :: Constant { value, disambiguator : 0 } )
488+ self . insert ( ty, Value :: Constant { value, disambiguator : DETERMINISTIC } )
438489 }
439490
440491 fn insert_tuple ( & mut self , ty : Ty < ' tcx > , values : Vec < VnIndex > ) -> VnIndex {
@@ -1690,7 +1741,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16901741 // This was already constant in MIR, do not change it. If the constant is not
16911742 // deterministic, adding an additional mention of it in MIR will not give the same value as
16921743 // 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) {
16941745 debug_assert ! ( value. is_deterministic( ) ) ;
16951746 return Some ( ConstOperand { span : DUMMY_SP , user_ty : None , const_ : value } ) ;
16961747 }
0 commit comments