Auto merge of #56764 - sinkuu:simpcfg_bb0, r=matthewjasper

mir-opt: Make SimplifyCfg collapse goto chains starting from bb0

`SimplifyCfg` pass was not able to collapse goto chains starting from bb0, leaving MIR like this:

```
bb0: {
    goto -> bb1;
}
```
This commit is contained in:
bors 2018-12-17 06:34:04 +00:00
commit 7fb479c92b
2 changed files with 80 additions and 1 deletions

View File

@ -108,10 +108,14 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
pub fn simplify(mut self) {
self.strip_nops();
let mut start = START_BLOCK;
loop {
let mut changed = false;
for bb in (0..self.basic_blocks.len()).map(BasicBlock::new) {
self.collapse_goto_chain(&mut start, &mut changed);
for bb in self.basic_blocks.indices() {
if self.pred_count[bb] == 0 {
continue
}
@ -142,6 +146,27 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
if !changed { break }
}
if start != START_BLOCK {
debug_assert!(self.pred_count[START_BLOCK] == 0);
self.basic_blocks.swap(START_BLOCK, start);
self.pred_count.swap(START_BLOCK, start);
// pred_count == 1 if the start block has no predecessor _blocks_.
if self.pred_count[START_BLOCK] > 1 {
for (bb, data) in self.basic_blocks.iter_enumerated_mut() {
if self.pred_count[bb] == 0 {
continue;
}
for target in data.terminator_mut().successors_mut() {
if *target == start {
*target = START_BLOCK;
}
}
}
}
}
}
// Collapse a goto chain starting from `start`

View File

@ -0,0 +1,54 @@
// Test that the goto chain starting from bb0 is collapsed.
fn main() {
loop {
if bar() {
break;
}
}
}
#[inline(never)]
fn bar() -> bool {
true
}
// END RUST SOURCE
// START rustc.main.SimplifyCfg-initial.before.mir
// bb0: {
// goto -> bb1;
// }
// bb1: {
// falseUnwind -> [real: bb3, cleanup: bb4];
// }
// ...
// bb11: {
// ...
// goto -> bb1;
// }
// END rustc.main.SimplifyCfg-initial.before.mir
// START rustc.main.SimplifyCfg-initial.after.mir
// bb0: {
// falseUnwind -> [real: bb1, cleanup: bb2];
// }
// ...
// bb5: {
// ...
// goto -> bb0;
// }
// END rustc.main.SimplifyCfg-initial.after.mir
// START rustc.main.SimplifyCfg-early-opt.before.mir
// bb0: {
// goto -> bb1;
// }
// bb1: {
// StorageLive(_2);
// _2 = const bar() -> bb3;
// }
// END rustc.main.SimplifyCfg-early-opt.before.mir
// START rustc.main.SimplifyCfg-early-opt.after.mir
// bb0: {
// StorageLive(_2);
// _2 = const bar() -> bb1;
// }
// END rustc.main.SimplifyCfg-early-opt.after.mir