64
64
//! methods. It effectively does a reverse walk of the AST; whenever we
65
65
//! reach a loop node, we iterate until a fixed point is reached.
66
66
//!
67
- //! ## The `Users` struct
67
+ //! ## The `users_*` fields
68
68
//!
69
69
//! At each live node `N`, we track three pieces of information for each
70
- //! variable `V` (these are encapsulated in the `Users` struct ):
70
+ //! variable `V` (these are in the `users_*` fields ):
71
71
//!
72
72
//! - `reader`: the `LiveNode` ID of some node which will read the value
73
73
//! that `V` holds on entry to `N`. Formally: a node `M` such
@@ -536,21 +536,6 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
536
536
// Actually we compute just a bit more than just liveness, but we use
537
537
// the same basic propagation framework in all cases.
538
538
539
- #[ derive( Clone , Copy ) ]
540
- struct Users {
541
- reader : LiveNode ,
542
- writer : LiveNode ,
543
- used : bool
544
- }
545
-
546
- fn invalid_users ( ) -> Users {
547
- Users {
548
- reader : invalid_node ( ) ,
549
- writer : invalid_node ( ) ,
550
- used : false
551
- }
552
- }
553
-
554
539
#[ derive( Copy , Clone ) ]
555
540
struct Specials {
556
541
exit_ln : LiveNode ,
@@ -567,7 +552,14 @@ struct Liveness<'a, 'tcx: 'a> {
567
552
tables : & ' a ty:: TypeckTables < ' tcx > ,
568
553
s : Specials ,
569
554
successors : Vec < LiveNode > ,
570
- users : Vec < Users > ,
555
+
556
+ // We used to have a single `users: Vec<Users>` field here, where `Users`
557
+ // had `reader`, `writer` and `used` fields. But the number of users can
558
+ // get very large, and it's more compact to store the data in three
559
+ // separate `Vec`s so that no space is wasted for padding.
560
+ users_reader : Vec < LiveNode > ,
561
+ users_writer : Vec < LiveNode > ,
562
+ users_used : Vec < bool > ,
571
563
572
564
// mappings from loop node ID to LiveNode
573
565
// ("break" label should map to loop node ID,
@@ -592,13 +584,16 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
592
584
593
585
let num_live_nodes = ir. num_live_nodes ;
594
586
let num_vars = ir. num_vars ;
587
+ let num_users = num_live_nodes * num_vars;
595
588
596
589
Liveness {
597
590
ir,
598
591
tables,
599
592
s : specials,
600
593
successors : vec ! [ invalid_node( ) ; num_live_nodes] ,
601
- users : vec ! [ invalid_users( ) ; num_live_nodes * num_vars] ,
594
+ users_reader : vec ! [ invalid_node( ) ; num_users] ,
595
+ users_writer : vec ! [ invalid_node( ) ; num_users] ,
596
+ users_used : vec ! [ false ; num_users] ,
602
597
break_ln : NodeMap ( ) ,
603
598
cont_ln : NodeMap ( ) ,
604
599
}
@@ -665,7 +660,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
665
660
fn live_on_entry ( & self , ln : LiveNode , var : Variable )
666
661
-> Option < LiveNodeKind > {
667
662
assert ! ( ln. is_valid( ) ) ;
668
- let reader = self . users [ self . idx ( ln, var) ] . reader ;
663
+ let reader = self . users_reader [ self . idx ( ln, var) ] ;
669
664
if reader. is_valid ( ) { Some ( self . ir . lnk ( reader) ) } else { None }
670
665
}
671
666
@@ -680,13 +675,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
680
675
681
676
fn used_on_entry ( & self , ln : LiveNode , var : Variable ) -> bool {
682
677
assert ! ( ln. is_valid( ) ) ;
683
- self . users [ self . idx ( ln, var) ] . used
678
+ self . users_used [ self . idx ( ln, var) ]
684
679
}
685
680
686
681
fn assigned_on_entry ( & self , ln : LiveNode , var : Variable )
687
682
-> Option < LiveNodeKind > {
688
683
assert ! ( ln. is_valid( ) ) ;
689
- let writer = self . users [ self . idx ( ln, var) ] . writer ;
684
+ let writer = self . users_writer [ self . idx ( ln, var) ] ;
690
685
if writer. is_valid ( ) { Some ( self . ir . lnk ( writer) ) } else { None }
691
686
}
692
687
@@ -730,9 +725,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
730
725
{
731
726
let wr = & mut wr as & mut dyn Write ;
732
727
write ! ( wr, "[ln({:?}) of kind {:?} reads" , ln. get( ) , self . ir. lnk( ln) ) ;
733
- self . write_vars ( wr, ln, |idx| self . users [ idx] . reader ) ;
728
+ self . write_vars ( wr, ln, |idx| self . users_reader [ idx] ) ;
734
729
write ! ( wr, " writes" ) ;
735
- self . write_vars ( wr, ln, |idx| self . users [ idx] . writer ) ;
730
+ self . write_vars ( wr, ln, |idx| self . users_writer [ idx] ) ;
736
731
write ! ( wr, " precedes {:?}]" , self . successors[ ln. get( ) ] ) ;
737
732
}
738
733
String :: from_utf8 ( wr) . unwrap ( )
@@ -747,7 +742,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
747
742
// only grow during iterations.
748
743
//
749
744
// self.indices(ln) { |idx|
750
- // self.users[idx] = invalid_users();
745
+ // self.users_reader[idx] = invalid_node();
746
+ // self.users_writer[idx] = invalid_node();
747
+ // self.users_used[idx] = false;
751
748
// }
752
749
}
753
750
@@ -756,7 +753,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
756
753
self . successors [ ln. get ( ) ] = succ_ln;
757
754
758
755
self . indices2 ( ln, succ_ln, |this, idx, succ_idx| {
759
- this. users [ idx] = this. users [ succ_idx]
756
+ this. users_reader [ idx] = this. users_reader [ succ_idx] ;
757
+ this. users_writer [ idx] = this. users_writer [ succ_idx] ;
758
+ this. users_used [ idx] = this. users_used [ succ_idx] ;
760
759
} ) ;
761
760
debug ! ( "init_from_succ(ln={}, succ={})" ,
762
761
self . ln_str( ln) , self . ln_str( succ_ln) ) ;
@@ -771,12 +770,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
771
770
772
771
let mut changed = false ;
773
772
self . indices2 ( ln, succ_ln, |this, idx, succ_idx| {
774
- changed |= copy_if_invalid ( this. users [ succ_idx] . reader ,
775
- & mut this. users [ idx] . reader ) ;
776
- changed |= copy_if_invalid ( this. users [ succ_idx] . writer ,
777
- & mut this. users [ idx] . writer ) ;
778
- if this. users [ succ_idx] . used && !this. users [ idx] . used {
779
- this. users [ idx] . used = true ;
773
+ changed |= copy_if_invalid ( this. users_reader [ succ_idx] , & mut this. users_reader [ idx] ) ;
774
+ changed |= copy_if_invalid ( this. users_writer [ succ_idx] , & mut this. users_writer [ idx] ) ;
775
+ if this. users_used [ succ_idx] && !this. users_used [ idx] {
776
+ this. users_used [ idx] = true ;
780
777
changed = true ;
781
778
}
782
779
} ) ;
@@ -800,8 +797,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
800
797
// this) so we just clear out all the data.
801
798
fn define ( & mut self , writer : LiveNode , var : Variable ) {
802
799
let idx = self . idx ( writer, var) ;
803
- self . users [ idx] . reader = invalid_node ( ) ;
804
- self . users [ idx] . writer = invalid_node ( ) ;
800
+ self . users_reader [ idx] = invalid_node ( ) ;
801
+ self . users_writer [ idx] = invalid_node ( ) ;
805
802
806
803
debug ! ( "{:?} defines {:?} (idx={}): {}" , writer, var,
807
804
idx, self . ln_str( writer) ) ;
@@ -813,21 +810,20 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
813
810
ln, acc, var, self . ln_str( ln) ) ;
814
811
815
812
let idx = self . idx ( ln, var) ;
816
- let user = & mut self . users [ idx] ;
817
813
818
814
if ( acc & ACC_WRITE ) != 0 {
819
- user . reader = invalid_node ( ) ;
820
- user . writer = ln;
815
+ self . users_reader [ idx ] = invalid_node ( ) ;
816
+ self . users_writer [ idx ] = ln;
821
817
}
822
818
823
819
// Important: if we both read/write, must do read second
824
820
// or else the write will override.
825
821
if ( acc & ACC_READ ) != 0 {
826
- user . reader = ln;
822
+ self . users_reader [ idx ] = ln;
827
823
}
828
824
829
825
if ( acc & ACC_USE ) != 0 {
830
- user . used = true ;
826
+ self . users_used [ idx ] = true ;
831
827
}
832
828
}
833
829
0 commit comments