Skip to content

Commit b1db8a4

Browse files
committed
merge the RemoveDeadBlocks pass into the SimplifyCfg pass
1 parent 9b2beca commit b1db8a4

File tree

4 files changed

+70
-103
lines changed

4 files changed

+70
-103
lines changed

src/librustc_driver/driver.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -964,11 +964,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
964964
time(time_passes, "MIR passes", || {
965965
let mut passes = sess.mir_passes.borrow_mut();
966966
// Push all the built-in passes.
967-
passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks);
967+
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("initial"));
968968
passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants);
969969
passes.push_pass(box mir::transform::type_check::TypeckMir);
970-
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg);
971-
passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks);
970+
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("qualify-consts"));
972971
// And run everything.
973972
passes.run_passes(tcx, &mut mir_map);
974973
});
@@ -1035,14 +1034,18 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10351034
time(time_passes, "Prepare MIR codegen passes", || {
10361035
let mut passes = ::rustc::mir::transform::Passes::new();
10371036
passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
1038-
passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks);
1037+
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("no-landing-pads"));
1038+
10391039
passes.push_pass(box mir::transform::erase_regions::EraseRegions);
1040+
10401041
passes.push_pass(box mir::transform::add_call_guards::AddCallGuards);
10411042
passes.push_pass(box borrowck::ElaborateDrops);
10421043
passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
1043-
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg);
1044+
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("elaborate-drops"));
1045+
10441046
passes.push_pass(box mir::transform::add_call_guards::AddCallGuards);
10451047
passes.push_pass(box mir::transform::dump_mir::DumpMir("pre_trans"));
1048+
10461049
passes.run_passes(tcx, &mut mir_map);
10471050
});
10481051

src/librustc_mir/transform/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
pub mod remove_dead_blocks;
1211
pub mod simplify_cfg;
1312
pub mod erase_regions;
1413
pub mod no_landing_pads;

src/librustc_mir/transform/remove_dead_blocks.rs

Lines changed: 0 additions & 86 deletions
This file was deleted.

src/librustc_mir/transform/simplify_cfg.rs

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,30 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! A pass that removes various redundancies in the CFG. It should be
12+
//! called after every significant CFG modification to tidy things
13+
//! up.
14+
//!
15+
//! This pass must also be run before any analysis passes because it removes
16+
//! dead blocks, and some of these can be ill-typed.
17+
//!
18+
//! The cause of that is that typeck lets most blocks whose end is not
19+
//! reachable have an arbitrary return type, rather than having the
20+
//! usual () return type (as a note, typeck's notion of reachability
21+
//! is in fact slightly weaker than MIR CFG reachability - see #31617).
22+
//!
23+
//! A standard example of the situation is:
24+
//! ```rust
25+
//! fn example() {
26+
//! let _a: char = { return; };
27+
//! }
28+
//! ```
29+
//!
30+
//! Here the block (`{ return; }`) has the return type `char`,
31+
//! rather than `()`, but the MIR we naively generate still contains
32+
//! the `_a = ()` write in the unreachable block "after" the return.
33+
34+
1135
use rustc_data_structures::bitvec::BitVector;
1236
use rustc::middle::const_val::ConstVal;
1337
use rustc::ty::TyCtxt;
@@ -16,32 +40,31 @@ use rustc::mir::transform::{MirPass, MirSource, Pass};
1640
use pretty;
1741
use std::mem;
1842

19-
use super::remove_dead_blocks::RemoveDeadBlocks;
20-
2143
use traversal;
2244

23-
pub struct SimplifyCfg;
45+
pub struct SimplifyCfg<'a> { label: &'a str }
2446

25-
impl SimplifyCfg {
26-
pub fn new() -> SimplifyCfg {
27-
SimplifyCfg
47+
impl<'a> SimplifyCfg<'a> {
48+
pub fn new(label: &'a str) -> Self {
49+
SimplifyCfg { label: label }
2850
}
2951
}
3052

31-
impl<'tcx> MirPass<'tcx> for SimplifyCfg {
53+
impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> {
3254
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) {
55+
pretty::dump_mir(tcx, "simplify_cfg", &format!("{}-before", self.label), src, mir, None);
3356
simplify_branches(mir);
34-
RemoveDeadBlocks.run_pass(tcx, src, mir);
57+
remove_dead_blocks(mir);
3558
merge_consecutive_blocks(mir);
36-
RemoveDeadBlocks.run_pass(tcx, src, mir);
37-
pretty::dump_mir(tcx, "simplify_cfg", &0, src, mir, None);
59+
remove_dead_blocks(mir);
60+
pretty::dump_mir(tcx, "simplify_cfg", &format!("{}-after", self.label), src, mir, None);
3861

3962
// FIXME: Should probably be moved into some kind of pass manager
4063
mir.basic_blocks.shrink_to_fit();
4164
}
4265
}
4366

44-
impl Pass for SimplifyCfg {}
67+
impl<'l> Pass for SimplifyCfg<'l> {}
4568

4669
fn merge_consecutive_blocks(mir: &mut Mir) {
4770
// Build the precedecessor map for the MIR
@@ -203,3 +226,31 @@ fn simplify_branches(mir: &mut Mir) {
203226
}
204227
}
205228
}
229+
230+
fn remove_dead_blocks(mir: &mut Mir) {
231+
let mut seen = BitVector::new(mir.basic_blocks.len());
232+
for (bb, _) in traversal::preorder(mir) {
233+
seen.insert(bb.index());
234+
}
235+
236+
let num_blocks = mir.basic_blocks.len();
237+
238+
let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
239+
let mut used_blocks = 0;
240+
for alive_index in seen.iter() {
241+
replacements[alive_index] = BasicBlock::new(used_blocks);
242+
if alive_index != used_blocks {
243+
// Swap the next alive block data with the current available slot. Since alive_index is
244+
// non-decreasing this is a valid operation.
245+
mir.basic_blocks.swap(alive_index, used_blocks);
246+
}
247+
used_blocks += 1;
248+
}
249+
mir.basic_blocks.truncate(used_blocks);
250+
251+
for bb in mir.all_basic_blocks() {
252+
for target in mir.basic_block_data_mut(bb).terminator_mut().successors_mut() {
253+
*target = replacements[target.index()];
254+
}
255+
}
256+
}

0 commit comments

Comments
 (0)