Skip to content

Commit 392b5a0

Browse files
committed
Add supporting APIs for MIR storage reconstruction
1 parent bc0d0fa commit 392b5a0

4 files changed

Lines changed: 61 additions & 12 deletions

File tree

‎compiler/rustc_index/src/interval.rs‎

Lines changed: 36 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.
@@ -204,17 +208,38 @@ impl<I: Idx> IntervalSet<I> {
204208
needle <= *prev_end
205209
}
206210

211+
/// Returns whether any point in `range` is contained in the set.
212+
pub fn intersects_range(&self, range: impl RangeBounds<I> + Clone) -> bool {
213+
let start = inclusive_start(range.clone());
214+
let Some(end) = inclusive_end(self.domain, range) else {
215+
// empty range
216+
return false;
217+
};
218+
if start > end {
219+
return false;
220+
}
221+
222+
// Find the last interval whose start is <= end.
223+
let Some(last) = self.map.partition_point(|r| r.0 <= end).checked_sub(1) else {
224+
// All ranges in the map start after the new range's end
225+
return false;
226+
};
227+
let (_, prev_end) = &self.map[last];
228+
start <= *prev_end
229+
}
230+
207231
pub fn superset(&self, other: &IntervalSet<I>) -> bool
208232
where
209233
I: Step,
210234
{
211235
let mut sup_iter = self.iter_intervals();
212236
let mut current = None;
213-
let contains = |sup: Range<I>, sub: Range<I>, current: &mut Option<Range<I>>| {
214-
if sup.end < sub.start {
215-
// if `sup.end == sub.start`, the next sup doesn't contain `sub.start`
237+
let contains = |sup: RangeInclusive<I>,
238+
sub: RangeInclusive<I>,
239+
current: &mut Option<RangeInclusive<I>>| {
240+
if sup.last < sub.start {
216241
None // continue to the next sup
217-
} else if sup.end >= sub.end && sup.start <= sub.start {
242+
} else if sup.last >= sub.last && sup.start <= sub.start {
218243
*current = Some(sup); // save the current sup
219244
Some(true)
220245
} else {
@@ -224,8 +249,8 @@ impl<I: Idx> IntervalSet<I> {
224249
other.iter_intervals().all(|sub| {
225250
current
226251
.take()
227-
.and_then(|sup| contains(sup, sub.clone(), &mut current))
228-
.or_else(|| sup_iter.find_map(|sup| contains(sup, sub.clone(), &mut current)))
252+
.and_then(|sup| contains(sup, sub, &mut current))
253+
.or_else(|| sup_iter.find_map(|sup| contains(sup, sub, &mut current)))
229254
.unwrap_or(false)
230255
})
231256
}
@@ -242,11 +267,11 @@ impl<I: Idx> IntervalSet<I> {
242267
let mut other_current = other_iter.next()?;
243268

244269
loop {
245-
if self_current.end <= other_current.start {
270+
if self_current.last < other_current.start {
246271
self_current = self_iter.next()?;
247272
continue;
248273
}
249-
if other_current.end <= self_current.start {
274+
if other_current.last < self_current.start {
250275
other_current = other_iter.next()?;
251276
continue;
252277
}

‎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_mir_dataflow/src/points.rs‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ impl DenseLocationMap {
6161
PointIndex::new(start_index)
6262
}
6363

64+
/// Returns the `PointIndex` for the terminator in the given `BasicBlock`. O(1).
65+
#[inline]
66+
pub fn terminator(&self, block: BasicBlock) -> PointIndex {
67+
let next_block = BasicBlock::new(block.index() + 1);
68+
let next_start_index =
69+
*self.statements_before_block.get(next_block).unwrap_or(&self.num_points);
70+
PointIndex::new(next_start_index - 1)
71+
}
72+
6473
/// Return the PointIndex for the block start of this index.
6574
#[inline]
6675
pub fn to_block_start(&self, index: PointIndex) -> PointIndex {

‎compiler/rustc_mir_transform/src/patch.rs‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,21 @@ impl<'tcx> MirPatch<'tcx> {
215215
self.term_patch_map.insert(block, new);
216216
}
217217

218+
/// Modifies the terminator of a block, reading the existing patch if one exists or
219+
/// cloning from the body otherwise.
220+
pub(crate) fn mutate_terminator(
221+
&mut self,
222+
body: &Body<'tcx>,
223+
bb: BasicBlock,
224+
f: impl FnOnce(&mut TerminatorKind<'tcx>),
225+
) {
226+
let kind = self
227+
.term_patch_map
228+
.entry(bb)
229+
.or_insert_with(|| body.basic_blocks[bb].terminator().kind.clone());
230+
f(kind);
231+
}
232+
218233
/// Mark given statement to be replaced by a `Nop`.
219234
///
220235
/// This method only works on statements from the initial body, and cannot be used to remove

0 commit comments

Comments
 (0)