Skip to content

Commit 4983996

Browse files
Auto merge of #142821 - cjgillot:jump-threading-single, r=<try>
Compute jump threading opportunities in a single pass
2 parents 52618eb + 1b74a55 commit 4983996

File tree

28 files changed

+1776
-761
lines changed

28 files changed

+1776
-761
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4237,7 +4237,6 @@ dependencies = [
42374237
"either",
42384238
"itertools",
42394239
"rustc_abi",
4240-
"rustc_arena",
42414240
"rustc_ast",
42424241
"rustc_const_eval",
42434242
"rustc_data_structures",

compiler/rustc_mir_dataflow/src/value_analysis.rs

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ rustc_index::newtype_index!(
2424

2525
rustc_index::newtype_index!(
2626
/// This index uniquely identifies a tracked place and therefore a slot in [`State`].
27-
///
28-
/// It is an implementation detail of this module.
29-
struct ValueIndex {}
27+
pub struct ValueIndex {}
3028
);
3129

3230
/// See [`State`].
@@ -211,22 +209,9 @@ impl<V: Clone + HasBottom> State<V> {
211209
/// The target place must have been flooded before calling this method.
212210
pub fn insert_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map<'_>) {
213211
let State::Reachable(values) = self else { return };
214-
215-
// If both places are tracked, we copy the value to the target.
216-
// If the target is tracked, but the source is not, we do nothing, as invalidation has
217-
// already been performed.
218-
if let Some(target_value) = map.places[target].value_index
219-
&& let Some(source_value) = map.places[source].value_index
220-
{
221-
values.insert(target_value, values.get(source_value).clone());
222-
}
223-
for target_child in map.children(target) {
224-
// Try to find corresponding child and recurse. Reasoning is similar as above.
225-
let projection = map.places[target_child].proj_elem.unwrap();
226-
if let Some(source_child) = map.projections.get(&(source, projection)) {
227-
self.insert_place_idx(target_child, *source_child, map);
228-
}
229-
}
212+
map.for_each_value_pair(target, source, &mut |target, source| {
213+
values.insert(target, values.get(source).clone());
214+
});
230215
}
231216

232217
/// Helper method to interpret `target = result`.
@@ -677,6 +662,26 @@ impl<'tcx> Map<'tcx> {
677662
self.find_extra(place, [TrackElem::DerefLen])
678663
}
679664

665+
/// Locates the value corresponding to the given place.
666+
pub fn value(&self, place: PlaceIndex) -> Option<ValueIndex> {
667+
self.places[place].value_index
668+
}
669+
670+
/// Locates the value corresponding to the given place.
671+
pub fn find_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
672+
self.value(self.find(place)?)
673+
}
674+
675+
/// Locates the value corresponding to the given discriminant.
676+
pub fn find_discr_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
677+
self.value(self.find_discr(place)?)
678+
}
679+
680+
/// Locates the value corresponding to the given length.
681+
pub fn find_len_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
682+
self.value(self.find_len(place)?)
683+
}
684+
680685
/// Iterate over all direct children.
681686
fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> {
682687
Children::new(self, parent)
@@ -689,7 +694,7 @@ impl<'tcx> Map<'tcx> {
689694
///
690695
/// `tail_elem` allows to support discriminants that are not a place in MIR, but that we track
691696
/// as such.
692-
fn for_each_aliasing_place(
697+
pub fn for_each_aliasing_place(
693698
&self,
694699
place: PlaceRef<'_>,
695700
tail_elem: Option<TrackElem>,
@@ -745,11 +750,15 @@ impl<'tcx> Map<'tcx> {
745750
}
746751
}
747752

753+
/// Return the range of value indices inside this place.
754+
pub fn values_inside(&self, root: PlaceIndex) -> &[ValueIndex] {
755+
let range = self.inner_values[root].clone();
756+
&self.inner_values_buffer[range]
757+
}
758+
748759
/// Invoke a function on each value in the given place and all descendants.
749760
fn for_each_value_inside(&self, root: PlaceIndex, f: &mut impl FnMut(ValueIndex)) {
750-
let range = self.inner_values[root].clone();
751-
let values = &self.inner_values_buffer[range];
752-
for &v in values {
761+
for &v in self.values_inside(root) {
753762
f(v)
754763
}
755764
}
@@ -778,6 +787,31 @@ impl<'tcx> Map<'tcx> {
778787
}
779788
}
780789
}
790+
791+
/// Recursively iterates on each value contained in `target`, paired with matching projection
792+
/// inside `source`.
793+
pub fn for_each_value_pair(
794+
&self,
795+
target: PlaceIndex,
796+
source: PlaceIndex,
797+
f: &mut impl FnMut(ValueIndex, ValueIndex),
798+
) {
799+
// If both places are tracked, we copy the value to the target.
800+
// If the target is tracked, but the source is not, we do nothing, as invalidation has
801+
// already been performed.
802+
if let Some(target_value) = self.places[target].value_index
803+
&& let Some(source_value) = self.places[source].value_index
804+
{
805+
f(target_value, source_value)
806+
}
807+
for target_child in self.children(target) {
808+
// Try to find corresponding child and recurse. Reasoning is similar as above.
809+
let projection = self.places[target_child].proj_elem.unwrap();
810+
if let Some(source_child) = self.projections.get(&(source, projection)) {
811+
self.for_each_value_pair(target_child, *source_child, f);
812+
}
813+
}
814+
}
781815
}
782816

783817
/// This is the information tracked for every [`PlaceIndex`] and is stored by [`Map`].

compiler/rustc_mir_transform/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ edition = "2024"
88
either = "1"
99
itertools = "0.12"
1010
rustc_abi = { path = "../rustc_abi" }
11-
rustc_arena = { path = "../rustc_arena" }
1211
rustc_ast = { path = "../rustc_ast" }
1312
rustc_const_eval = { path = "../rustc_const_eval" }
1413
rustc_data_structures = { path = "../rustc_data_structures" }

0 commit comments

Comments
 (0)