@@ -153,9 +153,17 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
153
153
}
154
154
155
155
newtype_index ! {
156
+ #[ debug_format = "_v{}" ]
156
157
struct VnIndex { }
157
158
}
158
159
160
+ newtype_index ! {
161
+ #[ debug_format = "_o{}" ]
162
+ struct VnOpaque { }
163
+ }
164
+
165
+ const DETERMINISTIC : VnOpaque = VnOpaque :: MAX ;
166
+
159
167
#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
160
168
enum AddressKind {
161
169
Ref ( BorrowKind ) ,
@@ -167,14 +175,14 @@ enum Value<'tcx> {
167
175
// Root values.
168
176
/// Used to represent values we know nothing about.
169
177
/// The `usize` is a counter incremented by `new_opaque`.
170
- Opaque ( usize ) ,
178
+ Opaque ( VnOpaque ) ,
171
179
/// Evaluated or unevaluated constant value.
172
180
Constant {
173
181
value : Const < ' tcx > ,
174
182
/// Some constants do not have a deterministic value. To avoid merging two instances of the
175
183
/// 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 ,
178
186
} ,
179
187
/// An aggregate value, either tuple/closure/struct/enum.
180
188
/// This does not contain unions, as we cannot reason with the value.
@@ -193,7 +201,7 @@ enum Value<'tcx> {
193
201
place : Place < ' tcx > ,
194
202
kind : AddressKind ,
195
203
/// Give each borrow and pointer a different provenance, so we don't merge them.
196
- provenance : usize ,
204
+ provenance : VnOpaque ,
197
205
} ,
198
206
199
207
// Extractions.
@@ -219,8 +227,7 @@ struct ValueSet<'tcx> {
219
227
hashes : IndexVec < VnIndex , u64 > ,
220
228
values : IndexVec < VnIndex , Value < ' tcx > > ,
221
229
types : IndexVec < VnIndex , Ty < ' tcx > > ,
222
- /// Counter to generate different values.
223
- next_opaque : usize ,
230
+ opaques : IndexVec < VnOpaque , VnIndex > ,
224
231
}
225
232
226
233
impl < ' tcx > ValueSet < ' tcx > {
@@ -230,10 +237,25 @@ impl<'tcx> ValueSet<'tcx> {
230
237
hashes : IndexVec :: with_capacity ( num_values) ,
231
238
values : IndexVec :: with_capacity ( num_values) ,
232
239
types : IndexVec :: with_capacity ( num_values) ,
233
- next_opaque : 1 ,
240
+ opaques : IndexVec :: with_capacity ( num_values ) ,
234
241
}
235
242
}
236
243
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
+
237
259
#[ allow( rustc:: pass_by_value) ]
238
260
fn insert ( & mut self , value : Value < ' tcx > , ty : Ty < ' tcx > ) -> ( VnIndex , bool ) {
239
261
let hash: u64 = {
@@ -262,13 +284,6 @@ impl<'tcx> ValueSet<'tcx> {
262
284
}
263
285
}
264
286
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
-
272
287
#[ inline]
273
288
fn value ( & self , index : VnIndex ) -> & Value < ' tcx > {
274
289
& self . values [ index]
@@ -281,7 +296,7 @@ impl<'tcx> ValueSet<'tcx> {
281
296
282
297
#[ inline]
283
298
fn forget ( & mut self , index : VnIndex ) {
284
- let opaque = self . next_opaque ( ) ;
299
+ let opaque = self . opaques . push ( index ) ;
285
300
self . values [ index] = Value :: Opaque ( opaque) ;
286
301
}
287
302
}
@@ -360,8 +375,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
360
375
/// from all the others.
361
376
#[ instrument( level = "trace" , skip( self ) , ret) ]
362
377
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
365
384
}
366
385
367
386
/// Create a new `Value::Address` distinct from all the others.
@@ -374,8 +393,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
374
393
}
375
394
AddressKind :: Address ( mutbl) => Ty :: new_ptr ( self . tcx , pty, mutbl. to_mutbl_lossy ( ) ) ,
376
395
} ;
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
379
429
}
380
430
381
431
#[ inline]
@@ -396,33 +446,18 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
396
446
self . rev_locals [ value] . push ( local) ;
397
447
}
398
448
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
-
414
449
fn insert_bool ( & mut self , flag : bool ) -> VnIndex {
415
450
// Booleans are deterministic.
416
451
let value = Const :: from_bool ( self . tcx , flag) ;
417
452
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 } )
419
454
}
420
455
421
456
fn insert_scalar ( & mut self , ty : Ty < ' tcx > , scalar : Scalar ) -> VnIndex {
422
457
// Scalars are deterministic.
423
458
let value = Const :: from_scalar ( self . tcx , scalar, ty) ;
424
459
debug_assert ! ( value. is_deterministic( ) ) ;
425
- self . insert ( ty, Value :: Constant { value, disambiguator : 0 } )
460
+ self . insert ( ty, Value :: Constant { value, disambiguator : DETERMINISTIC } )
426
461
}
427
462
428
463
fn insert_tuple ( & mut self , ty : Ty < ' tcx > , values : Vec < VnIndex > ) -> VnIndex {
@@ -1678,7 +1713,7 @@ impl<'tcx> VnState<'_, 'tcx> {
1678
1713
// This was already constant in MIR, do not change it. If the constant is not
1679
1714
// deterministic, adding an additional mention of it in MIR will not give the same value as
1680
1715
// 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) {
1682
1717
debug_assert ! ( value. is_deterministic( ) ) ;
1683
1718
return Some ( ConstOperand { span : DUMMY_SP , user_ty : None , const_ : value } ) ;
1684
1719
}
0 commit comments