Skip to content

[perf] test MCP510 #113382

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 126 additions & 10 deletions compiler/rustc_borrowck/src/type_check/liveness/trace.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_index::bit_set::DenseBitSet;
use rustc_index::interval::IntervalSet;
use rustc_infer::infer::canonical::QueryRegionConstraints;
Expand All @@ -7,10 +7,10 @@ use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, HasLocalDecls, Loc
use rustc_middle::traits::query::DropckOutlivesResult;
use rustc_middle::ty::relate::Relate;
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
use rustc_mir_dataflow::impls::{FilteringMovePathIndexMapper, MaybeInitializedPlaces2};
use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex, SparseMovePathIndex};
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
use rustc_mir_dataflow::{Analysis, ResultsCursor};
use rustc_mir_dataflow::{Analysis, ResultsCursor, on_all_children_bits};
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::ObligationCtxt;
Expand Down Expand Up @@ -45,13 +45,33 @@ pub(super) fn trace<'tcx>(
boring_locals: Vec<Local>,
) {
let local_use_map = &LocalUseMap::build(&relevant_live_locals, location_map, typeck.body);

let mut dense_mpis = FxHashMap::default();
// let mut dense_mpis = smallvec::SmallVec::new();
for &local in relevant_live_locals.iter() {
let Some(mpi) = move_data.rev_lookup.find_local(local) else { unreachable!() };

// We only compute initializedness in drop-liveness on locals with drop points.
if local_use_map.drops(local).next().is_none() {
continue;
}

on_all_children_bits(move_data, mpi, |child| {
// dense_mpis.push(child);
let dense_idx = dense_mpis.len();
let sparse_idx = SparseMovePathIndex::from_u32(dense_idx.try_into().unwrap());
dense_mpis.insert(child, sparse_idx);
});
}

let cx = LivenessContext {
typeck,
flow_inits: None,
location_map,
local_use_map,
move_data,
drop_data: FxIndexMap::default(),
dense_mpis,
};

let mut results = LivenessResults::new(cx);
Expand Down Expand Up @@ -81,11 +101,16 @@ struct LivenessContext<'a, 'typeck, 'tcx> {

/// Results of dataflow tracking which variables (and paths) have been
/// initialized. Computed lazily when needed by drop-liveness.
flow_inits: Option<ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>>,
flow_inits: Option<
ResultsCursor<'a, 'tcx, MaybeInitializedPlaces2<'a, 'tcx, FilteringMovePathIndexMapper>>,
>,

/// Index indicating where each variable is assigned, used, or
/// dropped.
local_use_map: &'a LocalUseMap,

// dense_mpis: smallvec::SmallVec<[MovePathIndex; 1]>,
dense_mpis: FxHashMap<MovePathIndex, SparseMovePathIndex>,
}

struct DropData<'tcx> {
Expand Down Expand Up @@ -468,7 +493,10 @@ impl<'a, 'typeck, 'tcx> LivenessContext<'a, 'typeck, 'tcx> {
///
/// This happens as part of the drop-liveness computation: it's the only place checking for
/// maybe-initializedness of `MovePathIndex`es.
fn flow_inits(&mut self) -> &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>> {
fn flow_inits(
&mut self,
) -> &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces2<'a, 'tcx, FilteringMovePathIndexMapper>>
{
self.flow_inits.get_or_insert_with(|| {
let tcx = self.typeck.tcx();
let body = self.typeck.body;
Expand All @@ -484,9 +512,86 @@ impl<'a, 'typeck, 'tcx> LivenessContext<'a, 'typeck, 'tcx> {
// a much, much smaller domain: in our benchmarks, when it's not zero (the most likely
// case), there are a few dozens compared to e.g. thousands or tens of thousands of
// locals and move paths.
let flow_inits = MaybeInitializedPlaces::new(tcx, body, self.move_data)
// eprintln!(
// "computing flow_inits: {} MPIs total, {} relevant MPIs",
// self.move_data.move_paths.len(),
// self.dense_mpis.len()
// );

// FIXME: use the sparse vec + bitset metadata trick instead of a map!

// let map_timer = std::time::Instant::now();
// let mut sparse_map = FxIndexMap::default();
// for (idx, &dense_idx) in self.dense_mpis.iter().enumerate() {
// let sparse_idx = SparseMovePathIndex::from_usize(idx);
// sparse_map.insert(dense_idx, sparse_idx);
// }
// // for local in body.args_iter() {
// // let Some(mpi) = self.move_data.rev_lookup.find_local(local) else { unreachable!() };
// // self.dense_mpis.push(mpi);
// // map.insert(mpi, self.dense_mpis.len());
// // }

// let map_len = sparse_map.len();
// let mapper = FilteringMovePathIndexMapper { sparse_map };
// let map_elapsed = map_timer.elapsed();

// // let mapper = rustc_mir_dataflow::impls::NoOpMapper;

// let sparse_bitset_timer = std::time::Instant::now();

// // let mut sparse_bitset = Sparse32::new(self.dense_mpis.len());
// // // FIXME: do this in asc order to keep idxes stable and not shuffle the vec inside
// // for &dense_idx in self.dense_mpis.iter() {
// // sparse_bitset.insert(dense_idx);
// // }

// let sparse_bitset = Sparse32::new(&self.dense_mpis);

// // let sparse_bitset_elapsed = sparse_bitset_timer.elapsed();
// // let sparse_bitset_len = sparse_bitset.dense.len();

// // let sparse_bitset_timer = std::time::Instant::now();

// let mut sparse_bitset = Sparse::new(
// 1 + self.dense_mpis.iter().max().unwrap().as_usize(),
// self.dense_mpis.len(),
// );
// // FIXME: do this in asc order to keep idxes stable and not shuffle the vec inside
// for &dense_idx in self.dense_mpis.iter() {
// sparse_bitset.insert(dense_idx);
// }
// // also: move this into the sparse ctor, so that prefixes can be computed there after inserting stuff

// sparse_bitset.compute_prefixes();

// // let sparse_bitset_elapsed = sparse_bitset_timer.elapsed();
// // let sparse_bitset_len = sparse_bitset.sparse.len();

// let mapper = sparse_bitset;

// let timer = std::time::Instant::now();
let x = std::mem::take(&mut self.dense_mpis);
let flow_inits = MaybeInitializedPlaces2::new(tcx, body, self.move_data)
.filter_move_paths(x)
// .with_mapper(mapper)
.iterate_to_fixpoint(tcx, body, Some("borrowck"))
.into_results_cursor(body);
// let elapsed = timer.elapsed();

// use std::sync::OnceLock;
// static PROFILE: OnceLock<bool> = OnceLock::new();
// if *PROFILE.get_or_init(|| std::env::var("LETSGO1").is_ok()) {
// eprintln!(
// "flow_inits took {:?} ns, map of {} took: {} ns, sparse bitset of {} took {} ns, {:?}",
// elapsed.as_nanos(),
// map_len,
// map_elapsed.as_nanos(),
// sparse_bitset_len,
// sparse_bitset_elapsed.as_nanos(),
// body.span,
// );
// }
flow_inits
})
}
Expand All @@ -502,13 +607,24 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
/// the cursor to the desired location.
fn initialized_at_curr_loc(&mut self, mpi: MovePathIndex) -> bool {
let flow_inits = self.flow_inits();
let analysis = flow_inits.analysis();
let idx = analysis
.map_index(mpi)
.unwrap_or_else(|| unreachable!("dataflow is somehow missing MPI {mpi:?}"));
let state = flow_inits.get();
if state.contains(mpi) {
if state.contains(idx) {
return true;
}

let move_paths = &flow_inits.analysis().move_data().move_paths;
move_paths[mpi].find_descendant(move_paths, |mpi| state.contains(mpi)).is_some()
let move_paths = &analysis.move_data().move_paths;
move_paths[mpi]
.find_descendant(move_paths, |mpi| {
let idx = analysis
.map_index(mpi)
.unwrap_or_else(|| unreachable!("dataflow is somehow missing MPI {mpi:?}"));
state.contains(idx)
})
.is_some()
}

/// Returns `true` if the local variable (or some part of it) is initialized in
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_data_structures/src/fx.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::hash::BuildHasherDefault;

pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
pub use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet, FxHasher};

pub type StdEntry<'a, K, V> = std::collections::hash_map::Entry<'a, K, V>;

Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_mir_dataflow/src/framework/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,17 @@ where
write!(f, "{}", ctxt.move_data().move_paths[*self])
}
}

impl<C> DebugWithContext<C> for crate::move_paths::SparseMovePathIndex {}
impl<C> DebugWithContext<C> for u32 {}

// impl<'tcx, C> DebugWithContext<C> for crate::move_paths::SparseMovePathIndex
// where
// C: crate::move_paths::HasMoveData<'tcx> +
// C: crate::impls::MovePathIndexMapper
// {
// fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// let
// write!(f, "{}", ctxt.move_data().move_paths[*self])
// }
// }
8 changes: 4 additions & 4 deletions compiler/rustc_mir_dataflow/src/impls/initialized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,22 @@ use crate::{

// Used by both `MaybeInitializedPlaces` and `MaybeUninitializedPlaces`.
pub struct MaybePlacesSwitchIntData<'tcx> {
enum_place: mir::Place<'tcx>,
pub(super) enum_place: mir::Place<'tcx>,
discriminants: Vec<(VariantIdx, Discr<'tcx>)>,
index: usize,
}

impl<'tcx> MaybePlacesSwitchIntData<'tcx> {
/// Creates a `SmallVec` mapping each target in `targets` to its `VariantIdx`.
fn variants(&mut self, targets: &mir::SwitchTargets) -> SmallVec<[VariantIdx; 4]> {
pub(super) fn variants(&mut self, targets: &mir::SwitchTargets) -> SmallVec<[VariantIdx; 4]> {
self.index = 0;
targets.all_values().iter().map(|value| self.next_discr(value.get())).collect()
}

// The discriminant order in the `SwitchInt` targets should match the order yielded by
// `AdtDef::discriminants`. We rely on this to match each discriminant in the targets to its
// corresponding variant in linear time.
fn next_discr(&mut self, value: u128) -> VariantIdx {
pub(super) fn next_discr(&mut self, value: u128) -> VariantIdx {
// An out-of-bounds abort will occur if the discriminant ordering isn't as described above.
loop {
let (variant, discr) = self.discriminants[self.index];
Expand All @@ -49,7 +49,7 @@ impl<'tcx> MaybePlacesSwitchIntData<'tcx> {
}

impl<'tcx> MaybePlacesSwitchIntData<'tcx> {
fn new(
pub(super) fn new(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
block: mir::BasicBlock,
Expand Down
Loading
Loading