Skip to content
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
96 changes: 85 additions & 11 deletions compiler/rustc_index/src/interval.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::iter::Step;
use std::marker::PhantomData;
use std::ops::{Bound, Range, RangeBounds};
use std::ops::{Bound, RangeBounds};
use std::range::RangeInclusive;

use smallvec::SmallVec;

Expand Down Expand Up @@ -59,11 +60,14 @@ impl<I: Idx> IntervalSet<I> {
}

/// Iterates through intervals stored in the set, in order.
pub fn iter_intervals(&self) -> impl Iterator<Item = std::ops::Range<I>>
pub fn iter_intervals(&self) -> impl Iterator<Item = RangeInclusive<I>>
where
I: Step,
{
self.map.iter().map(|&(start, end)| I::new(start as usize)..I::new(end as usize + 1))
self.map.iter().map(|&(start, end)| RangeInclusive {
start: I::new(start as usize),
last: I::new(end as usize),
})
}

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

/// Specialized version of `insert` when we know that the inserted range is
/// *after* any contained.
pub fn append_range(&mut self, range: impl RangeBounds<I> + Clone) {
let start = inclusive_start(range.clone());
let Some(end) = inclusive_end(self.domain, range) else {
// empty range
return;
};
if start > end {
return;
}

if let Some((_, last_end)) = self.map.last_mut() {
assert!(*last_end < start);
if start == *last_end + 1 {
*last_end = end;
} else {
self.map.push((start, end));
}
} else {
self.map.push((start, end));
}

debug_assert!(
self.check_invariants(),
"wrong intervals after append {start:?}..={end:?} to {self:?}"
);
}

pub fn contains(&self, needle: I) -> bool {
let needle = needle.index() as u32;
let Some(last) = self.map.partition_point(|r| r.0 <= needle).checked_sub(1) else {
Expand All @@ -174,17 +207,38 @@ impl<I: Idx> IntervalSet<I> {
needle <= *prev_end
}

/// Returns whether any point in `range` is contained in the set.
pub fn intersects_range(&self, range: impl RangeBounds<I> + Clone) -> bool {
let start = inclusive_start(range.clone());
let Some(end) = inclusive_end(self.domain, range) else {
// empty range
return false;
};
if start > end {
return false;
}

// Find the last interval whose start is <= end.
let Some(last) = self.map.partition_point(|r| r.0 <= end).checked_sub(1) else {
// All ranges in the map start after the new range's end
return false;
};
let (_, prev_end) = &self.map[last];
start <= *prev_end
}

pub fn superset(&self, other: &IntervalSet<I>) -> bool
where
I: Step,
{
let mut sup_iter = self.iter_intervals();
let mut current = None;
let contains = |sup: Range<I>, sub: Range<I>, current: &mut Option<Range<I>>| {
if sup.end < sub.start {
// if `sup.end == sub.start`, the next sup doesn't contain `sub.start`
let contains = |sup: RangeInclusive<I>,
sub: RangeInclusive<I>,
current: &mut Option<RangeInclusive<I>>| {
if sup.last < sub.start {
None // continue to the next sup
} else if sup.end >= sub.end && sup.start <= sub.start {
} else if sup.last >= sub.last && sup.start <= sub.start {
*current = Some(sup); // save the current sup
Some(true)
} else {
Expand All @@ -194,8 +248,8 @@ impl<I: Idx> IntervalSet<I> {
other.iter_intervals().all(|sub| {
current
.take()
.and_then(|sup| contains(sup, sub.clone(), &mut current))
.or_else(|| sup_iter.find_map(|sup| contains(sup, sub.clone(), &mut current)))
.and_then(|sup| contains(sup, sub, &mut current))
.or_else(|| sup_iter.find_map(|sup| contains(sup, sub, &mut current)))
.unwrap_or(false)
})
}
Expand All @@ -212,11 +266,11 @@ impl<I: Idx> IntervalSet<I> {
let mut other_current = other_iter.next()?;

loop {
if self_current.end <= other_current.start {
if self_current.last < other_current.start {
self_current = self_iter.next()?;
continue;
}
if other_current.end <= self_current.start {
if other_current.last < self_current.start {
other_current = other_iter.next()?;
continue;
}
Expand Down Expand Up @@ -340,6 +394,12 @@ impl<R: Idx, C: Step + Idx> SparseIntervalMatrix<R, C> {
self.rows.get(row)
}

pub fn clear_row(&mut self, row: R) {
if let Some(row) = self.rows.get_mut(row) {
row.clear();
}
}

fn ensure_row(&mut self, row: R) -> &mut IntervalSet<C> {
self.rows.ensure_contains_elem(row, || IntervalSet::new(self.column_size))
}
Expand All @@ -363,6 +423,16 @@ impl<R: Idx, C: Step + Idx> SparseIntervalMatrix<R, C> {
write_row.union(read_row)
}

pub fn disjoint_rows(&self, a: R, b: R) -> bool
where
C: Step,
{
let (Some(a), Some(b)) = (self.rows.get(a), self.rows.get(b)) else {
return true;
};
a.disjoint(b)
}

pub fn insert_all_into_row(&mut self, row: R) {
self.ensure_row(row).insert_all();
}
Expand All @@ -379,6 +449,10 @@ impl<R: Idx, C: Step + Idx> SparseIntervalMatrix<R, C> {
self.ensure_row(row).append(point)
}

pub fn append_range(&mut self, row: R, range: impl RangeBounds<C> + Clone) {
self.ensure_row(row).append_range(range)
}

pub fn contains(&self, row: R, point: C) -> bool {
self.row(row).is_some_and(|r| r.contains(point))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_index/src/interval/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ fn insert_collapses() {
let mut set = IntervalSet::<u32>::new(10000);
set.insert_range(9831..=9837);
set.insert_range(43..=9830);
assert_eq!(set.iter_intervals().collect::<Vec<_>>(), [43..9838]);
assert_eq!(set.iter_intervals().collect::<Vec<_>>(), [(43..=9837).into()]);
}

#[test]
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ pub enum RuntimePhase {
/// disallowed:
/// * [`TerminatorKind::Yield`]
/// * [`TerminatorKind::CoroutineDrop`]
/// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
/// * [`Rvalue::CopyForDeref`]
/// * [`PlaceElem::OpaqueCast`]
/// * [`LocalInfo::DerefTemp`](super::LocalInfo::DerefTemp)
Expand Down Expand Up @@ -1442,9 +1441,6 @@ pub enum Rvalue<'tcx> {
/// This is needed because dataflow analysis needs to distinguish
/// `dest = Foo { x: ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case that `Foo`
/// has a destructor.
///
/// Disallowed after deaggregation for all aggregate kinds except `Array` and `Coroutine`. After
/// coroutine lowering, `Coroutine` aggregate kinds are disallowed too.
Aggregate(Box<AggregateKind<'tcx>>, IndexVec<FieldIdx, Operand<'tcx>>),

/// A CopyForDeref is equivalent to a read from a place at the
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_mir_dataflow/src/framework/direction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ impl Direction for Backward {
) where
A: Analysis<'tcx>,
{
vis.visit_block_end(state);
vis.visit_block_end(state, block);

let loc = Location { block, statement_index: block_data.statements.len() };
let term = block_data.terminator();
Expand All @@ -231,7 +231,7 @@ impl Direction for Backward {
vis.visit_after_primary_statement_effect(analysis, state, stmt, loc);
}

vis.visit_block_start(state);
vis.visit_block_start(state, block);
}
}

Expand Down Expand Up @@ -394,7 +394,7 @@ impl Direction for Forward {
) where
A: Analysis<'tcx>,
{
vis.visit_block_start(state);
vis.visit_block_start(state, block);

for (statement_index, stmt) in block_data.statements.iter().enumerate() {
let loc = Location { block, statement_index };
Expand All @@ -411,6 +411,6 @@ impl Direction for Forward {
analysis.apply_primary_terminator_effect(state, term, loc);
vis.visit_after_primary_terminator_effect(analysis, state, term, loc);

vis.visit_block_end(state);
vis.visit_block_end(state, block);
}
}
4 changes: 2 additions & 2 deletions compiler/rustc_mir_dataflow/src/framework/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -660,13 +660,13 @@ where
A: Analysis<'tcx>,
A::Domain: DebugWithContext<A>,
{
fn visit_block_start(&mut self, state: &A::Domain) {
fn visit_block_start(&mut self, state: &A::Domain, _block: BasicBlock) {
if A::Direction::IS_FORWARD {
self.prev_state.clone_from(state);
}
}

fn visit_block_end(&mut self, state: &A::Domain) {
fn visit_block_end(&mut self, state: &A::Domain, _block: BasicBlock) {
if A::Direction::IS_BACKWARD {
self.prev_state.clone_from(state);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_dataflow/src/framework/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub trait ResultsVisitor<'tcx, A>
where
A: Analysis<'tcx>,
{
fn visit_block_start(&mut self, _state: &A::Domain) {}
fn visit_block_start(&mut self, _state: &A::Domain, _block: BasicBlock) {}

/// Called after the "early" effect of the given statement is applied to `state`.
fn visit_after_early_statement_effect(
Expand Down Expand Up @@ -90,5 +90,5 @@ where
) {
}

fn visit_block_end(&mut self, _state: &A::Domain) {}
fn visit_block_end(&mut self, _state: &A::Domain, _block: BasicBlock) {}
}
4 changes: 4 additions & 0 deletions compiler/rustc_mir_dataflow/src/impls/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod borrowed_locals;
mod initialized;
mod liveness;
mod precise_liveness;
mod storage_liveness;

pub use self::borrowed_locals::{MaybeBorrowedLocals, borrowed_locals};
Expand All @@ -12,6 +13,9 @@ pub use self::liveness::{
DefUse, MaybeLiveLocals, MaybeTransitiveLiveLocals,
TransferFunction as LivenessTransferFunction,
};
pub use self::precise_liveness::{
SplitPointEffect, SplitPointIndex, dump_liveness_matrix, liveness_matrix,
};
pub use self::storage_liveness::{
MaybeRequiresStorage, MaybeStorageDead, MaybeStorageLive, always_storage_live_locals,
};
Loading
Loading