Limit creation of tracked place directly.
This commit is contained in:
parent
9a6c04f5d0
commit
c48756cdbf
2 changed files with 22 additions and 11 deletions
|
@ -599,10 +599,11 @@ impl Map {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
filter: impl FnMut(Ty<'tcx>) -> bool,
|
filter: impl FnMut(Ty<'tcx>) -> bool,
|
||||||
|
place_limit: Option<usize>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut map = Self::new();
|
let mut map = Self::new();
|
||||||
let exclude = excluded_locals(body);
|
let exclude = excluded_locals(body);
|
||||||
map.register_with_filter(tcx, body, filter, exclude);
|
map.register_with_filter(tcx, body, filter, exclude, place_limit);
|
||||||
debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len());
|
debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len());
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
|
@ -614,12 +615,20 @@ impl Map {
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
mut filter: impl FnMut(Ty<'tcx>) -> bool,
|
mut filter: impl FnMut(Ty<'tcx>) -> bool,
|
||||||
exclude: BitSet<Local>,
|
exclude: BitSet<Local>,
|
||||||
|
place_limit: Option<usize>,
|
||||||
) {
|
) {
|
||||||
// We use this vector as stack, pushing and popping projections.
|
// We use this vector as stack, pushing and popping projections.
|
||||||
let mut projection = Vec::new();
|
let mut projection = Vec::new();
|
||||||
for (local, decl) in body.local_decls.iter_enumerated() {
|
for (local, decl) in body.local_decls.iter_enumerated() {
|
||||||
if !exclude.contains(local) {
|
if !exclude.contains(local) {
|
||||||
self.register_with_filter_rec(tcx, local, &mut projection, decl.ty, &mut filter);
|
self.register_with_filter_rec(
|
||||||
|
tcx,
|
||||||
|
local,
|
||||||
|
&mut projection,
|
||||||
|
decl.ty,
|
||||||
|
&mut filter,
|
||||||
|
place_limit,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -634,7 +643,12 @@ impl Map {
|
||||||
projection: &mut Vec<PlaceElem<'tcx>>,
|
projection: &mut Vec<PlaceElem<'tcx>>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
filter: &mut impl FnMut(Ty<'tcx>) -> bool,
|
filter: &mut impl FnMut(Ty<'tcx>) -> bool,
|
||||||
|
place_limit: Option<usize>,
|
||||||
) {
|
) {
|
||||||
|
if let Some(place_limit) = place_limit && self.value_count >= place_limit {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// We know that the projection only contains trackable elements.
|
// We know that the projection only contains trackable elements.
|
||||||
let place = self.make_place(local, projection).unwrap();
|
let place = self.make_place(local, projection).unwrap();
|
||||||
|
|
||||||
|
@ -672,13 +686,13 @@ impl Map {
|
||||||
projection.push(PlaceElem::Downcast(None, variant));
|
projection.push(PlaceElem::Downcast(None, variant));
|
||||||
let _ = self.make_place(local, projection);
|
let _ = self.make_place(local, projection);
|
||||||
projection.push(PlaceElem::Field(field, ty));
|
projection.push(PlaceElem::Field(field, ty));
|
||||||
self.register_with_filter_rec(tcx, local, projection, ty, filter);
|
self.register_with_filter_rec(tcx, local, projection, ty, filter, place_limit);
|
||||||
projection.pop();
|
projection.pop();
|
||||||
projection.pop();
|
projection.pop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
projection.push(PlaceElem::Field(field, ty));
|
projection.push(PlaceElem::Field(field, ty));
|
||||||
self.register_with_filter_rec(tcx, local, projection, ty, filter);
|
self.register_with_filter_rec(tcx, local, projection, ty, filter, place_limit);
|
||||||
projection.pop();
|
projection.pop();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,6 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decide which places to track during the analysis.
|
|
||||||
let map = Map::from_filter(tcx, body, Ty::is_scalar);
|
|
||||||
|
|
||||||
// We want to have a somewhat linear runtime w.r.t. the number of statements/terminators.
|
// We want to have a somewhat linear runtime w.r.t. the number of statements/terminators.
|
||||||
// Let's call this number `n`. Dataflow analysis has `O(h*n)` transfer function
|
// Let's call this number `n`. Dataflow analysis has `O(h*n)` transfer function
|
||||||
// applications, where `h` is the height of the lattice. Because the height of our lattice
|
// applications, where `h` is the height of the lattice. Because the height of our lattice
|
||||||
|
@ -48,10 +45,10 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp {
|
||||||
// `O(num_nodes * tracked_places * n)` in terms of time complexity. Since the number of
|
// `O(num_nodes * tracked_places * n)` in terms of time complexity. Since the number of
|
||||||
// map nodes is strongly correlated to the number of tracked places, this becomes more or
|
// map nodes is strongly correlated to the number of tracked places, this becomes more or
|
||||||
// less `O(n)` if we place a constant limit on the number of tracked places.
|
// less `O(n)` if we place a constant limit on the number of tracked places.
|
||||||
if tcx.sess.mir_opt_level() < 4 && map.tracked_places() > PLACE_LIMIT {
|
let place_limit = if tcx.sess.mir_opt_level() < 4 { Some(PLACE_LIMIT) } else { None };
|
||||||
debug!("aborted dataflow const prop due to too many tracked places");
|
|
||||||
return;
|
// Decide which places to track during the analysis.
|
||||||
}
|
let map = Map::from_filter(tcx, body, Ty::is_scalar, place_limit);
|
||||||
|
|
||||||
// Perform the actual dataflow analysis.
|
// Perform the actual dataflow analysis.
|
||||||
let analysis = ConstAnalysis::new(tcx, body, map);
|
let analysis = ConstAnalysis::new(tcx, body, map);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue