]>
git.proxmox.com Git - rustc.git/blob - src/librustc_mir/transform/remove_noop_landing_pads.rs
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.
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.
11 use rustc
::ty
::TyCtxt
;
13 use rustc_data_structures
::bitvec
::BitVector
;
14 use transform
::{MirPass, MirSource}
;
15 use util
::patch
::MirPatch
;
17 /// A pass that removes no-op landing pads and replaces jumps to them with
18 /// `None`. This is important because otherwise LLVM generates terrible
20 pub struct RemoveNoopLandingPads
;
22 pub fn remove_noop_landing_pads
<'a
, 'tcx
>(
23 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
26 if tcx
.sess
.no_landing_pads() {
29 debug
!("remove_noop_landing_pads({:?})", mir
);
31 RemoveNoopLandingPads
.remove_nop_landing_pads(mir
)
34 impl MirPass
for RemoveNoopLandingPads
{
35 fn run_pass
<'a
, 'tcx
>(&self,
36 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
38 mir
: &mut Mir
<'tcx
>) {
39 remove_noop_landing_pads(tcx
, mir
);
43 impl RemoveNoopLandingPads
{
44 fn is_nop_landing_pad(
48 nop_landing_pads
: &BitVector
<BasicBlock
>,
50 for stmt
in &mir
[bb
].statements
{
52 StatementKind
::ReadForMatch(_
) |
53 StatementKind
::StorageLive(_
) |
54 StatementKind
::StorageDead(_
) |
55 StatementKind
::EndRegion(_
) |
56 StatementKind
::UserAssertTy(..) |
57 StatementKind
::Nop
=> {
58 // These are all nops in a landing pad (there's some
59 // borrowck interaction between EndRegion and storage
60 // instructions, but this should all run after borrowck).
63 StatementKind
::Assign(Place
::Local(_
), Rvalue
::Use(_
)) => {
64 // Writing to a local (e.g. a drop flag) does not
65 // turn a landing pad to a non-nop
68 StatementKind
::Assign(_
, _
) |
69 StatementKind
::SetDiscriminant { .. }
|
70 StatementKind
::InlineAsm { .. }
|
71 StatementKind
::Validate { .. }
=> {
77 let terminator
= mir
[bb
].terminator();
78 match terminator
.kind
{
79 TerminatorKind
::Goto { .. }
|
80 TerminatorKind
::Resume
|
81 TerminatorKind
::SwitchInt { .. }
|
82 TerminatorKind
::FalseEdges { .. }
|
83 TerminatorKind
::FalseUnwind { .. }
=> {
84 terminator
.successors().all(|&succ
| {
85 nop_landing_pads
.contains(succ
)
88 TerminatorKind
::GeneratorDrop
|
89 TerminatorKind
::Yield { .. }
|
90 TerminatorKind
::Return
|
91 TerminatorKind
::Abort
|
92 TerminatorKind
::Unreachable
|
93 TerminatorKind
::Call { .. }
|
94 TerminatorKind
::Assert { .. }
|
95 TerminatorKind
::DropAndReplace { .. }
|
96 TerminatorKind
::Drop { .. }
=> {
102 fn remove_nop_landing_pads(&self, mir
: &mut Mir
) {
103 // make sure there's a single resume block
105 let patch
= MirPatch
::new(mir
);
106 let resume_block
= patch
.resume_block();
110 debug
!("remove_noop_landing_pads: resume block is {:?}", resume_block
);
112 let mut jumps_folded
= 0;
113 let mut landing_pads_removed
= 0;
114 let mut nop_landing_pads
= BitVector
::new(mir
.basic_blocks().len());
116 // This is a post-order traversal, so that if A post-dominates B
117 // then A will be visited before B.
118 let postorder
: Vec
<_
> = traversal
::postorder(mir
).map(|(bb
, _
)| bb
).collect();
119 for bb
in postorder
{
120 debug
!(" processing {:?}", bb
);
121 for target
in mir
[bb
].terminator_mut().successors_mut() {
122 if *target
!= resume_block
&& nop_landing_pads
.contains(*target
) {
123 debug
!(" folding noop jump to {:?} to resume block", target
);
124 *target
= resume_block
;
129 match mir
[bb
].terminator_mut().unwind_mut() {
131 if *unwind
== Some(resume_block
) {
132 debug
!(" removing noop landing pad");
134 landing_pads_removed
+= 1;
141 let is_nop_landing_pad
= self.is_nop_landing_pad(bb
, mir
, &nop_landing_pads
);
142 if is_nop_landing_pad
{
143 nop_landing_pads
.insert(bb
);
145 debug
!(" is_nop_landing_pad({:?}) = {}", bb
, is_nop_landing_pad
);
148 debug
!("removed {:?} jumps and {:?} landing pads", jumps_folded
, landing_pads_removed
);