3434
3535use std:: collections:: VecDeque ;
3636use std:: fmt:: { Debug , Formatter } ;
37+ use std:: ops:: Range ;
3738
3839use rustc_data_structures:: fx:: FxHashMap ;
3940use rustc_index:: bit_set:: BitSet ;
@@ -448,10 +449,8 @@ impl<V: Clone + HasTop + HasBottom> State<V> {
448449
449450 pub fn flood_with ( & mut self , place : PlaceRef < ' _ > , map : & Map , value : V ) {
450451 let StateData :: Reachable ( values) = & mut self . 0 else { return } ;
451- map. for_each_aliasing_place ( place, None , & mut |place| {
452- if let Some ( vi) = map. places [ place] . value_index {
453- values[ vi] = value. clone ( ) ;
454- }
452+ map. for_each_aliasing_place ( place, None , & mut |vi| {
453+ values[ vi] = value. clone ( ) ;
455454 } ) ;
456455 }
457456
@@ -461,10 +460,8 @@ impl<V: Clone + HasTop + HasBottom> State<V> {
461460
462461 pub fn flood_discr_with ( & mut self , place : PlaceRef < ' _ > , map : & Map , value : V ) {
463462 let StateData :: Reachable ( values) = & mut self . 0 else { return } ;
464- map. for_each_aliasing_place ( place, Some ( TrackElem :: Discriminant ) , & mut |place| {
465- if let Some ( vi) = map. places [ place] . value_index {
466- values[ vi] = value. clone ( ) ;
467- }
463+ map. for_each_aliasing_place ( place, Some ( TrackElem :: Discriminant ) , & mut |vi| {
464+ values[ vi] = value. clone ( ) ;
468465 } ) ;
469466 }
470467
@@ -589,6 +586,9 @@ pub struct Map {
589586 projections : FxHashMap < ( PlaceIndex , TrackElem ) , PlaceIndex > ,
590587 places : IndexVec < PlaceIndex , PlaceInfo > ,
591588 value_count : usize ,
589+ // The Range corresponds to a slice into `inner_values_buffer`.
590+ inner_values : IndexVec < PlaceIndex , Range < usize > > ,
591+ inner_values_buffer : Vec < ValueIndex > ,
592592}
593593
594594impl Map {
@@ -598,6 +598,8 @@ impl Map {
598598 projections : FxHashMap :: default ( ) ,
599599 places : IndexVec :: new ( ) ,
600600 value_count : 0 ,
601+ inner_values : IndexVec :: new ( ) ,
602+ inner_values_buffer : Vec :: new ( ) ,
601603 }
602604 }
603605
@@ -665,6 +667,14 @@ impl Map {
665667 // And push the eventual children places to the worklist.
666668 self . register_children ( tcx, place, ty, & filter, & mut worklist) ;
667669 }
670+
671+ self . inner_values_buffer = Vec :: with_capacity ( self . value_count ) ;
672+ self . inner_values = IndexVec :: from_elem ( 0 ..0 , & self . places ) ;
673+ for local in body. local_decls . indices ( ) {
674+ if let Some ( place) = self . locals [ local] {
675+ self . cache_preorder_invoke ( place) ;
676+ }
677+ }
668678 }
669679
670680 /// Potentially register the (local, projection) place and its fields, recursively.
@@ -718,6 +728,25 @@ impl Map {
718728 } ) ;
719729 }
720730
731+ /// Precompute the list of values inside `root` and store it inside
732+ /// as a slice within `inner_values_buffer`.
733+ fn cache_preorder_invoke ( & mut self , root : PlaceIndex ) {
734+ let start = self . inner_values_buffer . len ( ) ;
735+ if let Some ( vi) = self . places [ root] . value_index {
736+ self . inner_values_buffer . push ( vi) ;
737+ }
738+
739+ // We manually iterate instead of using `children` as we need to mutate `self`.
740+ let mut next_child = self . places [ root] . first_child ;
741+ while let Some ( child) = next_child {
742+ self . cache_preorder_invoke ( child) ;
743+ next_child = self . places [ child] . next_sibling ;
744+ }
745+
746+ let end = self . inner_values_buffer . len ( ) ;
747+ self . inner_values [ root] = start..end;
748+ }
749+
721750 /// Returns the number of tracked places, i.e., those for which a value can be stored.
722751 pub fn tracked_places ( & self ) -> usize {
723752 self . value_count
@@ -768,11 +797,11 @@ impl Map {
768797 ///
769798 /// `tail_elem` allows to support discriminants that are not a place in MIR, but that we track
770799 /// as such.
771- pub fn for_each_aliasing_place (
800+ fn for_each_aliasing_place (
772801 & self ,
773802 place : PlaceRef < ' _ > ,
774803 tail_elem : Option < TrackElem > ,
775- f : & mut impl FnMut ( PlaceIndex ) ,
804+ f : & mut impl FnMut ( ValueIndex ) ,
776805 ) {
777806 if place. is_indirect ( ) {
778807 // We do not track indirect places.
@@ -789,7 +818,9 @@ impl Map {
789818 . chain ( tail_elem. map ( Ok ) . into_iter ( ) ) ;
790819 for elem in elems {
791820 // A field aliases the parent place.
792- f ( index) ;
821+ if let Some ( vi) = self . places [ index] . value_index {
822+ f ( vi) ;
823+ }
793824
794825 let Ok ( elem) = elem else { return } ;
795826 let sub = self . apply ( index, elem) ;
@@ -803,15 +834,15 @@ impl Map {
803834 return ;
804835 }
805836 }
806- self . preorder_invoke ( index, f) ;
837+ self . for_each_value_inside ( index, f) ;
807838 }
808839
809840 /// Invoke the given function on all the descendants of the given place, except one branch.
810841 fn for_each_variant_sibling (
811842 & self ,
812843 parent : PlaceIndex ,
813844 preserved_child : Option < PlaceIndex > ,
814- f : & mut impl FnMut ( PlaceIndex ) ,
845+ f : & mut impl FnMut ( ValueIndex ) ,
815846 ) {
816847 for sibling in self . children ( parent) {
817848 let elem = self . places [ sibling] . proj_elem ;
@@ -821,16 +852,17 @@ impl Map {
821852 // Only invalidate the other variants, the current one is fine.
822853 && Some ( sibling) != preserved_child
823854 {
824- self . preorder_invoke ( sibling, f) ;
855+ self . for_each_value_inside ( sibling, f) ;
825856 }
826857 }
827858 }
828859
829- /// Invoke a function on the given place and all descendants.
830- fn preorder_invoke ( & self , root : PlaceIndex , f : & mut impl FnMut ( PlaceIndex ) ) {
831- f ( root) ;
832- for child in self . children ( root) {
833- self . preorder_invoke ( child, f) ;
860+ /// Invoke a function on each value in the given place and all descendants.
861+ fn for_each_value_inside ( & self , root : PlaceIndex , f : & mut impl FnMut ( ValueIndex ) ) {
862+ let range = self . inner_values [ root] . clone ( ) ;
863+ let values = & self . inner_values_buffer [ range] ;
864+ for & v in values {
865+ f ( v)
834866 }
835867 }
836868}
0 commit comments