Rollup merge of #137203 - nnethercote:improve-MIR-modification, r=compiler-errors
Improve MIR modification A few commits that simplify code that manipulates MIR bodies. r? `@tmiasko`
This commit is contained in:
commit
10dd016a80
11 changed files with 130 additions and 201 deletions
|
@ -4,8 +4,8 @@
|
|||
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::iter;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::{iter, mem};
|
||||
|
||||
pub use basic_blocks::{BasicBlocks, SwitchTargetValue};
|
||||
use either::Either;
|
||||
|
@ -1365,66 +1365,6 @@ impl<'tcx> BasicBlockData<'tcx> {
|
|||
self.terminator.as_mut().expect("invalid terminator state")
|
||||
}
|
||||
|
||||
pub fn retain_statements<F>(&mut self, mut f: F)
|
||||
where
|
||||
F: FnMut(&mut Statement<'_>) -> bool,
|
||||
{
|
||||
for s in &mut self.statements {
|
||||
if !f(s) {
|
||||
s.make_nop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_statements<F, I>(&mut self, mut f: F)
|
||||
where
|
||||
F: FnMut(&mut Statement<'tcx>) -> Option<I>,
|
||||
I: iter::TrustedLen<Item = Statement<'tcx>>,
|
||||
{
|
||||
// Gather all the iterators we'll need to splice in, and their positions.
|
||||
let mut splices: Vec<(usize, I)> = vec![];
|
||||
let mut extra_stmts = 0;
|
||||
for (i, s) in self.statements.iter_mut().enumerate() {
|
||||
if let Some(mut new_stmts) = f(s) {
|
||||
if let Some(first) = new_stmts.next() {
|
||||
// We can already store the first new statement.
|
||||
*s = first;
|
||||
|
||||
// Save the other statements for optimized splicing.
|
||||
let remaining = new_stmts.size_hint().0;
|
||||
if remaining > 0 {
|
||||
splices.push((i + 1 + extra_stmts, new_stmts));
|
||||
extra_stmts += remaining;
|
||||
}
|
||||
} else {
|
||||
s.make_nop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Splice in the new statements, from the end of the block.
|
||||
// FIXME(eddyb) This could be more efficient with a "gap buffer"
|
||||
// where a range of elements ("gap") is left uninitialized, with
|
||||
// splicing adding new elements to the end of that gap and moving
|
||||
// existing elements from before the gap to the end of the gap.
|
||||
// For now, this is safe code, emulating a gap but initializing it.
|
||||
let mut gap = self.statements.len()..self.statements.len() + extra_stmts;
|
||||
self.statements.resize(
|
||||
gap.end,
|
||||
Statement { source_info: SourceInfo::outermost(DUMMY_SP), kind: StatementKind::Nop },
|
||||
);
|
||||
for (splice_start, new_stmts) in splices.into_iter().rev() {
|
||||
let splice_end = splice_start + new_stmts.size_hint().0;
|
||||
while gap.end > splice_end {
|
||||
gap.start -= 1;
|
||||
gap.end -= 1;
|
||||
self.statements.swap(gap.start, gap.end);
|
||||
}
|
||||
self.statements.splice(splice_start..splice_end, new_stmts);
|
||||
gap.end = splice_start;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
|
||||
if index < self.statements.len() { &self.statements[index] } else { &self.terminator }
|
||||
}
|
||||
|
|
|
@ -19,15 +19,6 @@ impl Statement<'_> {
|
|||
pub fn make_nop(&mut self) {
|
||||
self.kind = StatementKind::Nop
|
||||
}
|
||||
|
||||
/// Changes a statement to a nop and returns the original statement.
|
||||
#[must_use = "If you don't need the statement, use `make_nop` instead"]
|
||||
pub fn replace_nop(&mut self) -> Self {
|
||||
Statement {
|
||||
source_info: self.source_info,
|
||||
kind: mem::replace(&mut self.kind, StatementKind::Nop),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> StatementKind<'tcx> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue