From ae51ccfa771ffdfae63ad2a5a9deecf9712833d8 Mon Sep 17 00:00:00 2001
From: Ariel Ben-Yehuda <ariel.byd@gmail.com>
Date: Tue, 4 Oct 2016 16:23:01 +0300
Subject: [PATCH 1/3] SimplifyCfg: simplify the start block

---
 src/librustc_mir/transform/simplify_cfg.rs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs
index 8e1b7b44976..228fa468841 100644
--- a/src/librustc_mir/transform/simplify_cfg.rs
+++ b/src/librustc_mir/transform/simplify_cfg.rs
@@ -50,6 +50,7 @@ impl<'a> SimplifyCfg<'a> {
 
 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>) {
+        debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir);
         CfgSimplifier::new(mir).simplify();
         remove_dead_blocks(mir);
 
@@ -78,6 +79,8 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
 
         // we can't use mir.predecessors() here because that counts
         // dead blocks, which we don't want to.
+        pred_count[START_BLOCK] = 1;
+
         for (_, data) in traversal::preorder(mir) {
             if let Some(ref term) = data.terminator {
                 for &tgt in term.successors().iter() {

From 44ac0160cef4824082f738ce5d2b847b0b8f88ea Mon Sep 17 00:00:00 2001
From: Ariel Ben-Yehuda <ariel.byd@gmail.com>
Date: Tue, 4 Oct 2016 16:27:27 +0300
Subject: [PATCH 2/3] SimplifyCfg: don't incref target when collapsing a goto
 with 1 pred

---
 src/librustc_mir/transform/simplify_cfg.rs | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs
index 228fa468841..ca8556496fa 100644
--- a/src/librustc_mir/transform/simplify_cfg.rs
+++ b/src/librustc_mir/transform/simplify_cfg.rs
@@ -160,8 +160,16 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
         debug!("collapsing goto chain from {:?} to {:?}", *start, target);
 
         *changed |= *start != target;
-        self.pred_count[target] += 1;
-        self.pred_count[*start] -= 1;
+
+        if self.pred_count[*start] == 1 {
+            // This is the last reference to *start, so the pred-count to
+            // to target is moved into the current block.
+            self.pred_count[*start] = 0;
+        } else {
+            self.pred_count[target] += 1;
+            self.pred_count[*start] -= 1;
+        }
+
         *start = target;
     }
 

From bfdf437f37c3cffc4f9ba01f248d2e08399b4280 Mon Sep 17 00:00:00 2001
From: Ariel Ben-Yehuda <ariel.byd@gmail.com>
Date: Tue, 4 Oct 2016 20:43:43 +0300
Subject: [PATCH 3/3] update tests

---
 src/test/mir-opt/deaggregator_test.rs      | 4 ++--
 src/test/mir-opt/deaggregator_test_enum.rs | 4 ++--
 src/test/mir-opt/storage_ranges.rs         | 4 ----
 3 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/src/test/mir-opt/deaggregator_test.rs b/src/test/mir-opt/deaggregator_test.rs
index 3304a66773a..f136d74fa51 100644
--- a/src/test/mir-opt/deaggregator_test.rs
+++ b/src/test/mir-opt/deaggregator_test.rs
@@ -26,7 +26,7 @@ fn main() {}
 //     _2 = _1;
 //     _3 = _2;
 //     _0 = Baz { x: _3, y: const F32(0), z: const false };
-//     goto -> bb1;
+//     return;
 // }
 // END rustc.node13.Deaggregator.before.mir
 // START rustc.node13.Deaggregator.after.mir
@@ -36,6 +36,6 @@ fn main() {}
 //     (_0.0: usize) = _3;
 //     (_0.1: f32) = const F32(0);
 //     (_0.2: bool) = const false;
-//     goto -> bb1;
+//     return;
 // }
 // END rustc.node13.Deaggregator.after.mir
diff --git a/src/test/mir-opt/deaggregator_test_enum.rs b/src/test/mir-opt/deaggregator_test_enum.rs
index a6f12886f55..25fa0e90835 100644
--- a/src/test/mir-opt/deaggregator_test_enum.rs
+++ b/src/test/mir-opt/deaggregator_test_enum.rs
@@ -31,7 +31,7 @@ fn main() {
 //     _2 = _1;
 //     _3 = _2;
 //     _0 = Baz::Foo { x: _3 };
-//     goto -> bb1;
+//     return;
 // }
 // END rustc.node10.Deaggregator.before.mir
 // START rustc.node10.Deaggregator.after.mir
@@ -40,6 +40,6 @@ fn main() {
 //     _3 = _2;
 //     ((_0 as Foo).0: usize) = _3;
 //     discriminant(_0) = 1;
-//     goto -> bb1;
+//     return;
 // }
 // END rustc.node10.Deaggregator.after.mir
diff --git a/src/test/mir-opt/storage_ranges.rs b/src/test/mir-opt/storage_ranges.rs
index 3885b233fd2..933bfa8df2e 100644
--- a/src/test/mir-opt/storage_ranges.rs
+++ b/src/test/mir-opt/storage_ranges.rs
@@ -38,10 +38,6 @@ fn main() {
 //         _0 = ();
 //         StorageDead(_6);
 //         StorageDead(_1);
-//         goto -> bb1;
-//     }
-//
-//     bb1: {
 //         return;
 //     }
 // END rustc.node4.TypeckMir.before.mir