Skip to content

Commit 485476c

Browse files
committed
add a pass to remove no-op landing pads
1 parent 25416c7 commit 485476c

File tree

4 files changed

+169
-17
lines changed

4 files changed

+169
-17
lines changed

src/librustc/mir/mod.rs

+25
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,10 @@ impl<'tcx> Terminator<'tcx> {
733733
pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
734734
self.kind.successors_mut()
735735
}
736+
737+
pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
738+
self.kind.unwind_mut()
739+
}
736740
}
737741

738742
impl<'tcx> TerminatorKind<'tcx> {
@@ -811,6 +815,27 @@ impl<'tcx> TerminatorKind<'tcx> {
811815
}
812816
}
813817
}
818+
819+
pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
820+
match *self {
821+
TerminatorKind::Goto { .. } |
822+
TerminatorKind::Resume |
823+
TerminatorKind::Return |
824+
TerminatorKind::Unreachable |
825+
TerminatorKind::GeneratorDrop |
826+
TerminatorKind::Yield { .. } |
827+
TerminatorKind::SwitchInt { .. } |
828+
TerminatorKind::FalseEdges { .. } => {
829+
None
830+
},
831+
TerminatorKind::Call { cleanup: ref mut unwind, .. } |
832+
TerminatorKind::Assert { cleanup: ref mut unwind, .. } |
833+
TerminatorKind::DropAndReplace { ref mut unwind, .. } |
834+
TerminatorKind::Drop { ref mut unwind, .. } => {
835+
Some(unwind)
836+
}
837+
}
838+
}
814839
}
815840

816841
impl<'tcx> BasicBlockData<'tcx> {

src/librustc_mir/transform/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub mod elaborate_drops;
3636
pub mod add_call_guards;
3737
pub mod promote_consts;
3838
pub mod qualify_consts;
39+
pub mod remove_noop_landing_pads;
3940
pub mod dump_mir;
4041
pub mod deaggregator;
4142
pub mod instcombine;
@@ -226,8 +227,11 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
226227

227228
let mut mir = tcx.mir_validated(def_id).steal();
228229
run_passes![tcx, mir, def_id, 2;
230+
// Remove all things not needed by analysis
229231
no_landing_pads::NoLandingPads,
230232
simplify_branches::SimplifyBranches::new("initial"),
233+
remove_noop_landing_pads::RemoveNoopLandingPads,
234+
simplify::SimplifyCfg::new("early-opt"),
231235

232236
// These next passes must be executed together
233237
add_call_guards::CriticalCallEdges,
@@ -255,6 +259,7 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
255259
instcombine::InstCombine,
256260
deaggregator::Deaggregator,
257261
copy_prop::CopyPropagation,
262+
remove_noop_landing_pads::RemoveNoopLandingPads,
258263
simplify::SimplifyLocals,
259264

260265
generator::StateTransform,

src/librustc_mir/transform/no_landing_pads.rs

+2-17
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,8 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
3838
bb: BasicBlock,
3939
terminator: &mut Terminator<'tcx>,
4040
location: Location) {
41-
match terminator.kind {
42-
TerminatorKind::Goto { .. } |
43-
TerminatorKind::Resume |
44-
TerminatorKind::Return |
45-
TerminatorKind::Unreachable |
46-
TerminatorKind::GeneratorDrop |
47-
TerminatorKind::Yield { .. } |
48-
TerminatorKind::SwitchInt { .. } |
49-
TerminatorKind::FalseEdges { .. } => {
50-
/* nothing to do */
51-
},
52-
TerminatorKind::Call { cleanup: ref mut unwind, .. } |
53-
TerminatorKind::Assert { cleanup: ref mut unwind, .. } |
54-
TerminatorKind::DropAndReplace { ref mut unwind, .. } |
55-
TerminatorKind::Drop { ref mut unwind, .. } => {
56-
unwind.take();
57-
},
41+
if let Some(unwind) = terminator.kind.unwind_mut() {
42+
unwind.take();
5843
}
5944
self.super_terminator(bb, terminator, location);
6045
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use rustc::ty::TyCtxt;
12+
use rustc::mir::*;
13+
use rustc_data_structures::bitvec::BitVector;
14+
use rustc_data_structures::indexed_vec::Idx;
15+
use transform::{MirPass, MirSource};
16+
use util::patch::MirPatch;
17+
18+
/// A pass that removes no-op landing pads and replaces jumps to them with
19+
/// `None`. This is important because otherwise LLVM generates terrible
20+
/// code for these.
21+
pub struct RemoveNoopLandingPads;
22+
23+
impl MirPass for RemoveNoopLandingPads {
24+
fn run_pass<'a, 'tcx>(&self,
25+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
26+
_src: MirSource,
27+
mir: &mut Mir<'tcx>) {
28+
if tcx.sess.no_landing_pads() {
29+
return
30+
}
31+
32+
debug!("remove_noop_landing_pads({:?})", mir);
33+
self.remove_nop_landing_pads(mir);
34+
}
35+
}
36+
37+
impl RemoveNoopLandingPads {
38+
fn is_nop_landing_pad(&self, bb: BasicBlock, mir: &Mir, nop_landing_pads: &BitVector)
39+
-> bool
40+
{
41+
for stmt in &mir[bb].statements {
42+
match stmt.kind {
43+
StatementKind::StorageLive(_) |
44+
StatementKind::StorageDead(_) |
45+
StatementKind::EndRegion(_) |
46+
StatementKind::Nop => {
47+
// These are all nops in a landing pad (there's some
48+
// borrowck interaction between EndRegion and storage
49+
// instructions, but this should all run after borrowck).
50+
}
51+
52+
StatementKind::Assign(Place::Local(_), Rvalue::Use(_)) => {
53+
// Writing to a local (e.g. a drop flag) does not
54+
// turn a landing pad to a non-nop
55+
}
56+
57+
StatementKind::Assign(_, _) |
58+
StatementKind::SetDiscriminant { .. } |
59+
StatementKind::InlineAsm { .. } |
60+
StatementKind::Validate { .. } => {
61+
return false;
62+
}
63+
}
64+
}
65+
66+
let terminator = mir[bb].terminator();
67+
match terminator.kind {
68+
TerminatorKind::Goto { .. } |
69+
TerminatorKind::Resume |
70+
TerminatorKind::SwitchInt { .. } |
71+
TerminatorKind::FalseEdges { .. } => {
72+
terminator.successors().iter().all(|succ| {
73+
nop_landing_pads.contains(succ.index())
74+
})
75+
},
76+
TerminatorKind::GeneratorDrop |
77+
TerminatorKind::Yield { .. } |
78+
TerminatorKind::Return |
79+
TerminatorKind::Unreachable |
80+
TerminatorKind::Call { .. } |
81+
TerminatorKind::Assert { .. } |
82+
TerminatorKind::DropAndReplace { .. } |
83+
TerminatorKind::Drop { .. } => {
84+
false
85+
}
86+
}
87+
}
88+
89+
fn remove_nop_landing_pads(&self, mir: &mut Mir) {
90+
// make sure there's a single resume block
91+
let resume_block = {
92+
let patch = MirPatch::new(mir);
93+
let resume_block = patch.resume_block();
94+
patch.apply(mir);
95+
resume_block
96+
};
97+
debug!("remove_noop_landing_pads: resume block is {:?}", resume_block);
98+
99+
let mut jumps_folded = 0;
100+
let mut landing_pads_removed = 0;
101+
let mut nop_landing_pads = BitVector::new(mir.basic_blocks().len());
102+
103+
// This is a post-order traversal, so that if A post-dominates B
104+
// then A will be visited before B.
105+
let postorder: Vec<_> = traversal::postorder(mir).map(|(bb, _)| bb).collect();
106+
for bb in postorder {
107+
debug!(" processing {:?}", bb);
108+
for target in mir[bb].terminator_mut().successors_mut() {
109+
if *target != resume_block && nop_landing_pads.contains(target.index()) {
110+
debug!(" folding noop jump to {:?} to resume block", target);
111+
*target = resume_block;
112+
jumps_folded += 1;
113+
}
114+
}
115+
116+
match mir[bb].terminator_mut().unwind_mut() {
117+
Some(unwind) => {
118+
if *unwind == Some(resume_block) {
119+
debug!(" removing noop landing pad");
120+
jumps_folded -= 1;
121+
landing_pads_removed += 1;
122+
*unwind = None;
123+
}
124+
}
125+
_ => {}
126+
}
127+
128+
let is_nop_landing_pad = self.is_nop_landing_pad(bb, mir, &nop_landing_pads);
129+
if is_nop_landing_pad {
130+
nop_landing_pads.insert(bb.index());
131+
}
132+
debug!(" is_nop_landing_pad({:?}) = {}", bb, is_nop_landing_pad);
133+
}
134+
135+
debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed);
136+
}
137+
}

0 commit comments

Comments
 (0)