Skip to content

Commit 38fa676

Browse files
committed
Precompute values to flood.
1 parent 7c3d551 commit 38fa676

File tree

1 file changed

+51
-19
lines changed

1 file changed

+51
-19
lines changed

compiler/rustc_mir_dataflow/src/value_analysis.rs

+51-19
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
3535
use std::collections::VecDeque;
3636
use std::fmt::{Debug, Formatter};
37+
use std::ops::Range;
3738

3839
use rustc_data_structures::fx::FxHashMap;
3940
use 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

594594
impl 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

Comments
 (0)