From 78ada846ae7d8338aef07852a60006ad5f61e76d Mon Sep 17 00:00:00 2001 From: Jonathan S Date: Sun, 6 Dec 2015 10:37:06 -0600 Subject: [PATCH 1/3] [MIR] Generalize the depth first search logic and use it in all of SimplifyCfg --- src/librustc_mir/transform/simplify_cfg.rs | 30 +++------------------- src/librustc_mir/transform/util.rs | 23 +++++++++++++++++ 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs index 558276a13a8b8..32eea9d7c8acf 100644 --- a/src/librustc_mir/transform/simplify_cfg.rs +++ b/src/librustc_mir/transform/simplify_cfg.rs @@ -21,27 +21,6 @@ impl SimplifyCfg { SimplifyCfg } - fn remove_dead_blocks(&self, mir: &mut Mir) { - let mut seen = vec![false; mir.basic_blocks.len()]; - - // These blocks are always required. - seen[START_BLOCK.index()] = true; - seen[END_BLOCK.index()] = true; - seen[DIVERGE_BLOCK.index()] = true; - - let mut worklist = vec![START_BLOCK]; - while let Some(bb) = worklist.pop() { - for succ in mir.basic_block_data(bb).terminator.successors() { - if !seen[succ.index()] { - seen[succ.index()] = true; - worklist.push(*succ); - } - } - } - - util::retain_basic_blocks(mir, &seen); - } - fn remove_goto_chains(&self, mir: &mut Mir) -> bool { // Find the target at the end of the jump chain, return None if there is a loop @@ -66,7 +45,7 @@ impl SimplifyCfg { } let mut changed = false; - for bb in mir.all_basic_blocks() { + util::adjust_reachable_basic_blocks(mir, |mir, bb| { // Temporarily swap out the terminator we're modifying to keep borrowck happy let mut terminator = Terminator::Diverge; mem::swap(&mut terminator, &mut mir.basic_block_data_mut(bb).terminator); @@ -82,7 +61,7 @@ impl SimplifyCfg { } mir.basic_block_data_mut(bb).terminator = terminator; - } + }); changed } @@ -90,7 +69,7 @@ impl SimplifyCfg { fn simplify_branches(&self, mir: &mut Mir) -> bool { let mut changed = false; - for bb in mir.all_basic_blocks() { + util::adjust_reachable_basic_blocks(mir, |mir, bb| { // Temporarily swap out the terminator we're modifying to keep borrowck happy let mut terminator = Terminator::Diverge; mem::swap(&mut terminator, &mut mir.basic_block_data_mut(bb).terminator); @@ -114,7 +93,7 @@ impl SimplifyCfg { } _ => terminator } - } + }); changed } @@ -126,7 +105,6 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg { while changed { changed = self.simplify_branches(mir); changed |= self.remove_goto_chains(mir); - self.remove_dead_blocks(mir); } // FIXME: Should probably be moved into some kind of pass manager diff --git a/src/librustc_mir/transform/util.rs b/src/librustc_mir/transform/util.rs index 9510269454485..a83b8105dd177 100644 --- a/src/librustc_mir/transform/util.rs +++ b/src/librustc_mir/transform/util.rs @@ -21,6 +21,29 @@ pub fn update_basic_block_ids(mir: &mut Mir, replacements: &[BasicBlock]) { } } +pub fn adjust_reachable_basic_blocks(mir: &mut Mir, mut func: F) { + let mut seen = vec![false; mir.basic_blocks.len()]; + + let mut worklist = vec![START_BLOCK]; + while let Some(bb) = worklist.pop() { + func(mir, bb); + + for succ in mir.basic_block_data(bb).terminator.successors() { + if !seen[succ.index()] { + seen[succ.index()] = true; + worklist.push(*succ); + } + } + } + + // These blocks are always required. + seen[START_BLOCK.index()] = true; + seen[END_BLOCK.index()] = true; + seen[DIVERGE_BLOCK.index()] = true; + + retain_basic_blocks(mir, &seen); +} + /// Mass removal of basic blocks to keep the ID-remapping cheap. pub fn retain_basic_blocks(mir: &mut Mir, keep: &[bool]) { let num_blocks = mir.basic_blocks.len(); From b59f377352010c04bf5c9622cfb9165a9b570cfa Mon Sep 17 00:00:00 2001 From: Jonathan S Date: Sun, 6 Dec 2015 10:47:22 -0600 Subject: [PATCH 2/3] [MIR] Add documentation to adjust_reachable_basic_blocks --- src/librustc_mir/transform/util.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_mir/transform/util.rs b/src/librustc_mir/transform/util.rs index a83b8105dd177..30cf82e422940 100644 --- a/src/librustc_mir/transform/util.rs +++ b/src/librustc_mir/transform/util.rs @@ -21,6 +21,8 @@ pub fn update_basic_block_ids(mir: &mut Mir, replacements: &[BasicBlock]) { } } +/// Run a function on every reachable basic block, then delete any unreachable blocks. +/// The function given should not add or remove and blocks from the control flow graph. pub fn adjust_reachable_basic_blocks(mir: &mut Mir, mut func: F) { let mut seen = vec![false; mir.basic_blocks.len()]; From 852997815445b54ea1d21fe1bb2be6a3dc9695fb Mon Sep 17 00:00:00 2001 From: Jonathan S Date: Sun, 6 Dec 2015 13:18:39 -0600 Subject: [PATCH 3/3] [MIR] Fix typo in adjust_reachable_basic_blocks' docs --- src/librustc_mir/transform/util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/util.rs b/src/librustc_mir/transform/util.rs index 30cf82e422940..23ba61260e4ae 100644 --- a/src/librustc_mir/transform/util.rs +++ b/src/librustc_mir/transform/util.rs @@ -22,7 +22,7 @@ pub fn update_basic_block_ids(mir: &mut Mir, replacements: &[BasicBlock]) { } /// Run a function on every reachable basic block, then delete any unreachable blocks. -/// The function given should not add or remove and blocks from the control flow graph. +/// The function given should not add or remove any blocks from the control flow graph. pub fn adjust_reachable_basic_blocks(mir: &mut Mir, mut func: F) { let mut seen = vec![false; mir.basic_blocks.len()];