Implement JumpThreading pass.
This commit is contained in:
parent
3cb0c2e385
commit
751a079413
27 changed files with 2375 additions and 18 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue