Skip to content

Commit ffcc38a

Browse files
committed
Only record conflicts between relevant locals.
1 parent b4970e4 commit ffcc38a

File tree

1 file changed

+70
-10
lines changed

1 file changed

+70
-10
lines changed

compiler/rustc_mir_transform/src/dest_prop.rs

Lines changed: 70 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@
134134
use rustc_data_structures::fx::FxIndexMap;
135135
use rustc_index::bit_set::{BitMatrix, DenseBitSet};
136136
use rustc_index::interval::SparseIntervalMatrix;
137+
use rustc_index::{IndexVec, newtype_index};
137138
use rustc_middle::bug;
138139
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
139140
use rustc_middle::mir::{
@@ -186,8 +187,13 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
186187
trace!(?candidates);
187188
dest_prop_mir_dump(tcx, body, &points, &live, round_count);
188189

189-
let mut filter =
190-
FilterInformation::filter_liveness(&points, &live, &mut write_info, body);
190+
let mut filter = FilterInformation::filter_liveness(
191+
&points,
192+
&live,
193+
&mut write_info,
194+
body,
195+
&candidates,
196+
);
191197

192198
// This is the set of merges we will apply this round. It is a subset of the candidates.
193199
let mut merges = FxIndexMap::default();
@@ -316,6 +322,45 @@ impl<'tcx> MutVisitor<'tcx> for Merger<'tcx> {
316322
}
317323
}
318324

325+
//////////////////////////////////////////////////////////
326+
// Relevant locals
327+
//
328+
// Small utility to reduce size of the conflict matrix by only considering locals that appear in
329+
// the candidates
330+
331+
newtype_index! {
332+
/// Represent a subset of locals which appear in candidates.
333+
struct RelevantLocal {}
334+
}
335+
336+
#[derive(Debug)]
337+
struct RelevantLocals {
338+
original: IndexVec<RelevantLocal, Local>,
339+
shrink: IndexVec<Local, Option<RelevantLocal>>,
340+
}
341+
342+
impl RelevantLocals {
343+
#[tracing::instrument(level = "trace", skip(candidates, num_locals), ret)]
344+
fn compute(candidates: &Candidates, num_locals: usize) -> RelevantLocals {
345+
let mut original = IndexVec::with_capacity(candidates.c.len());
346+
let mut shrink = IndexVec::from_elem_n(None, num_locals);
347+
348+
// Mark a local as relevant and record it into the maps.
349+
let mut declare = |local| {
350+
shrink.get_or_insert_with(local, || original.push(local));
351+
};
352+
353+
for (&src, destinations) in candidates.c.iter() {
354+
declare(src);
355+
for &dest in destinations {
356+
declare(dest)
357+
}
358+
}
359+
360+
RelevantLocals { original, shrink }
361+
}
362+
}
363+
319364
//////////////////////////////////////////////////////////
320365
// Liveness filtering
321366
//
@@ -324,7 +369,8 @@ impl<'tcx> MutVisitor<'tcx> for Merger<'tcx> {
324369
struct FilterInformation<'a, 'tcx> {
325370
body: &'a Body<'tcx>,
326371
points: &'a DenseLocationMap,
327-
conflicts: BitMatrix<Local, Local>,
372+
relevant: RelevantLocals,
373+
conflicts: BitMatrix<RelevantLocal, RelevantLocal>,
328374
write_info: &'a mut WriteInfo,
329375
at: Location,
330376
}
@@ -371,12 +417,16 @@ impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
371417
live: &SparseIntervalMatrix<Local, PointIndex>,
372418
write_info: &'a mut WriteInfo,
373419
body: &'a Body<'tcx>,
420+
candidates: &Candidates,
374421
) -> Self {
375422
let num_locals = body.local_decls.len();
423+
let relevant = RelevantLocals::compute(candidates, num_locals);
424+
let num_relevant = relevant.original.len();
376425
let mut this = FilterInformation {
377426
body,
427+
relevant,
378428
points,
379-
conflicts: BitMatrix::new(num_locals, num_locals),
429+
conflicts: BitMatrix::new(num_relevant, num_relevant),
380430
// We don't actually store anything at this scope, we just keep things here to be able
381431
// to reuse the allocation.
382432
write_info,
@@ -404,22 +454,28 @@ impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
404454
}
405455

406456
fn record_conflicts(&mut self, live: &SparseIntervalMatrix<Local, PointIndex>) {
407-
let writes = &self.write_info.writes;
408-
let skip_pair = self.write_info.skip_pair;
457+
let writes = self.write_info.writes.iter().filter_map(|&p| self.relevant.shrink[p]);
458+
459+
let skip_pair = self.write_info.skip_pair.and_then(|(p, q)| {
460+
let p = self.relevant.shrink[p]?;
461+
let q = self.relevant.shrink[q]?;
462+
Some((p, q))
463+
});
464+
409465
let at = self.points.point_from_location(self.at);
410466

411-
for &p in writes {
412-
for &q in writes {
467+
for p in writes.clone() {
468+
for q in writes.clone() {
413469
if p != q && skip_pair != Some((p, q)) && skip_pair != Some((q, p)) {
414470
self.conflicts.insert(p, q);
415471
}
416472
}
417473

418-
for q in live.rows() {
474+
for (q, &original_q) in self.relevant.original.iter_enumerated() {
419475
if p != q
420476
&& skip_pair != Some((p, q))
421477
&& skip_pair != Some((q, p))
422-
&& live.contains(q, at)
478+
&& live.contains(original_q, at)
423479
{
424480
self.conflicts.insert(p, q);
425481
}
@@ -430,14 +486,18 @@ impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
430486
#[tracing::instrument(level = "trace", skip(self))]
431487
fn record_merge(&mut self, src: Local, dest: Local) {
432488
trace!(?self.conflicts, "pre");
489+
let src = self.relevant.shrink[src].expect("merged locals are relevant");
490+
let dest = self.relevant.shrink[dest].expect("merged locals are relevant");
433491
self.conflicts.union_rows(src, dest);
434492
self.conflicts.union_cols(src, dest);
435493
trace!(?self.conflicts, "post");
436494
}
437495

438496
#[tracing::instrument(level = "trace", skip(self), ret)]
439497
fn find_non_conflicting(&self, src: Local, candidates: &Vec<Local>) -> Option<Local> {
498+
let src = self.relevant.shrink[src].expect("merged locals are relevant");
440499
candidates.iter().copied().find(|&dest| {
500+
let dest = self.relevant.shrink[dest].expect("merged locals are relevant");
441501
!self.conflicts.contains(src, dest) && !self.conflicts.contains(dest, src)
442502
})
443503
}

0 commit comments

Comments
 (0)