6464//! methods. It effectively does a reverse walk of the AST; whenever we
6565//! reach a loop node, we iterate until a fixed point is reached.
6666//!
67- //! ## The `Users` struct
67+ //! ## The `users_*` fields
6868//!
6969//! 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 ):
7171//!
7272//! - `reader`: the `LiveNode` ID of some node which will read the value
7373//! 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) {
536536// Actually we compute just a bit more than just liveness, but we use
537537// the same basic propagation framework in all cases.
538538
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-
554539#[ derive( Copy , Clone ) ]
555540struct Specials {
556541 exit_ln : LiveNode ,
@@ -567,7 +552,14 @@ struct Liveness<'a, 'tcx: 'a> {
567552 tables : & ' a ty:: TypeckTables < ' tcx > ,
568553 s : Specials ,
569554 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 > ,
571563
572564 // mappings from loop node ID to LiveNode
573565 // ("break" label should map to loop node ID,
@@ -592,13 +584,16 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
592584
593585 let num_live_nodes = ir. num_live_nodes ;
594586 let num_vars = ir. num_vars ;
587+ let num_users = num_live_nodes * num_vars;
595588
596589 Liveness {
597590 ir,
598591 tables,
599592 s : specials,
600593 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] ,
602597 break_ln : NodeMap ( ) ,
603598 cont_ln : NodeMap ( ) ,
604599 }
@@ -665,7 +660,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
665660 fn live_on_entry ( & self , ln : LiveNode , var : Variable )
666661 -> Option < LiveNodeKind > {
667662 assert ! ( ln. is_valid( ) ) ;
668- let reader = self . users [ self . idx ( ln, var) ] . reader ;
663+ let reader = self . users_reader [ self . idx ( ln, var) ] ;
669664 if reader. is_valid ( ) { Some ( self . ir . lnk ( reader) ) } else { None }
670665 }
671666
@@ -680,13 +675,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
680675
681676 fn used_on_entry ( & self , ln : LiveNode , var : Variable ) -> bool {
682677 assert ! ( ln. is_valid( ) ) ;
683- self . users [ self . idx ( ln, var) ] . used
678+ self . users_used [ self . idx ( ln, var) ]
684679 }
685680
686681 fn assigned_on_entry ( & self , ln : LiveNode , var : Variable )
687682 -> Option < LiveNodeKind > {
688683 assert ! ( ln. is_valid( ) ) ;
689- let writer = self . users [ self . idx ( ln, var) ] . writer ;
684+ let writer = self . users_writer [ self . idx ( ln, var) ] ;
690685 if writer. is_valid ( ) { Some ( self . ir . lnk ( writer) ) } else { None }
691686 }
692687
@@ -730,9 +725,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
730725 {
731726 let wr = & mut wr as & mut dyn Write ;
732727 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] ) ;
734729 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] ) ;
736731 write ! ( wr, " precedes {:?}]" , self . successors[ ln. get( ) ] ) ;
737732 }
738733 String :: from_utf8 ( wr) . unwrap ( )
@@ -747,7 +742,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
747742 // only grow during iterations.
748743 //
749744 // 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;
751748 // }
752749 }
753750
@@ -756,7 +753,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
756753 self . successors [ ln. get ( ) ] = succ_ln;
757754
758755 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] ;
760759 } ) ;
761760 debug ! ( "init_from_succ(ln={}, succ={})" ,
762761 self . ln_str( ln) , self . ln_str( succ_ln) ) ;
@@ -771,12 +770,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
771770
772771 let mut changed = false ;
773772 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 ;
780777 changed = true ;
781778 }
782779 } ) ;
@@ -800,8 +797,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
800797 // this) so we just clear out all the data.
801798 fn define ( & mut self , writer : LiveNode , var : Variable ) {
802799 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 ( ) ;
805802
806803 debug ! ( "{:?} defines {:?} (idx={}): {}" , writer, var,
807804 idx, self . ln_str( writer) ) ;
@@ -813,21 +810,20 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
813810 ln, acc, var, self . ln_str( ln) ) ;
814811
815812 let idx = self . idx ( ln, var) ;
816- let user = & mut self . users [ idx] ;
817813
818814 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;
821817 }
822818
823819 // Important: if we both read/write, must do read second
824820 // or else the write will override.
825821 if ( acc & ACC_READ ) != 0 {
826- user . reader = ln;
822+ self . users_reader [ idx ] = ln;
827823 }
828824
829825 if ( acc & ACC_USE ) != 0 {
830- user . used = true ;
826+ self . users_used [ idx ] = true ;
831827 }
832828 }
833829
0 commit comments