@@ -153,9 +153,17 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
153153}
154154
155155newtype_index ! {
156+ #[ debug_format = "_v{}" ]
156157 struct VnIndex { }
157158}
158159
160+ newtype_index ! {
161+ #[ debug_format = "_o{}" ]
162+ struct VnOpaque { }
163+ }
164+
165+ const DETERMINISTIC : VnOpaque = VnOpaque :: MAX ;
166+
159167#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
160168enum AddressKind {
161169 Ref ( BorrowKind ) ,
@@ -167,14 +175,14 @@ enum Value<'tcx> {
167175 // Root values.
168176 /// Used to represent values we know nothing about.
169177 /// The `usize` is a counter incremented by `new_opaque`.
170- Opaque ( usize ) ,
178+ Opaque ( VnOpaque ) ,
171179 /// Evaluated or unevaluated constant value.
172180 Constant {
173181 value : Const < ' tcx > ,
174182 /// Some constants do not have a deterministic value. To avoid merging two instances of the
175183 /// same `Const`, we assign them an additional integer index.
176- // `disambiguator` is 0 iff the constant is deterministic.
177- disambiguator : usize ,
184+ // `disambiguator` is `DETERMINISTIC` iff the constant is deterministic.
185+ disambiguator : VnOpaque ,
178186 } ,
179187 /// An aggregate value, either tuple/closure/struct/enum.
180188 /// This does not contain unions, as we cannot reason with the value.
@@ -193,7 +201,7 @@ enum Value<'tcx> {
193201 place : Place < ' tcx > ,
194202 kind : AddressKind ,
195203 /// Give each borrow and pointer a different provenance, so we don't merge them.
196- provenance : usize ,
204+ provenance : VnOpaque ,
197205 } ,
198206
199207 // Extractions.
@@ -219,8 +227,7 @@ struct ValueSet<'tcx> {
219227 hashes : IndexVec < VnIndex , u64 > ,
220228 values : IndexVec < VnIndex , Value < ' tcx > > ,
221229 types : IndexVec < VnIndex , Ty < ' tcx > > ,
222- /// Counter to generate different values.
223- next_opaque : usize ,
230+ opaques : IndexVec < VnOpaque , VnIndex > ,
224231}
225232
226233impl < ' tcx > ValueSet < ' tcx > {
@@ -230,10 +237,25 @@ impl<'tcx> ValueSet<'tcx> {
230237 hashes : IndexVec :: with_capacity ( num_values) ,
231238 values : IndexVec :: with_capacity ( num_values) ,
232239 types : IndexVec :: with_capacity ( num_values) ,
233- next_opaque : 1 ,
240+ opaques : IndexVec :: with_capacity ( num_values ) ,
234241 }
235242 }
236243
244+ #[ inline]
245+ fn insert_unique (
246+ & mut self ,
247+ ty : Ty < ' tcx > ,
248+ value : impl FnOnce ( VnOpaque ) -> Value < ' tcx > ,
249+ ) -> VnIndex {
250+ let index = self . hashes . push ( 0 ) ;
251+ let _index = self . types . push ( ty) ;
252+ debug_assert_eq ! ( index, _index) ;
253+ let opaque = self . opaques . push ( index) ;
254+ let _index = self . values . push ( value ( opaque) ) ;
255+ debug_assert_eq ! ( index, _index) ;
256+ index
257+ }
258+
237259 #[ allow( rustc:: pass_by_value) ]
238260 fn insert ( & mut self , value : Value < ' tcx > , ty : Ty < ' tcx > ) -> ( VnIndex , bool ) {
239261 let hash: u64 = {
@@ -262,13 +284,6 @@ impl<'tcx> ValueSet<'tcx> {
262284 }
263285 }
264286
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-
272287 #[ inline]
273288 fn value ( & self , index : VnIndex ) -> & Value < ' tcx > {
274289 & self . values [ index]
@@ -281,7 +296,7 @@ impl<'tcx> ValueSet<'tcx> {
281296
282297 #[ inline]
283298 fn forget ( & mut self , index : VnIndex ) {
284- let opaque = self . next_opaque ( ) ;
299+ let opaque = self . opaques . push ( index ) ;
285300 self . values [ index] = Value :: Opaque ( opaque) ;
286301 }
287302}
@@ -360,8 +375,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
360375 /// from all the others.
361376 #[ instrument( level = "trace" , skip( self ) , ret) ]
362377 fn new_opaque ( & mut self , ty : Ty < ' tcx > ) -> VnIndex {
363- let value = Value :: Opaque ( self . values . next_opaque ( ) ) ;
364- self . insert ( ty, value)
378+ let index = self . values . insert_unique ( ty, Value :: Opaque ) ;
379+ let _index = self . evaluated . push ( None ) ;
380+ debug_assert_eq ! ( index, _index) ;
381+ let _index = self . rev_locals . push ( SmallVec :: new ( ) ) ;
382+ debug_assert_eq ! ( index, _index) ;
383+ index
365384 }
366385
367386 /// Create a new `Value::Address` distinct from all the others.
@@ -374,8 +393,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
374393 }
375394 AddressKind :: Address ( mutbl) => Ty :: new_ptr ( self . tcx , pty, mutbl. to_mutbl_lossy ( ) ) ,
376395 } ;
377- let value = Value :: Address { place, kind, provenance : self . values . next_opaque ( ) } ;
378- self . insert ( ty, value)
396+ let index =
397+ self . values . insert_unique ( ty, |provenance| Value :: Address { place, kind, provenance } ) ;
398+ let evaluated = self . eval_to_const ( index) ;
399+ let _index = self . evaluated . push ( evaluated) ;
400+ debug_assert_eq ! ( index, _index) ;
401+ let _index = self . rev_locals . push ( SmallVec :: new ( ) ) ;
402+ debug_assert_eq ! ( index, _index) ;
403+ index
404+ }
405+
406+ #[ instrument( level = "trace" , skip( self ) , ret) ]
407+ fn insert_constant ( & mut self , value : Const < ' tcx > ) -> VnIndex {
408+ let ( index, new) = if value. is_deterministic ( ) {
409+ // The constant is deterministic, no need to disambiguate.
410+ let constant = Value :: Constant { value, disambiguator : DETERMINISTIC } ;
411+ self . values . insert ( constant, value. ty ( ) )
412+ } else {
413+ // Multiple mentions of this constant will yield different values,
414+ // so assign a different `disambiguator` to ensure they do not get the same `VnIndex`.
415+ let index = self . values . insert_unique ( value. ty ( ) , |disambiguator| {
416+ debug_assert_ne ! ( disambiguator, DETERMINISTIC ) ;
417+ Value :: Constant { value, disambiguator }
418+ } ) ;
419+ ( index, true )
420+ } ;
421+ if new {
422+ let evaluated = self . eval_to_const ( index) ;
423+ let _index = self . evaluated . push ( evaluated) ;
424+ debug_assert_eq ! ( index, _index) ;
425+ let _index = self . rev_locals . push ( SmallVec :: new ( ) ) ;
426+ debug_assert_eq ! ( index, _index) ;
427+ }
428+ index
379429 }
380430
381431 #[ inline]
@@ -396,33 +446,18 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
396446 self . rev_locals [ value] . push ( local) ;
397447 }
398448
399- fn insert_constant ( & mut self , value : Const < ' tcx > ) -> VnIndex {
400- let disambiguator = if value. is_deterministic ( ) {
401- // The constant is deterministic, no need to disambiguate.
402- 0
403- } else {
404- // Multiple mentions of this constant will yield different values,
405- // so assign a different `disambiguator` to ensure they do not get the same `VnIndex`.
406- let disambiguator = self . values . next_opaque ( ) ;
407- // `disambiguator: 0` means deterministic.
408- debug_assert_ne ! ( disambiguator, 0 ) ;
409- disambiguator
410- } ;
411- self . insert ( value. ty ( ) , Value :: Constant { value, disambiguator } )
412- }
413-
414449 fn insert_bool ( & mut self , flag : bool ) -> VnIndex {
415450 // Booleans are deterministic.
416451 let value = Const :: from_bool ( self . tcx , flag) ;
417452 debug_assert ! ( value. is_deterministic( ) ) ;
418- self . insert ( self . tcx . types . bool , Value :: Constant { value, disambiguator : 0 } )
453+ self . insert ( self . tcx . types . bool , Value :: Constant { value, disambiguator : DETERMINISTIC } )
419454 }
420455
421456 fn insert_scalar ( & mut self , ty : Ty < ' tcx > , scalar : Scalar ) -> VnIndex {
422457 // Scalars are deterministic.
423458 let value = Const :: from_scalar ( self . tcx , scalar, ty) ;
424459 debug_assert ! ( value. is_deterministic( ) ) ;
425- self . insert ( ty, Value :: Constant { value, disambiguator : 0 } )
460+ self . insert ( ty, Value :: Constant { value, disambiguator : DETERMINISTIC } )
426461 }
427462
428463 fn insert_tuple ( & mut self , ty : Ty < ' tcx > , values : Vec < VnIndex > ) -> VnIndex {
@@ -1678,7 +1713,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16781713 // This was already constant in MIR, do not change it. If the constant is not
16791714 // deterministic, adding an additional mention of it in MIR will not give the same value as
16801715 // the former mention.
1681- if let Value :: Constant { value, disambiguator : 0 } = * self . get ( index) {
1716+ if let Value :: Constant { value, disambiguator : DETERMINISTIC } = * self . get ( index) {
16821717 debug_assert ! ( value. is_deterministic( ) ) ;
16831718 return Some ( ConstOperand { span : DUMMY_SP , user_ty : None , const_ : value } ) ;
16841719 }
0 commit comments