@@ -100,7 +100,7 @@ use rustc_data_structures::fx::FxHasher;
100100use rustc_data_structures:: graph:: dominators:: Dominators ;
101101use rustc_hir:: def:: DefKind ;
102102use rustc_index:: bit_set:: DenseBitSet ;
103- use rustc_index:: { IndexVec , newtype_index} ;
103+ use rustc_index:: { Idx , IndexVec , newtype_index} ;
104104use rustc_middle:: bug;
105105use rustc_middle:: mir:: interpret:: GlobalAlloc ;
106106use rustc_middle:: mir:: visit:: * ;
@@ -158,6 +158,14 @@ newtype_index! {
158158 struct VnIndex { }
159159}
160160
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+
161169#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
162170enum AddressKind {
163171 Ref ( BorrowKind ) ,
@@ -169,14 +177,14 @@ enum Value<'tcx> {
169177 // Root values.
170178 /// Used to represent values we know nothing about.
171179 /// The `usize` is a counter incremented by `new_opaque`.
172- Opaque ( usize ) ,
180+ Opaque ( VnOpaque ) ,
173181 /// Evaluated or unevaluated constant value.
174182 Constant {
175183 value : Const < ' tcx > ,
176184 /// Some constants do not have a deterministic value. To avoid merging two instances of the
177185 /// 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 ,
180188 } ,
181189 /// An aggregate value, either tuple/closure/struct/enum.
182190 /// This does not contain unions, as we cannot reason with the value.
@@ -195,7 +203,7 @@ enum Value<'tcx> {
195203 place : Place < ' tcx > ,
196204 kind : AddressKind ,
197205 /// Give each borrow and pointer a different provenance, so we don't merge them.
198- provenance : usize ,
206+ provenance : VnOpaque ,
199207 } ,
200208
201209 // Extractions.
@@ -227,7 +235,7 @@ struct ValueSet<'tcx> {
227235 values : IndexVec < VnIndex , Value < ' tcx > > ,
228236 types : IndexVec < VnIndex , Ty < ' tcx > > ,
229237 /// Counter to generate different values.
230- next_opaque : usize ,
238+ next_opaque : VnOpaque ,
231239}
232240
233241impl < ' tcx > ValueSet < ' tcx > {
@@ -237,14 +245,45 @@ impl<'tcx> ValueSet<'tcx> {
237245 hashes : IndexVec :: with_capacity ( num_values) ,
238246 values : IndexVec :: with_capacity ( num_values) ,
239247 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 ) ,
241250 }
242251 }
243252
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+
244277 /// Insert a `(Value, Ty)` pair to be deduplicated.
245278 /// Returns `true` as second tuple field if this value did not exist previously.
246279 #[ allow( rustc:: pass_by_value) ] // closures take `&VnIndex`
247280 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+
248287 let hash: u64 = {
249288 let mut h = FxHasher :: default ( ) ;
250289 value. hash ( & mut h) ;
@@ -271,14 +310,6 @@ impl<'tcx> ValueSet<'tcx> {
271310 }
272311 }
273312
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-
282313 /// Return the `Value` associated with the given `VnIndex`.
283314 #[ inline]
284315 fn value ( & self , index : VnIndex ) -> & Value < ' tcx > {
@@ -294,8 +325,8 @@ impl<'tcx> ValueSet<'tcx> {
294325 /// Replace the value associated with `index` with an opaque value.
295326 #[ inline]
296327 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 ) ;
299330 }
300331}
301332
@@ -373,8 +404,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
373404 /// from all the others.
374405 #[ instrument( level = "trace" , skip( self ) , ret) ]
375406 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
378413 }
379414
380415 /// Create a new `Value::Address` distinct from all the others.
@@ -387,8 +422,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
387422 }
388423 AddressKind :: Address ( mutbl) => Ty :: new_ptr ( self . tcx , pty, mutbl. to_mutbl_lossy ( ) ) ,
389424 } ;
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
392458 }
393459
394460 #[ inline]
@@ -409,33 +475,18 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
409475 self . rev_locals [ value] . push ( local) ;
410476 }
411477
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-
427478 fn insert_bool ( & mut self , flag : bool ) -> VnIndex {
428479 // Booleans are deterministic.
429480 let value = Const :: from_bool ( self . tcx , flag) ;
430481 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 } )
432483 }
433484
434485 fn insert_scalar ( & mut self , ty : Ty < ' tcx > , scalar : Scalar ) -> VnIndex {
435486 // Scalars are deterministic.
436487 let value = Const :: from_scalar ( self . tcx , scalar, ty) ;
437488 debug_assert ! ( value. is_deterministic( ) ) ;
438- self . insert ( ty, Value :: Constant { value, disambiguator : 0 } )
489+ self . insert ( ty, Value :: Constant { value, disambiguator : DETERMINISTIC } )
439490 }
440491
441492 fn insert_tuple ( & mut self , ty : Ty < ' tcx > , values : Vec < VnIndex > ) -> VnIndex {
@@ -1680,7 +1731,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16801731 // This was already constant in MIR, do not change it. If the constant is not
16811732 // deterministic, adding an additional mention of it in MIR will not give the same value as
16821733 // 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) {
16841735 debug_assert ! ( value. is_deterministic( ) ) ;
16851736 return Some ( ConstOperand { span : DUMMY_SP , user_ty : None , const_ : value } ) ;
16861737 }
0 commit comments