diff options
| author | Camille GILLOT <gillot.camille@gmail.com> | 2023-01-16 22:12:36 +0000 |
|---|---|---|
| committer | Camille GILLOT <gillot.camille@gmail.com> | 2023-10-21 06:58:38 +0000 |
| commit | 751a079413a920ab380d63cdffbe99cf2476fe89 (patch) | |
| tree | 9e4d9d302552943b52b3c779cd3f90f725b0b4ab /compiler/rustc_mir_dataflow/src/value_analysis.rs | |
| parent | 3cb0c2e3851c8ec129216f63fdf322276dd1eb96 (diff) | |
| download | rust-751a079413a920ab380d63cdffbe99cf2476fe89.tar.gz rust-751a079413a920ab380d63cdffbe99cf2476fe89.zip | |
Implement JumpThreading pass.
Diffstat (limited to 'compiler/rustc_mir_dataflow/src/value_analysis.rs')
| -rw-r--r-- | compiler/rustc_mir_dataflow/src/value_analysis.rs | 107 |
1 files changed, 89 insertions, 18 deletions
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 04108aeedf6..77c9a22df79 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -463,7 +463,19 @@ impl<V: Clone> Clone for State<V> { } } -impl<V: Clone + HasTop + HasBottom> State<V> { +impl<V: Clone> State<V> { + pub fn new(init: V, map: &Map) -> State<V> { + let values = IndexVec::from_elem_n(init, map.value_count); + State(StateData::Reachable(values)) + } + + pub fn all(&self, f: impl Fn(&V) -> bool) -> bool { + match self.0 { + StateData::Unreachable => true, + StateData::Reachable(ref values) => values.iter().all(f), + } + } + pub fn is_reachable(&self) -> bool { matches!(&self.0, StateData::Reachable(_)) } @@ -472,7 +484,10 @@ impl<V: Clone + HasTop + HasBottom> State<V> { self.0 = StateData::Unreachable; } - pub fn flood_all(&mut self) { + pub fn flood_all(&mut self) + where + V: HasTop, + { self.flood_all_with(V::TOP) } @@ -482,27 +497,40 @@ impl<V: Clone + HasTop + HasBottom> State<V> { } pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { - let StateData::Reachable(values) = &mut self.0 else { return }; - map.for_each_aliasing_place(place, None, &mut |vi| { - values[vi] = value.clone(); - }); + self.flood_with_extra(place, None, map, value) } - pub fn flood(&mut self, place: PlaceRef<'_>, map: &Map) { + pub fn flood(&mut self, place: PlaceRef<'_>, map: &Map) + where + V: HasTop, + { self.flood_with(place, map, V::TOP) } pub fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { - let StateData::Reachable(values) = &mut self.0 else { return }; - map.for_each_aliasing_place(place, Some(TrackElem::Discriminant), &mut |vi| { - values[vi] = value.clone(); - }); + self.flood_with_extra(place, Some(TrackElem::Discriminant), map, value) } - pub fn flood_discr(&mut self, place: PlaceRef<'_>, map: &Map) { + pub fn flood_discr(&mut self, place: PlaceRef<'_>, map: &Map) + where + V: HasTop, + { self.flood_discr_with(place, map, V::TOP) } + pub fn flood_with_extra( + &mut self, + place: PlaceRef<'_>, + tail_elem: Option<TrackElem>, + map: &Map, + value: V, + ) { + let StateData::Reachable(values) = &mut self.0 else { return }; + map.for_each_aliasing_place(place, tail_elem, &mut |vi| { + values[vi] = value.clone(); + }); + } + /// Low-level method that assigns to a place. /// This does nothing if the place is not tracked. /// @@ -553,7 +581,10 @@ impl<V: Clone + HasTop + HasBottom> State<V> { } /// Helper method to interpret `target = result`. - pub fn assign(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map) { + pub fn assign(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map) + where + V: HasTop, + { self.flood(target, map); if let Some(target) = map.find(target) { self.insert_idx(target, result, map); @@ -561,7 +592,10 @@ impl<V: Clone + HasTop + HasBottom> State<V> { } /// Helper method for assignments to a discriminant. - pub fn assign_discr(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map) { + pub fn assign_discr(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map) + where + V: HasTop, + { self.flood_discr(target, map); if let Some(target) = map.find_discr(target) { self.insert_idx(target, result, map); @@ -569,12 +603,43 @@ impl<V: Clone + HasTop + HasBottom> State<V> { } /// Retrieve the value stored for a place, or ⊤ if it is not tracked. - pub fn get(&self, place: PlaceRef<'_>, map: &Map) -> V { + pub fn try_get(&self, place: PlaceRef<'_>, map: &Map) -> Option<V> { + let place = map.find(place)?; + self.try_get_idx(place, map) + } + + /// Retrieve the value stored for a place, or ⊤ if it is not tracked. + pub fn try_get_discr(&self, place: PlaceRef<'_>, map: &Map) -> Option<V> { + let place = map.find_discr(place)?; + self.try_get_idx(place, map) + } + + /// Retrieve the value stored for a place index, or ⊤ if it is not tracked. + pub fn try_get_idx(&self, place: PlaceIndex, map: &Map) -> Option<V> { + match &self.0 { + StateData::Reachable(values) => { + map.places[place].value_index.map(|v| values[v].clone()) + } + StateData::Unreachable => { + // Because this is unreachable, we can return any value we want. + None + } + } + } + + /// Retrieve the value stored for a place, or ⊤ if it is not tracked. + pub fn get(&self, place: PlaceRef<'_>, map: &Map) -> V + where + V: HasBottom + HasTop, + { map.find(place).map(|place| self.get_idx(place, map)).unwrap_or(V::TOP) } /// Retrieve the value stored for a place, or ⊤ if it is not tracked. - pub fn get_discr(&self, place: PlaceRef<'_>, map: &Map) -> V { + pub fn get_discr(&self, place: PlaceRef<'_>, map: &Map) -> V + where + V: HasBottom + HasTop, + { match map.find_discr(place) { Some(place) => self.get_idx(place, map), None => V::TOP, @@ -582,7 +647,10 @@ impl<V: Clone + HasTop + HasBottom> State<V> { } /// Retrieve the value stored for a place, or ⊤ if it is not tracked. - pub fn get_len(&self, place: PlaceRef<'_>, map: &Map) -> V { + pub fn get_len(&self, place: PlaceRef<'_>, map: &Map) -> V + where + V: HasBottom + HasTop, + { match map.find_len(place) { Some(place) => self.get_idx(place, map), None => V::TOP, @@ -590,7 +658,10 @@ impl<V: Clone + HasTop + HasBottom> State<V> { } /// Retrieve the value stored for a place index, or ⊤ if it is not tracked. - pub fn get_idx(&self, place: PlaceIndex, map: &Map) -> V { + pub fn get_idx(&self, place: PlaceIndex, map: &Map) -> V + where + V: HasBottom + HasTop, + { match &self.0 { StateData::Reachable(values) => { map.places[place].value_index.map(|v| values[v].clone()).unwrap_or(V::TOP) |
