Skip to content
Merged
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
56 changes: 29 additions & 27 deletions compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use tracing::debug;
use tracing::{debug, instrument};

use crate::patch::MirPatch;

Expand All @@ -15,6 +15,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
sess.panic_strategy().unwinds()
}

#[instrument(level = "debug", skip(self, _tcx, body))]
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let def_id = body.source.def_id();
debug!(?def_id);
Expand All @@ -25,7 +26,24 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
.iter_enumerated()
.any(|(_bb, block)| matches!(block.terminator().kind, TerminatorKind::UnwindResume));
if !has_resume {
debug!("remove_noop_landing_pads: no resume block in MIR");
debug!("no resume block in MIR");
return;
}

let mut nop_landing_pads = DenseBitSet::new_empty(body.basic_blocks.len());

// This is a post-order traversal, so that if A post-dominates B
// then A will be visited before B.
for (bb, bbdata) in traversal::postorder(body) {
let is_nop_landing_pad = self.is_nop_landing_pad(bbdata, &nop_landing_pads);
debug!("is_nop_landing_pad({bb:?}) = {is_nop_landing_pad}");
if is_nop_landing_pad {
nop_landing_pads.insert(bb);
}
}

if nop_landing_pads.is_empty() {
debug!("no nop landing pads in MIR");
return;
}

Expand All @@ -36,42 +54,27 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
patch.apply(body);
resume_block
};
debug!("remove_noop_landing_pads: resume block is {:?}", resume_block);
debug!(?resume_block);

let mut jumps_folded = 0;
let mut landing_pads_removed = 0;
let mut nop_landing_pads = DenseBitSet::new_empty(body.basic_blocks.len());
let basic_blocks = body.basic_blocks.as_mut();
for (bb, bbdata) in basic_blocks.iter_enumerated_mut() {
debug!("processing {:?}", bb);

// This is a post-order traversal, so that if A post-dominates B
// then A will be visited before B.
let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect();
for bb in postorder {
debug!(" processing {:?}", bb);
if let Some(unwind) = body[bb].terminator_mut().unwind_mut()
if let Some(unwind) = bbdata.terminator_mut().unwind_mut()
&& let UnwindAction::Cleanup(unwind_bb) = *unwind
&& nop_landing_pads.contains(unwind_bb)
{
debug!(" removing noop landing pad");
landing_pads_removed += 1;
*unwind = UnwindAction::Continue;
}

body[bb].terminator_mut().successors_mut(|target| {
bbdata.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 {
nop_landing_pads.insert(bb);
}
debug!(" is_nop_landing_pad({:?}) = {}", bb, is_nop_landing_pad);
}

debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed);
}

fn is_required(&self) -> bool {
Expand All @@ -82,11 +85,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
impl RemoveNoopLandingPads {
fn is_nop_landing_pad(
&self,
bb: BasicBlock,
body: &Body<'_>,
bbdata: &BasicBlockData<'_>,
nop_landing_pads: &DenseBitSet<BasicBlock>,
) -> bool {
for stmt in &body[bb].statements {
for stmt in &bbdata.statements {
match &stmt.kind {
StatementKind::FakeRead(..)
| StatementKind::StorageLive(_)
Expand Down Expand Up @@ -119,7 +121,7 @@ impl RemoveNoopLandingPads {
}
}

let terminator = body[bb].terminator();
let terminator = bbdata.terminator();
match terminator.kind {
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
Expand Down
Loading