Skip to content
63 changes: 52 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 @@ -204,17 +208,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 @@ -224,8 +249,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 @@ -242,11 +267,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 @@ -370,6 +395,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 @@ -393,6 +424,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 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 @@ -212,7 +212,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 @@ -229,7 +229,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 @@ -391,7 +391,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 @@ -408,6 +408,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