Skip to content

Commit

Permalink
merge the RemoveDeadBlocks pass into the SimplifyCfg pass
Browse files Browse the repository at this point in the history
  • Loading branch information
arielb1 authored and Ariel Ben-Yehuda committed Jun 9, 2016
1 parent bb4b3fb commit e9003c5
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 103 deletions.
13 changes: 8 additions & 5 deletions src/librustc_driver/driver.rs
Expand Up @@ -976,11 +976,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
time(time_passes, "MIR passes", || {
let mut passes = sess.mir_passes.borrow_mut();
// Push all the built-in passes.
passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks);
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("initial"));
passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants);
passes.push_pass(box mir::transform::type_check::TypeckMir);
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg);
passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks);
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("qualify-consts"));
// And run everything.
passes.run_passes(tcx, &mut mir_map);
});
Expand Down Expand Up @@ -1047,14 +1046,18 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
time(time_passes, "Prepare MIR codegen passes", || {
let mut passes = ::rustc::mir::transform::Passes::new();
passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks);
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("no-landing-pads"));

passes.push_pass(box mir::transform::erase_regions::EraseRegions);

passes.push_pass(box mir::transform::add_call_guards::AddCallGuards);
passes.push_pass(box borrowck::ElaborateDrops);
passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg);
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("elaborate-drops"));

passes.push_pass(box mir::transform::add_call_guards::AddCallGuards);
passes.push_pass(box mir::transform::dump_mir::DumpMir("pre_trans"));

passes.run_passes(tcx, &mut mir_map);
});

Expand Down
1 change: 0 additions & 1 deletion src/librustc_mir/transform/mod.rs
Expand Up @@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub mod remove_dead_blocks;
pub mod simplify_cfg;
pub mod erase_regions;
pub mod no_landing_pads;
Expand Down
86 changes: 0 additions & 86 deletions src/librustc_mir/transform/remove_dead_blocks.rs

This file was deleted.

73 changes: 62 additions & 11 deletions src/librustc_mir/transform/simplify_cfg.rs
Expand Up @@ -8,6 +8,30 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A pass that removes various redundancies in the CFG. It should be
//! called after every significant CFG modification to tidy things
//! up.
//!
//! This pass must also be run before any analysis passes because it removes
//! dead blocks, and some of these can be ill-typed.
//!
//! The cause of that is that typeck lets most blocks whose end is not
//! reachable have an arbitrary return type, rather than having the
//! usual () return type (as a note, typeck's notion of reachability
//! is in fact slightly weaker than MIR CFG reachability - see #31617).
//!
//! A standard example of the situation is:
//! ```rust
//! fn example() {
//! let _a: char = { return; };
//! }
//! ```
//!
//! Here the block (`{ return; }`) has the return type `char`,
//! rather than `()`, but the MIR we naively generate still contains
//! the `_a = ()` write in the unreachable block "after" the return.


use rustc_data_structures::bitvec::BitVector;
use rustc::middle::const_val::ConstVal;
use rustc::ty::TyCtxt;
Expand All @@ -17,30 +41,29 @@ use rustc::mir::traversal;
use pretty;
use std::mem;

use super::remove_dead_blocks::RemoveDeadBlocks;
pub struct SimplifyCfg<'a> { label: &'a str }

pub struct SimplifyCfg;

impl SimplifyCfg {
pub fn new() -> SimplifyCfg {
SimplifyCfg
impl<'a> SimplifyCfg<'a> {
pub fn new(label: &'a str) -> Self {
SimplifyCfg { label: label }
}
}

impl<'tcx> MirPass<'tcx> for SimplifyCfg {
impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> {
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) {
pretty::dump_mir(tcx, "simplify_cfg", &format!("{}-before", self.label), src, mir, None);
simplify_branches(mir);
RemoveDeadBlocks.run_pass(tcx, src, mir);
remove_dead_blocks(mir);
merge_consecutive_blocks(mir);
RemoveDeadBlocks.run_pass(tcx, src, mir);
pretty::dump_mir(tcx, "simplify_cfg", &0, src, mir, None);
remove_dead_blocks(mir);
pretty::dump_mir(tcx, "simplify_cfg", &format!("{}-after", self.label), src, mir, None);

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

impl Pass for SimplifyCfg {}
impl<'l> Pass for SimplifyCfg<'l> {}

fn merge_consecutive_blocks(mir: &mut Mir) {
// Build the precedecessor map for the MIR
Expand Down Expand Up @@ -202,3 +225,31 @@ fn simplify_branches(mir: &mut Mir) {
}
}
}

fn remove_dead_blocks(mir: &mut Mir) {
let mut seen = BitVector::new(mir.basic_blocks.len());
for (bb, _) in traversal::preorder(mir) {
seen.insert(bb.index());
}

let num_blocks = mir.basic_blocks.len();

let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
let mut used_blocks = 0;
for alive_index in seen.iter() {
replacements[alive_index] = BasicBlock::new(used_blocks);
if alive_index != used_blocks {
// Swap the next alive block data with the current available slot. Since alive_index is
// non-decreasing this is a valid operation.
mir.basic_blocks.swap(alive_index, used_blocks);
}
used_blocks += 1;
}
mir.basic_blocks.truncate(used_blocks);

for bb in mir.all_basic_blocks() {
for target in mir.basic_block_data_mut(bb).terminator_mut().successors_mut() {
*target = replacements[target.index()];
}
}
}

0 comments on commit e9003c5

Please sign in to comment.