Use a closure instead of three chained iterators

This commit is contained in:
Oli Scherer 2025-04-29 14:23:23 +00:00
parent 820fce61e7
commit 9193dfe435
6 changed files with 58 additions and 72 deletions

View file

@ -437,8 +437,8 @@ impl<'tcx> Terminator<'tcx> {
}
#[inline]
pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
self.kind.successors_mut()
pub fn successors_mut<'a>(&'a mut self, f: impl FnMut(&'a mut BasicBlock)) {
self.kind.successors_mut(f)
}
#[inline]
@ -486,7 +486,6 @@ pub use helper::*;
mod helper {
use super::*;
pub type Successors<'a> = impl DoubleEndedIterator<Item = BasicBlock> + 'a;
pub type SuccessorsMut<'a> = impl DoubleEndedIterator<Item = &'a mut BasicBlock> + 'a;
impl SwitchTargets {
/// Like [`SwitchTargets::target_for_value`], but returning the same type as
@ -560,69 +559,63 @@ mod helper {
}
#[inline]
#[define_opaque(SuccessorsMut)]
pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
pub fn successors_mut<'a>(&'a mut self, mut f: impl FnMut(&'a mut BasicBlock)) {
use self::TerminatorKind::*;
match *self {
// 3-successors for async drop: target, unwind, dropline (parent coroutine drop)
Drop {
target: ref mut t,
unwind: UnwindAction::Cleanup(ref mut u),
drop: Some(ref mut d),
..
} => slice::from_mut(t).into_iter().chain(Some(u).into_iter().chain(Some(d))),
// 2-successors
Call {
target: Some(ref mut t), unwind: UnwindAction::Cleanup(ref mut u), ..
match self {
Drop { target, unwind, drop, .. } => {
f(target);
if let UnwindAction::Cleanup(u) = unwind {
f(u)
}
if let Some(d) = drop {
f(d)
}
}
| Yield { resume: ref mut t, drop: Some(ref mut u), .. }
| Drop {
target: ref mut t,
unwind: UnwindAction::Cleanup(ref mut u),
drop: None,
..
Call { target, unwind, .. } => {
if let Some(target) = target {
f(target);
}
if let UnwindAction::Cleanup(u) = unwind {
f(u)
}
}
| Drop { target: ref mut t, unwind: _, drop: Some(ref mut u), .. }
| Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
| FalseUnwind {
real_target: ref mut t,
unwind: UnwindAction::Cleanup(ref mut u),
} => slice::from_mut(t).into_iter().chain(Some(u).into_iter().chain(None)),
// single successor
Goto { target: ref mut t }
| Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
| Call { target: Some(ref mut t), unwind: _, .. }
| Yield { resume: ref mut t, drop: None, .. }
| Drop { target: ref mut t, unwind: _, .. }
| Assert { target: ref mut t, unwind: _, .. }
| FalseUnwind { real_target: ref mut t, unwind: _ } => {
slice::from_mut(t).into_iter().chain(None.into_iter().chain(None))
Yield { resume, drop, .. } => {
f(resume);
if let Some(d) = drop {
f(d)
}
}
Assert { target, unwind, .. } | FalseUnwind { real_target: target, unwind } => {
f(target);
if let UnwindAction::Cleanup(u) = unwind {
f(u)
}
}
Goto { target } => {
f(target);
}
// No successors
UnwindResume
| UnwindTerminate(_)
| CoroutineDrop
| Return
| Unreachable
| TailCall { .. }
| Call { target: None, unwind: _, .. } => {
(&mut []).into_iter().chain(None.into_iter().chain(None))
| TailCall { .. } => {}
InlineAsm { targets, unwind, .. } => {
for target in targets {
f(target);
}
if let UnwindAction::Cleanup(u) = unwind {
f(u)
}
}
// Multiple successors
InlineAsm { ref mut targets, unwind: UnwindAction::Cleanup(ref mut u), .. } => {
targets.iter_mut().chain(Some(u).into_iter().chain(None))
SwitchInt { targets, .. } => {
for target in &mut targets.targets {
f(target);
}
}
InlineAsm { ref mut targets, unwind: _, .. } => {
targets.iter_mut().chain(None.into_iter().chain(None))
}
SwitchInt { ref mut targets, .. } => {
targets.targets.iter_mut().chain(None.into_iter().chain(None))
}
// FalseEdge
FalseEdge { ref mut real_target, ref mut imaginary_target } => {
slice::from_mut(real_target)
.into_iter()
.chain(Some(imaginary_target).into_iter().chain(None))
FalseEdge { real_target, imaginary_target } => {
f(real_target);
f(imaginary_target);
}
}
}

View file

@ -1064,10 +1064,8 @@ fn insert_switch<'tcx>(
},
);
let blocks = body.basic_blocks_mut().iter_mut();
for target in blocks.flat_map(|b| b.terminator_mut().successors_mut()) {
*target += 1;
for b in body.basic_blocks_mut().iter_mut() {
b.terminator_mut().successors_mut(|target| *target += 1);
}
}

View file

@ -765,12 +765,12 @@ impl OpportunitySet {
// Replace `succ` by `new_succ` where it appears.
let mut num_edges = 0;
for s in basic_blocks[current].terminator_mut().successors_mut() {
basic_blocks[current].terminator_mut().successors_mut(|s| {
if *s == succ {
*s = new_succ;
num_edges += 1;
}
}
});
// Update predecessors with the new block.
let _new_succ = self.predecessors.push(num_edges);

View file

@ -115,9 +115,7 @@ impl<'tcx> MutVisitor<'tcx> for BasicBlockUpdater<'tcx> {
}
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, _location: Location) {
for succ in terminator.successors_mut() {
*succ = self.map[*succ];
}
terminator.successors_mut(|succ| *succ = self.map[*succ]);
}
}

View file

@ -58,13 +58,13 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
}
}
for target in body[bb].terminator_mut().successors_mut() {
body[bb].terminator_mut().successors_mut(|target| {
if *target != resume_block && nop_landing_pads.contains(*target) {
debug!(" folding noop jump to {:?} to resume block", target);
*target = resume_block;
jumps_folded += 1;
}
}
});
let is_nop_landing_pad = self.is_nop_landing_pad(bb, body, &nop_landing_pads);
if is_nop_landing_pad {

View file

@ -147,9 +147,8 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
let mut terminator =
self.basic_blocks[bb].terminator.take().expect("invalid terminator state");
for successor in terminator.successors_mut() {
self.collapse_goto_chain(successor, &mut changed);
}
terminator
.successors_mut(|successor| self.collapse_goto_chain(successor, &mut changed));
let mut inner_changed = true;
merged_blocks.clear();
@ -375,9 +374,7 @@ pub(super) fn remove_dead_blocks(body: &mut Body<'_>) {
}
for block in basic_blocks {
for target in block.terminator_mut().successors_mut() {
*target = replacements[target.index()];
}
block.terminator_mut().successors_mut(|target| *target = replacements[target.index()]);
}
}