@@ -36,7 +36,7 @@ use std::collections::VecDeque;
36
36
use std:: fmt:: { Debug , Formatter } ;
37
37
use std:: ops:: Range ;
38
38
39
- use rustc_data_structures:: fx:: FxHashMap ;
39
+ use rustc_data_structures:: fx:: { FxHashMap , StdEntry } ;
40
40
use rustc_data_structures:: stack:: ensure_sufficient_stack;
41
41
use rustc_index:: bit_set:: BitSet ;
42
42
use rustc_index:: IndexVec ;
@@ -342,8 +342,7 @@ impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper
342
342
fn initialize_start_block ( & self , body : & Body < ' tcx > , state : & mut Self :: Domain ) {
343
343
// The initial state maps all tracked places of argument projections to ⊤ and the rest to ⊥.
344
344
assert ! ( matches!( state, State :: Unreachable ) ) ;
345
- let values = StateData :: from_elem_n ( T :: Value :: BOTTOM , self . 0 . map ( ) . value_count ) ;
346
- * state = State :: Reachable ( values) ;
345
+ * state = State :: new_reachable ( ) ;
347
346
for arg in body. args_iter ( ) {
348
347
state. flood ( PlaceRef { local : arg, projection : & [ ] } , self . 0 . map ( ) ) ;
349
348
}
@@ -415,30 +414,54 @@ rustc_index::newtype_index!(
415
414
416
415
/// See [`State`].
417
416
#[ derive( PartialEq , Eq , Debug ) ]
418
- struct StateData < V > {
419
- map : IndexVec < ValueIndex , V > ,
417
+ pub struct StateData < V > {
418
+ bottom : V ,
419
+ /// This map only contains values that are not `⊥`.
420
+ map : FxHashMap < ValueIndex , V > ,
420
421
}
421
422
422
- impl < V : Clone > StateData < V > {
423
- fn from_elem_n ( elem : V , n : usize ) -> StateData < V > {
424
- StateData { map : IndexVec :: from_elem_n ( elem, n) }
423
+ impl < V : HasBottom > StateData < V > {
424
+ fn new ( ) -> StateData < V > {
425
+ StateData { bottom : V :: BOTTOM , map : FxHashMap :: default ( ) }
426
+ }
427
+
428
+ fn get ( & self , idx : ValueIndex ) -> & V {
429
+ self . map . get ( & idx) . unwrap_or ( & self . bottom )
430
+ }
431
+
432
+ fn insert ( & mut self , idx : ValueIndex , elem : V ) {
433
+ if elem. is_bottom ( ) {
434
+ self . map . remove ( & idx) ;
435
+ } else {
436
+ self . map . insert ( idx, elem) ;
437
+ }
425
438
}
426
439
}
427
440
428
441
impl < V : Clone > Clone for StateData < V > {
429
442
fn clone ( & self ) -> Self {
430
- StateData { map : self . map . clone ( ) }
443
+ StateData { bottom : self . bottom . clone ( ) , map : self . map . clone ( ) }
431
444
}
432
445
433
446
fn clone_from ( & mut self , source : & Self ) {
434
- // We go through `raw` here, because `IndexVec` currently has a naive `clone_from`.
435
- self . map . raw . clone_from ( & source. map . raw )
447
+ self . map . clone_from ( & source. map )
436
448
}
437
449
}
438
450
439
- impl < V : JoinSemiLattice + Clone > JoinSemiLattice for StateData < V > {
451
+ impl < V : JoinSemiLattice + Clone + HasBottom > JoinSemiLattice for StateData < V > {
440
452
fn join ( & mut self , other : & Self ) -> bool {
441
- self . map . join ( & other. map )
453
+ let mut changed = false ;
454
+ #[ allow( rustc:: potential_query_instability) ]
455
+ for ( i, v) in other. map . iter ( ) {
456
+ match self . map . entry ( * i) {
457
+ StdEntry :: Vacant ( e) => {
458
+ e. insert ( v. clone ( ) ) ;
459
+ changed = true
460
+ }
461
+ StdEntry :: Occupied ( e) => changed |= e. into_mut ( ) . join ( v) ,
462
+ }
463
+ }
464
+ changed
442
465
}
443
466
}
444
467
@@ -476,15 +499,19 @@ impl<V: Clone> Clone for State<V> {
476
499
}
477
500
}
478
501
479
- impl < V : Clone > State < V > {
480
- pub fn new ( init : V , map : & Map ) -> State < V > {
481
- State :: Reachable ( StateData :: from_elem_n ( init , map . value_count ) )
502
+ impl < V : Clone + HasBottom > State < V > {
503
+ pub fn new_reachable ( ) -> State < V > {
504
+ State :: Reachable ( StateData :: new ( ) )
482
505
}
483
506
484
- pub fn all ( & self , f : impl Fn ( & V ) -> bool ) -> bool {
507
+ pub fn all_bottom ( & self ) -> bool {
485
508
match self {
486
- State :: Unreachable => true ,
487
- State :: Reachable ( ref values) => values. map . iter ( ) . all ( f) ,
509
+ State :: Unreachable => false ,
510
+ State :: Reachable ( ref values) =>
511
+ {
512
+ #[ allow( rustc:: potential_query_instability) ]
513
+ values. map . values ( ) . all ( V :: is_bottom)
514
+ }
488
515
}
489
516
}
490
517
@@ -533,9 +560,7 @@ impl<V: Clone> State<V> {
533
560
value : V ,
534
561
) {
535
562
let State :: Reachable ( values) = self else { return } ;
536
- map. for_each_aliasing_place ( place, tail_elem, & mut |vi| {
537
- values. map [ vi] = value. clone ( ) ;
538
- } ) ;
563
+ map. for_each_aliasing_place ( place, tail_elem, & mut |vi| values. insert ( vi, value. clone ( ) ) ) ;
539
564
}
540
565
541
566
/// Low-level method that assigns to a place.
@@ -556,7 +581,7 @@ impl<V: Clone> State<V> {
556
581
pub fn insert_value_idx ( & mut self , target : PlaceIndex , value : V , map : & Map ) {
557
582
let State :: Reachable ( values) = self else { return } ;
558
583
if let Some ( value_index) = map. places [ target] . value_index {
559
- values. map [ value_index] = value;
584
+ values. insert ( value_index, value)
560
585
}
561
586
}
562
587
@@ -575,7 +600,7 @@ impl<V: Clone> State<V> {
575
600
// already been performed.
576
601
if let Some ( target_value) = map. places [ target] . value_index {
577
602
if let Some ( source_value) = map. places [ source] . value_index {
578
- values. map [ target_value] = values. map [ source_value] . clone ( ) ;
603
+ values. insert ( target_value, values. get ( source_value) . clone ( ) ) ;
579
604
}
580
605
}
581
606
for target_child in map. children ( target) {
@@ -631,7 +656,7 @@ impl<V: Clone> State<V> {
631
656
pub fn try_get_idx ( & self , place : PlaceIndex , map : & Map ) -> Option < V > {
632
657
match self {
633
658
State :: Reachable ( values) => {
634
- map. places [ place] . value_index . map ( |v| values. map [ v ] . clone ( ) )
659
+ map. places [ place] . value_index . map ( |v| values. get ( v ) . clone ( ) )
635
660
}
636
661
State :: Unreachable => None ,
637
662
}
@@ -688,7 +713,7 @@ impl<V: Clone> State<V> {
688
713
{
689
714
match self {
690
715
State :: Reachable ( values) => {
691
- map. places [ place] . value_index . map ( |v| values. map [ v ] . clone ( ) ) . unwrap_or ( V :: TOP )
716
+ map. places [ place] . value_index . map ( |v| values. get ( v ) . clone ( ) ) . unwrap_or ( V :: TOP )
692
717
}
693
718
State :: Unreachable => {
694
719
// Because this is unreachable, we can return any value we want.
@@ -698,7 +723,7 @@ impl<V: Clone> State<V> {
698
723
}
699
724
}
700
725
701
- impl < V : JoinSemiLattice + Clone > JoinSemiLattice for State < V > {
726
+ impl < V : JoinSemiLattice + Clone + HasBottom > JoinSemiLattice for State < V > {
702
727
fn join ( & mut self , other : & Self ) -> bool {
703
728
match ( & mut * self , other) {
704
729
( _, State :: Unreachable ) => false ,
@@ -1228,7 +1253,7 @@ where
1228
1253
}
1229
1254
}
1230
1255
1231
- fn debug_with_context_rec < V : Debug + Eq > (
1256
+ fn debug_with_context_rec < V : Debug + Eq + HasBottom > (
1232
1257
place : PlaceIndex ,
1233
1258
place_str : & str ,
1234
1259
new : & StateData < V > ,
@@ -1238,11 +1263,11 @@ fn debug_with_context_rec<V: Debug + Eq>(
1238
1263
) -> std:: fmt:: Result {
1239
1264
if let Some ( value) = map. places [ place] . value_index {
1240
1265
match old {
1241
- None => writeln ! ( f, "{}: {:?}" , place_str, new. map [ value] ) ?,
1266
+ None => writeln ! ( f, "{}: {:?}" , place_str, new. get ( value) ) ?,
1242
1267
Some ( old) => {
1243
- if new. map [ value] != old. map [ value] {
1244
- writeln ! ( f, "\u{001f} -{}: {:?}" , place_str, old. map [ value] ) ?;
1245
- writeln ! ( f, "\u{001f} +{}: {:?}" , place_str, new. map [ value] ) ?;
1268
+ if new. get ( value) != old. get ( value) {
1269
+ writeln ! ( f, "\u{001f} -{}: {:?}" , place_str, old. get ( value) ) ?;
1270
+ writeln ! ( f, "\u{001f} +{}: {:?}" , place_str, new. get ( value) ) ?;
1246
1271
}
1247
1272
}
1248
1273
}
@@ -1274,7 +1299,7 @@ fn debug_with_context_rec<V: Debug + Eq>(
1274
1299
Ok ( ( ) )
1275
1300
}
1276
1301
1277
- fn debug_with_context < V : Debug + Eq > (
1302
+ fn debug_with_context < V : Debug + Eq + HasBottom > (
1278
1303
new : & StateData < V > ,
1279
1304
old : Option < & StateData < V > > ,
1280
1305
map : & Map ,
0 commit comments