Skip to content

Commit b42852b

Browse files
committed
Auto merge of #156046 - Amanieu:move-elimination, r=<try>
[WIP] MIR move elimination pass
2 parents 0469a92 + d431a34 commit b42852b

14 files changed

Lines changed: 1238 additions & 48 deletions

File tree

compiler/rustc_index/src/interval.rs

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::iter::Step;
22
use std::marker::PhantomData;
3-
use std::ops::{Bound, Range, RangeBounds};
3+
use std::ops::{Bound, RangeBounds};
4+
use std::range::RangeInclusive;
45

56
use smallvec::SmallVec;
67

@@ -59,11 +60,14 @@ impl<I: Idx> IntervalSet<I> {
5960
}
6061

6162
/// Iterates through intervals stored in the set, in order.
62-
pub fn iter_intervals(&self) -> impl Iterator<Item = std::ops::Range<I>>
63+
pub fn iter_intervals(&self) -> impl Iterator<Item = RangeInclusive<I>>
6364
where
6465
I: Step,
6566
{
66-
self.map.iter().map(|&(start, end)| I::new(start as usize)..I::new(end as usize + 1))
67+
self.map.iter().map(|&(start, end)| RangeInclusive {
68+
start: I::new(start as usize),
69+
last: I::new(end as usize),
70+
})
6771
}
6872

6973
/// Returns true if we increased the number of elements present.
@@ -164,6 +168,35 @@ impl<I: Idx> IntervalSet<I> {
164168
);
165169
}
166170

171+
/// Specialized version of `insert` when we know that the inserted range is
172+
/// *after* any contained.
173+
pub fn append_range(&mut self, range: impl RangeBounds<I> + Clone) {
174+
let start = inclusive_start(range.clone());
175+
let Some(end) = inclusive_end(self.domain, range) else {
176+
// empty range
177+
return;
178+
};
179+
if start > end {
180+
return;
181+
}
182+
183+
if let Some((_, last_end)) = self.map.last_mut() {
184+
assert!(*last_end < start);
185+
if start == *last_end + 1 {
186+
*last_end = end;
187+
} else {
188+
self.map.push((start, end));
189+
}
190+
} else {
191+
self.map.push((start, end));
192+
}
193+
194+
debug_assert!(
195+
self.check_invariants(),
196+
"wrong intervals after append {start:?}..={end:?} to {self:?}"
197+
);
198+
}
199+
167200
pub fn contains(&self, needle: I) -> bool {
168201
let needle = needle.index() as u32;
169202
let Some(last) = self.map.partition_point(|r| r.0 <= needle).checked_sub(1) else {
@@ -180,11 +213,12 @@ impl<I: Idx> IntervalSet<I> {
180213
{
181214
let mut sup_iter = self.iter_intervals();
182215
let mut current = None;
183-
let contains = |sup: Range<I>, sub: Range<I>, current: &mut Option<Range<I>>| {
184-
if sup.end < sub.start {
185-
// if `sup.end == sub.start`, the next sup doesn't contain `sub.start`
216+
let contains = |sup: RangeInclusive<I>,
217+
sub: RangeInclusive<I>,
218+
current: &mut Option<RangeInclusive<I>>| {
219+
if sup.last < sub.start {
186220
None // continue to the next sup
187-
} else if sup.end >= sub.end && sup.start <= sub.start {
221+
} else if sup.last >= sub.last && sup.start <= sub.start {
188222
*current = Some(sup); // save the current sup
189223
Some(true)
190224
} else {
@@ -194,8 +228,8 @@ impl<I: Idx> IntervalSet<I> {
194228
other.iter_intervals().all(|sub| {
195229
current
196230
.take()
197-
.and_then(|sup| contains(sup, sub.clone(), &mut current))
198-
.or_else(|| sup_iter.find_map(|sup| contains(sup, sub.clone(), &mut current)))
231+
.and_then(|sup| contains(sup, sub, &mut current))
232+
.or_else(|| sup_iter.find_map(|sup| contains(sup, sub, &mut current)))
199233
.unwrap_or(false)
200234
})
201235
}
@@ -212,11 +246,11 @@ impl<I: Idx> IntervalSet<I> {
212246
let mut other_current = other_iter.next()?;
213247

214248
loop {
215-
if self_current.end <= other_current.start {
249+
if self_current.last < other_current.start {
216250
self_current = self_iter.next()?;
217251
continue;
218252
}
219-
if other_current.end <= self_current.start {
253+
if other_current.last < self_current.start {
220254
other_current = other_iter.next()?;
221255
continue;
222256
}
@@ -340,6 +374,12 @@ impl<R: Idx, C: Step + Idx> SparseIntervalMatrix<R, C> {
340374
self.rows.get(row)
341375
}
342376

377+
pub fn clear_row(&mut self, row: R) {
378+
if let Some(row) = self.rows.get_mut(row) {
379+
row.clear();
380+
}
381+
}
382+
343383
fn ensure_row(&mut self, row: R) -> &mut IntervalSet<C> {
344384
self.rows.ensure_contains_elem(row, || IntervalSet::new(self.column_size))
345385
}
@@ -363,6 +403,16 @@ impl<R: Idx, C: Step + Idx> SparseIntervalMatrix<R, C> {
363403
write_row.union(read_row)
364404
}
365405

406+
pub fn disjoint_rows(&self, a: R, b: R) -> bool
407+
where
408+
C: Step,
409+
{
410+
let (Some(a), Some(b)) = (self.rows.get(a), self.rows.get(b)) else {
411+
return true;
412+
};
413+
a.disjoint(b)
414+
}
415+
366416
pub fn insert_all_into_row(&mut self, row: R) {
367417
self.ensure_row(row).insert_all();
368418
}
@@ -379,6 +429,10 @@ impl<R: Idx, C: Step + Idx> SparseIntervalMatrix<R, C> {
379429
self.ensure_row(row).append(point)
380430
}
381431

432+
pub fn append_range(&mut self, row: R, range: impl RangeBounds<C> + Clone) {
433+
self.ensure_row(row).append_range(range)
434+
}
435+
382436
pub fn contains(&self, row: R, point: C) -> bool {
383437
self.row(row).is_some_and(|r| r.contains(point))
384438
}

compiler/rustc_index/src/interval/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ fn insert_collapses() {
55
let mut set = IntervalSet::<u32>::new(10000);
66
set.insert_range(9831..=9837);
77
set.insert_range(43..=9830);
8-
assert_eq!(set.iter_intervals().collect::<Vec<_>>(), [43..9838]);
8+
assert_eq!(set.iter_intervals().collect::<Vec<_>>(), [(43..=9837).into()]);
99
}
1010

1111
#[test]

compiler/rustc_middle/src/mir/syntax.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ pub enum RuntimePhase {
128128
/// disallowed:
129129
/// * [`TerminatorKind::Yield`]
130130
/// * [`TerminatorKind::CoroutineDrop`]
131-
/// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
132131
/// * [`Rvalue::CopyForDeref`]
133132
/// * [`PlaceElem::OpaqueCast`]
134133
/// * [`LocalInfo::DerefTemp`](super::LocalInfo::DerefTemp)
@@ -1452,9 +1451,6 @@ pub enum Rvalue<'tcx> {
14521451
/// This is needed because dataflow analysis needs to distinguish
14531452
/// `dest = Foo { x: ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case that `Foo`
14541453
/// has a destructor.
1455-
///
1456-
/// Disallowed after deaggregation for all aggregate kinds except `Array` and `Coroutine`. After
1457-
/// coroutine lowering, `Coroutine` aggregate kinds are disallowed too.
14581454
Aggregate(Box<AggregateKind<'tcx>>, IndexVec<FieldIdx, Operand<'tcx>>),
14591455

14601456
/// A CopyForDeref is equivalent to a read from a place at the

compiler/rustc_mir_dataflow/src/framework/direction.rs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_middle::mir::{
77

88
use super::visitor::ResultsVisitor;
99
use super::{Analysis, Effect, EffectIndex};
10+
use crate::Results;
1011

1112
pub trait Direction {
1213
const IS_FORWARD: bool;
@@ -40,7 +41,7 @@ pub trait Direction {
4041
/// all locations in a basic block (starting from `entry_state` and to
4142
/// visit them with `vis`.
4243
fn visit_results_in_block<'mir, 'tcx, A>(
43-
analysis: &A,
44+
results: &Results<'tcx, A>,
4445
state: &mut A::Domain,
4546
block: BasicBlock,
4647
block_data: &'mir mir::BasicBlockData<'tcx>,
@@ -206,32 +207,32 @@ impl Direction for Backward {
206207
}
207208

208209
fn visit_results_in_block<'mir, 'tcx, A>(
209-
analysis: &A,
210+
results: &Results<'tcx, A>,
210211
state: &mut A::Domain,
211212
block: BasicBlock,
212213
block_data: &'mir mir::BasicBlockData<'tcx>,
213214
vis: &mut impl ResultsVisitor<'tcx, A>,
214215
) where
215216
A: Analysis<'tcx>,
216217
{
217-
vis.visit_block_end(state);
218+
vis.visit_block_end(results, state, block);
218219

219220
let loc = Location { block, statement_index: block_data.statements.len() };
220221
let term = block_data.terminator();
221-
analysis.apply_early_terminator_effect(state, term, loc);
222-
vis.visit_after_early_terminator_effect(analysis, state, term, loc);
223-
analysis.apply_primary_terminator_effect(state, term, loc);
224-
vis.visit_after_primary_terminator_effect(analysis, state, term, loc);
222+
results.analysis.apply_early_terminator_effect(state, term, loc);
223+
vis.visit_after_early_terminator_effect(&results.analysis, state, term, loc);
224+
results.analysis.apply_primary_terminator_effect(state, term, loc);
225+
vis.visit_after_primary_terminator_effect(&results.analysis, state, term, loc);
225226

226227
for (statement_index, stmt) in block_data.statements.iter().enumerate().rev() {
227228
let loc = Location { block, statement_index };
228-
analysis.apply_early_statement_effect(state, stmt, loc);
229-
vis.visit_after_early_statement_effect(analysis, state, stmt, loc);
230-
analysis.apply_primary_statement_effect(state, stmt, loc);
231-
vis.visit_after_primary_statement_effect(analysis, state, stmt, loc);
229+
results.analysis.apply_early_statement_effect(state, stmt, loc);
230+
vis.visit_after_early_statement_effect(&results.analysis, state, stmt, loc);
231+
results.analysis.apply_primary_statement_effect(state, stmt, loc);
232+
vis.visit_after_primary_statement_effect(&results.analysis, state, stmt, loc);
232233
}
233234

234-
vis.visit_block_start(state);
235+
vis.visit_block_start(results, state, block);
235236
}
236237
}
237238

@@ -386,31 +387,31 @@ impl Direction for Forward {
386387
}
387388

388389
fn visit_results_in_block<'mir, 'tcx, A>(
389-
analysis: &A,
390+
results: &Results<'tcx, A>,
390391
state: &mut A::Domain,
391392
block: BasicBlock,
392393
block_data: &'mir mir::BasicBlockData<'tcx>,
393394
vis: &mut impl ResultsVisitor<'tcx, A>,
394395
) where
395396
A: Analysis<'tcx>,
396397
{
397-
vis.visit_block_start(state);
398+
vis.visit_block_start(results, state, block);
398399

399400
for (statement_index, stmt) in block_data.statements.iter().enumerate() {
400401
let loc = Location { block, statement_index };
401-
analysis.apply_early_statement_effect(state, stmt, loc);
402-
vis.visit_after_early_statement_effect(analysis, state, stmt, loc);
403-
analysis.apply_primary_statement_effect(state, stmt, loc);
404-
vis.visit_after_primary_statement_effect(analysis, state, stmt, loc);
402+
results.analysis.apply_early_statement_effect(state, stmt, loc);
403+
vis.visit_after_early_statement_effect(&results.analysis, state, stmt, loc);
404+
results.analysis.apply_primary_statement_effect(state, stmt, loc);
405+
vis.visit_after_primary_statement_effect(&results.analysis, state, stmt, loc);
405406
}
406407

407408
let loc = Location { block, statement_index: block_data.statements.len() };
408409
let term = block_data.terminator();
409-
analysis.apply_early_terminator_effect(state, term, loc);
410-
vis.visit_after_early_terminator_effect(analysis, state, term, loc);
411-
analysis.apply_primary_terminator_effect(state, term, loc);
412-
vis.visit_after_primary_terminator_effect(analysis, state, term, loc);
410+
results.analysis.apply_early_terminator_effect(state, term, loc);
411+
vis.visit_after_early_terminator_effect(&results.analysis, state, term, loc);
412+
results.analysis.apply_primary_terminator_effect(state, term, loc);
413+
vis.visit_after_primary_terminator_effect(&results.analysis, state, term, loc);
413414

414-
vis.visit_block_end(state);
415+
vis.visit_block_end(results, state, block);
415416
}
416417
}

compiler/rustc_mir_dataflow/src/framework/graphviz.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,13 +660,23 @@ where
660660
A: Analysis<'tcx>,
661661
A::Domain: DebugWithContext<A>,
662662
{
663-
fn visit_block_start(&mut self, state: &A::Domain) {
663+
fn visit_block_start(
664+
&mut self,
665+
_results: &Results<'tcx, A>,
666+
state: &A::Domain,
667+
_block: BasicBlock,
668+
) {
664669
if A::Direction::IS_FORWARD {
665670
self.prev_state.clone_from(state);
666671
}
667672
}
668673

669-
fn visit_block_end(&mut self, state: &A::Domain) {
674+
fn visit_block_end(
675+
&mut self,
676+
_results: &Results<'tcx, A>,
677+
state: &A::Domain,
678+
_block: BasicBlock,
679+
) {
670680
if A::Direction::IS_BACKWARD {
671681
self.prev_state.clone_from(state);
672682
}

compiler/rustc_mir_dataflow/src/framework/visitor.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn visit_results<'mir, 'tcx, A>(
2323

2424
let block_data = &body[block];
2525
state.clone_from(&results.entry_states[block]);
26-
A::Direction::visit_results_in_block(&results.analysis, &mut state, block, block_data, vis);
26+
A::Direction::visit_results_in_block(results, &mut state, block, block_data, vis);
2727
}
2828
}
2929

@@ -46,7 +46,13 @@ pub trait ResultsVisitor<'tcx, A>
4646
where
4747
A: Analysis<'tcx>,
4848
{
49-
fn visit_block_start(&mut self, _state: &A::Domain) {}
49+
fn visit_block_start(
50+
&mut self,
51+
_results: &Results<'tcx, A>,
52+
_state: &A::Domain,
53+
_block: BasicBlock,
54+
) {
55+
}
5056

5157
/// Called after the "early" effect of the given statement is applied to `state`.
5258
fn visit_after_early_statement_effect(
@@ -90,5 +96,11 @@ where
9096
) {
9197
}
9298

93-
fn visit_block_end(&mut self, _state: &A::Domain) {}
99+
fn visit_block_end(
100+
&mut self,
101+
_results: &Results<'tcx, A>,
102+
_state: &A::Domain,
103+
_block: BasicBlock,
104+
) {
105+
}
94106
}

compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ where
7171
}
7272
}
7373

74+
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
75+
self.super_operand(operand, location);
76+
77+
// Kill moved operands if the whole local was moved.
78+
if let Operand::Move(place) = operand {
79+
if let Some(local) = place.as_local() {
80+
self.trans.kill(local);
81+
}
82+
}
83+
}
84+
7485
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
7586
self.super_rvalue(rvalue, location);
7687

compiler/rustc_mir_dataflow/src/impls/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod borrowed_locals;
22
mod initialized;
33
mod liveness;
4+
mod precise_liveness;
45
mod storage_liveness;
56

67
pub use self::borrowed_locals::{MaybeBorrowedLocals, borrowed_locals};
@@ -12,6 +13,7 @@ pub use self::liveness::{
1213
DefUse, MaybeLiveLocals, MaybeTransitiveLiveLocals,
1314
TransferFunction as LivenessTransferFunction,
1415
};
16+
pub use self::precise_liveness::{SplitPointEffect, SplitPointIndex, liveness_matrix};
1517
pub use self::storage_liveness::{
1618
MaybeRequiresStorage, MaybeStorageDead, MaybeStorageLive, always_storage_live_locals,
1719
};

0 commit comments

Comments
 (0)