about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-12-17 06:34:04 +0000
committerbors <bors@rust-lang.org>2018-12-17 06:34:04 +0000
commit7fb479c92b6358590a0180b00a416bb055b6548e (patch)
tree272694c076471065f563284bd135159440eb1377 /src
parent63f8e6e12b3f9655fb58282e7a75f411b7e8b4ee (diff)
parent83298a212076e74808198f46bb98467d2cb41ac9 (diff)
downloadrust-7fb479c92b6358590a0180b00a416bb055b6548e.tar.gz
rust-7fb479c92b6358590a0180b00a416bb055b6548e.zip
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;
}
```
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/transform/simplify.rs27
-rw-r--r--src/test/mir-opt/simplify_cfg.rs54
2 files changed, 80 insertions, 1 deletions
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index f643870dec2..592f721b2f5 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -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`
diff --git a/src/test/mir-opt/simplify_cfg.rs b/src/test/mir-opt/simplify_cfg.rs
new file mode 100644
index 00000000000..ef843f71581
--- /dev/null
+++ b/src/test/mir-opt/simplify_cfg.rs
@@ -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