about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSimon Vandel Sillesen <simon.vandel@gmail.com>2020-08-02 01:47:52 +0200
committerSimon Vandel Sillesen <simon.vandel@gmail.com>2020-09-20 14:45:46 +0200
commit5fb32c2e33fd102adb14d943355542d1a1d2e68e (patch)
tree3845c1017e52d602d7e20cc1d4b404a92ee3465e
parent5e449b9adff463455743291b0c1f76feec092992 (diff)
downloadrust-5fb32c2e33fd102adb14d943355542d1a1d2e68e.tar.gz
rust-5fb32c2e33fd102adb14d943355542d1a1d2e68e.zip
New MIR optimization pass to reduce branches on match of tuples of enums
-rw-r--r--compiler/rustc_mir/src/transform/early_otherwise_branch.rs313
-rw-r--r--compiler/rustc_mir/src/transform/mod.rs2
-rw-r--r--src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff88
-rw-r--r--src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff.32bit88
-rw-r--r--src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff.64bit88
-rw-r--r--src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff105
-rw-r--r--src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff.32bit105
-rw-r--r--src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff.64bit105
-rw-r--r--src/test/mir-opt/early_otherwise_branch.rs23
-rw-r--r--src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff117
-rw-r--r--src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff.32bit117
-rw-r--r--src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff.64bit117
-rw-r--r--src/test/mir-opt/early_otherwise_branch_3_element_tuple.rs14
-rw-r--r--src/test/mir-opt/early_otherwise_branch_68867.rs31
-rw-r--r--src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff219
-rw-r--r--src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff114
-rw-r--r--src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff.32bit114
-rw-r--r--src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff.64bit114
-rw-r--r--src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff72
-rw-r--r--src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff.32bit72
-rw-r--r--src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff.64bit72
-rw-r--r--src/test/mir-opt/early_otherwise_branch_noopt.rs29
22 files changed, 2119 insertions, 0 deletions
diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs
new file mode 100644
index 00000000000..0dc311ebb8c
--- /dev/null
+++ b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs
@@ -0,0 +1,313 @@
+use crate::{
+    transform::{MirPass, MirSource},
+    util::patch::MirPatch,
+};
+use rustc_middle::mir::*;
+use rustc_middle::ty::{Ty, TyCtxt};
+use std::{borrow::Cow, fmt::Debug};
+
+/// This pass optimizes something like
+/// ```text
+/// let x: Option<()>;
+/// let y: Option<()>;
+/// match (x,y) {
+///     (Some(_), Some(_)) => {0},
+///     _ => {1}
+/// }
+/// ```
+/// into something like
+/// ```text
+/// let x: Option<()>;
+/// let y: Option<()>;
+/// let discriminant_x = // get discriminant of x
+/// let discriminant_y = // get discriminant of x
+/// if discriminant_x != discriminant_y {1} else {0}
+/// ```
+pub struct EarlyOtherwiseBranch;
+
+impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+        if tcx.sess.opts.debugging_opts.mir_opt_level < 3 {
+            return;
+        }
+        trace!("running EarlyOtherwiseBranch on {:?}", source);
+        // we are only interested in this bb if the terminator is a switchInt
+        let bbs_with_switch =
+            body.basic_blocks().iter_enumerated().filter(|(_, bb)| is_switch(bb.terminator()));
+
+        let opts_to_apply: Vec<OptimizationToApply<'tcx>> = bbs_with_switch
+            .flat_map(|(bb_idx, bb)| {
+                let switch = bb.terminator();
+                let helper = Helper { body, tcx };
+                let infos = helper.go(bb, switch)?;
+                Some(OptimizationToApply { infos, basic_block_first_switch: bb_idx })
+            })
+            .collect();
+
+        for opt_to_apply in opts_to_apply {
+            trace!("SUCCESS: found optimization possibility to apply: {:?}", &opt_to_apply);
+            // create the patch using MirPatch
+            let mut patch = MirPatch::new(body);
+
+            // create temp to store second discriminant in
+            let discr_type = opt_to_apply.infos[0].second_switch_info.discr_ty;
+            let discr_span = opt_to_apply.infos[0].second_switch_info.discr_source_info.span;
+            let temp = patch.new_temp(discr_type, discr_span);
+            let statements_before =
+                body.basic_blocks()[opt_to_apply.basic_block_first_switch].statements.len();
+            let end_of_block_location = Location {
+                block: opt_to_apply.basic_block_first_switch,
+                statement_index: statements_before,
+            };
+            patch.add_statement(end_of_block_location, StatementKind::StorageLive(temp));
+
+            // create assignment of discriminant
+            let place_of_adt_to_get_discriminant_of =
+                opt_to_apply.infos[0].second_switch_info.place_of_adt_discr_read;
+            patch.add_assign(
+                end_of_block_location,
+                Place::from(temp),
+                Rvalue::Discriminant(place_of_adt_to_get_discriminant_of),
+            );
+
+            // create temp to store NotEqual comparison between the two discriminants
+            let not_equal = BinOp::Ne;
+            let not_equal_res_type = not_equal.ty(tcx, discr_type, discr_type);
+            let not_equal_temp = patch.new_temp(not_equal_res_type, discr_span);
+            patch.add_statement(end_of_block_location, StatementKind::StorageLive(not_equal_temp));
+
+            // create NotEqual comparison between the two discriminants
+            let first_descriminant_place =
+                opt_to_apply.infos[0].first_switch_info.discr_used_in_switch;
+            let not_equal_rvalue = Rvalue::BinaryOp(
+                not_equal,
+                Operand::Copy(Place::from(temp)),
+                Operand::Copy(Place::from(first_descriminant_place)),
+            );
+            patch.add_statement(
+                end_of_block_location,
+                StatementKind::Assign(box (Place::from(not_equal_temp), not_equal_rvalue)),
+            );
+
+            let (mut targets_to_jump_to, values_to_jump_to): (Vec<_>, Vec<_>) = opt_to_apply
+                .infos
+                .iter()
+                .flat_map(|x| x.second_switch_info.targets_with_values.iter())
+                .cloned()
+                .unzip();
+
+            // add otherwise case in the end
+            targets_to_jump_to.push(opt_to_apply.infos[0].first_switch_info.otherwise_bb);
+            // new block that jumps to the correct discriminant case. This block is switched to if the discriminants are equal
+            let new_switch_data = BasicBlockData::new(Some(Terminator {
+                source_info: opt_to_apply.infos[0].second_switch_info.discr_source_info,
+                kind: TerminatorKind::SwitchInt {
+                    // the first and second discriminants are equal, so just pick one
+                    discr: Operand::Copy(first_descriminant_place),
+                    switch_ty: discr_type,
+                    values: Cow::from(values_to_jump_to),
+                    targets: targets_to_jump_to,
+                },
+            }));
+
+            let new_switch_bb = patch.new_block(new_switch_data);
+
+            // switch on the NotEqual. If true, then jump to the `otherwise` case.
+            // If false, then jump to a basic block that then jumps to the correct disciminant case
+            let true_case = opt_to_apply.infos[0].first_switch_info.otherwise_bb;
+            let false_case = new_switch_bb;
+            patch.patch_terminator(
+                opt_to_apply.basic_block_first_switch,
+                TerminatorKind::if_(
+                    tcx,
+                    Operand::Move(Place::from(not_equal_temp)),
+                    true_case,
+                    false_case,
+                ),
+            );
+
+            // generate StorageDead for the temp not in use anymore. We use the not_equal_temp in the switch, so we can't mark that dead
+            patch.add_statement(end_of_block_location, StatementKind::StorageDead(temp));
+
+            patch.apply(body);
+        }
+    }
+}
+
+fn is_switch<'tcx>(terminator: &Terminator<'tcx>) -> bool {
+    match terminator.kind {
+        TerminatorKind::SwitchInt { .. } => true,
+        _ => false,
+    }
+}
+
+struct Helper<'a, 'tcx> {
+    body: &'a Body<'tcx>,
+    tcx: TyCtxt<'tcx>,
+}
+
+#[derive(Debug, Clone)]
+struct SwitchDiscriminantInfo<'tcx> {
+    /// Type of the discriminant being switched on
+    discr_ty: Ty<'tcx>,
+    /// The basic block that the otherwise branch points to
+    otherwise_bb: BasicBlock,
+    /// Target along with the value being branched from. Otherwise is not included
+    targets_with_values: Vec<(BasicBlock, u128)>,
+    discr_source_info: SourceInfo,
+    /// The place of the discriminant used in the switch
+    discr_used_in_switch: Place<'tcx>,
+    /// The place of the adt that has its discriminant read
+    place_of_adt_discr_read: Place<'tcx>,
+    /// The type of the adt that has its discriminant read
+    type_adt_matched_on: Ty<'tcx>,
+}
+
+#[derive(Debug)]
+struct OptimizationToApply<'tcx> {
+    infos: Vec<OptimizationInfo<'tcx>>,
+    /// Basic block of the original first switch
+    basic_block_first_switch: BasicBlock,
+}
+
+#[derive(Debug)]
+struct OptimizationInfo<'tcx> {
+    /// Info about the first switch and discriminant
+    first_switch_info: SwitchDiscriminantInfo<'tcx>,
+    /// Info about the second switch and discriminant
+    second_switch_info: SwitchDiscriminantInfo<'tcx>,
+}
+
+impl<'a, 'tcx> Helper<'a, 'tcx> {
+    pub fn go(
+        &self,
+        bb: &BasicBlockData<'tcx>,
+        switch: &Terminator<'tcx>,
+    ) -> Option<Vec<OptimizationInfo<'tcx>>> {
+        // try to find the statement that defines the discriminant that is used for the switch
+        let discr = self.find_switch_discriminant_info(bb, switch)?;
+
+        // go through each target, finding a discriminant read, and a switch
+        let results = discr.targets_with_values.iter().map(|(target, value)| {
+            self.find_discriminant_switch_pairing(&discr, target.clone(), value.clone())
+        });
+
+        // if the optimization did not apply for one of the targets, then abort
+        if results.clone().any(|x| x.is_none()) || results.len() == 0 {
+            trace!("NO: not all of the targets matched the pattern for optimization");
+            return None;
+        }
+
+        Some(results.flatten().collect())
+    }
+
+    fn find_discriminant_switch_pairing(
+        &self,
+        discr_info: &SwitchDiscriminantInfo<'tcx>,
+        target: BasicBlock,
+        value: u128,
+    ) -> Option<OptimizationInfo<'tcx>> {
+        let bb = &self.body.basic_blocks()[target];
+        // find switch
+        let terminator = bb.terminator();
+        if is_switch(terminator) {
+            let this_bb_discr_info = self.find_switch_discriminant_info(bb, terminator)?;
+
+            // the types of the two adts matched on have to be equalfor this optimization to apply
+            if discr_info.type_adt_matched_on != this_bb_discr_info.type_adt_matched_on {
+                trace!(
+                    "NO: types do not match. LHS: {:?}, RHS: {:?}",
+                    discr_info.type_adt_matched_on,
+                    this_bb_discr_info.type_adt_matched_on
+                );
+                return None;
+            }
+
+            // the otherwise branch of the two switches have to point to the same bb
+            if discr_info.otherwise_bb != this_bb_discr_info.otherwise_bb {
+                trace!("NO: otherwise target is not the same");
+                return None;
+            }
+
+            // check that the value being matched on is the same. The
+            if this_bb_discr_info.targets_with_values.iter().find(|x| x.1 == value).is_none() {
+                trace!("NO: values being matched on are not the same");
+                return None;
+            }
+
+            // only allow optimization if the left and right of the tuple being matched are the same variants.
+            // so the following should not optimize
+            //  ```rust
+            // let x: Option<()>;
+            // let y: Option<()>;
+            // match (x,y) {
+            //     (Some(_), None) => {},
+            //     _ => {}
+            // }
+            //  ```
+            // We check this by seeing that the value of the first discriminant is the only other discriminant value being used as a target in the second switch
+            if !(this_bb_discr_info.targets_with_values.len() == 1
+                && this_bb_discr_info.targets_with_values[0].1 == value)
+            {
+                trace!(
+                    "NO: The second switch did not have only 1 target (besides otherwise) that had the same value as the value from the first switch that got us here"
+                );
+                return None;
+            }
+
+            // if we reach this point, the optimization applies, and we should be able to optimize this case
+            // store the info that is needed to apply the optimization
+
+            Some(OptimizationInfo {
+                first_switch_info: discr_info.clone(),
+                second_switch_info: this_bb_discr_info,
+            })
+        } else {
+            None
+        }
+    }
+
+    fn find_switch_discriminant_info(
+        &self,
+        bb: &BasicBlockData<'tcx>,
+        switch: &Terminator<'tcx>,
+    ) -> Option<SwitchDiscriminantInfo<'tcx>> {
+        match &switch.kind {
+            TerminatorKind::SwitchInt { discr, targets, values, .. } => {
+                let discr_local = discr.place()?.as_local()?;
+                // the declaration of the discriminant read. Place of this read is being used in the switch
+                let discr_decl = &self.body.local_decls()[discr_local];
+                let discr_ty = discr_decl.ty;
+                // the otherwise target lies as the last element
+                let otherwise_bb = targets.get(values.len())?.clone();
+                let targets_with_values = targets
+                    .iter()
+                    .zip(values.iter())
+                    .map(|(t, v)| (t.clone(), v.clone()))
+                    .collect();
+
+                // find the place of the adt where the discriminant is being read from
+                // assume this is the last statement of the block
+                let place_of_adt_discr_read = match bb.statements.last()?.kind {
+                    StatementKind::Assign(box (_, Rvalue::Discriminant(adt_place))) => {
+                        Some(adt_place)
+                    }
+                    _ => None,
+                }?;
+
+                let type_adt_matched_on = place_of_adt_discr_read.ty(self.body, self.tcx).ty;
+
+                Some(SwitchDiscriminantInfo {
+                    discr_used_in_switch: discr.place()?,
+                    discr_ty,
+                    otherwise_bb,
+                    targets_with_values,
+                    discr_source_info: discr_decl.source_info,
+                    place_of_adt_discr_read,
+                    type_adt_matched_on,
+                })
+            }
+            _ => unreachable!("must only be passed terminator that is a switch"),
+        }
+    }
+}
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs
index fc9854ba499..abe2dc496a6 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir/src/transform/mod.rs
@@ -26,6 +26,7 @@ pub mod copy_prop;
 pub mod deaggregator;
 pub mod dest_prop;
 pub mod dump_mir;
+pub mod early_otherwise_branch;
 pub mod elaborate_drops;
 pub mod generator;
 pub mod inline;
@@ -465,6 +466,7 @@ fn run_optimization_passes<'tcx>(
         &instcombine::InstCombine,
         &const_prop::ConstProp,
         &simplify_branches::SimplifyBranches::new("after-const-prop"),
+        &early_otherwise_branch::EarlyOtherwiseBranch,
         &simplify_comparison_integral::SimplifyComparisonIntegral,
         &simplify_try::SimplifyArmIdentity,
         &simplify_try::SimplifyBranchSame,
diff --git a/src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
new file mode 100644
index 00000000000..28c9d422a9f
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
@@ -0,0 +1,88 @@
+- // MIR for `opt1` before EarlyOtherwiseBranch
++ // MIR for `opt1` after EarlyOtherwiseBranch
+  
+  fn opt1(_1: std::option::Option<usize>, _2: std::option::Option<usize>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch.rs:5:9: 5:10
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch.rs:5:27: 5:28
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch.rs:5:47: 5:52
+      let mut _3: (std::option::Option<usize>, std::option::Option<usize>); // in scope 0 at $DIR/early_otherwise_branch.rs:6:11: 6:16
+      let mut _4: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch.rs:6:12: 6:13
+      let mut _5: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch.rs:6:14: 6:15
+      let mut _6: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:7:19: 7:26
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:7:10: 7:17
+      let _8: usize;                       // in scope 0 at $DIR/early_otherwise_branch.rs:7:15: 7:16
+      let _9: usize;                       // in scope 0 at $DIR/early_otherwise_branch.rs:7:24: 7:25
++     let mut _10: isize;                  // in scope 0 at $DIR/early_otherwise_branch.rs:7:19: 7:26
++     let mut _11: bool;                   // in scope 0 at $DIR/early_otherwise_branch.rs:7:19: 7:26
+      scope 1 {
+          debug a => _8;                   // in scope 1 at $DIR/early_otherwise_branch.rs:7:15: 7:16
+          debug b => _9;                   // in scope 1 at $DIR/early_otherwise_branch.rs:7:24: 7:25
+      }
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:6:11: 6:16
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:6:12: 6:13
+          _4 = _1;                         // scope 0 at $DIR/early_otherwise_branch.rs:6:12: 6:13
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:6:14: 6:15
+          _5 = _2;                         // scope 0 at $DIR/early_otherwise_branch.rs:6:14: 6:15
+          (_3.0: std::option::Option<usize>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:6:11: 6:16
+          (_3.1: std::option::Option<usize>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:6:11: 6:16
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:6:15: 6:16
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:6:15: 6:16
+          _7 = discriminant((_3.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:7:10: 7:17
+-         switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:7:10: 7:17
++         StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:7:10: 7:17
++         _10 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:7:10: 7:17
++         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:7:10: 7:17
++         _11 = Ne(_10, _7);               // scope 0 at $DIR/early_otherwise_branch.rs:7:10: 7:17
++         StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:7:10: 7:17
++         switchInt(move _11) -> [false: bb6, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:7:10: 7:17
+      }
+  
+      bb1: {
+          _0 = const 1_usize;              // scope 0 at $DIR/early_otherwise_branch.rs:8:14: 8:15
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:8:14: 8:15
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) }
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:6:5: 9:6
+      }
+  
+      bb2: {
+          _6 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:7:19: 7:26
+          switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:7:19: 7:26
+      }
+  
+      bb3: {
+          StorageLive(_8);                 // scope 0 at $DIR/early_otherwise_branch.rs:7:15: 7:16
+          _8 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch.rs:7:15: 7:16
+          StorageLive(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:7:24: 7:25
+          _9 = (((_3.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch.rs:7:24: 7:25
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch.rs:7:31: 7:32
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:7:31: 7:32
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+          StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:7:31: 7:32
+          StorageDead(_8);                 // scope 0 at $DIR/early_otherwise_branch.rs:7:31: 7:32
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:6:5: 9:6
+      }
+  
+      bb4: {
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:10:1: 10:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch.rs:10:2: 10:2
++     }
++ 
++     bb5 (cleanup): {
++         resume;                          // scope 0 at $DIR/early_otherwise_branch.rs:5:1: 10:2
++     }
++ 
++     bb6: {
++         switchInt(_7) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:7:19: 7:26
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff.32bit b/src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff.32bit
new file mode 100644
index 00000000000..dbeb09bf2bb
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff.32bit
@@ -0,0 +1,88 @@
+- // MIR for `opt1` before EarlyOtherwiseBranch
++ // MIR for `opt1` after EarlyOtherwiseBranch
+  
+  fn opt1(_1: std::option::Option<usize>, _2: std::option::Option<usize>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch.rs:4:9: 4:10
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch.rs:4:27: 4:28
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch.rs:4:47: 4:52
+      let mut _3: (std::option::Option<usize>, std::option::Option<usize>); // in scope 0 at $DIR/early_otherwise_branch.rs:5:11: 5:16
+      let mut _4: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch.rs:5:12: 5:13
+      let mut _5: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch.rs:5:14: 5:15
+      let mut _6: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:6:19: 6:26
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
+      let _8: usize;                       // in scope 0 at $DIR/early_otherwise_branch.rs:6:15: 6:16
+      let _9: usize;                       // in scope 0 at $DIR/early_otherwise_branch.rs:6:24: 6:25
++     let mut _10: isize;                  // in scope 0 at $DIR/early_otherwise_branch.rs:6:19: 6:26
++     let mut _11: bool;                   // in scope 0 at $DIR/early_otherwise_branch.rs:6:19: 6:26
+      scope 1 {
+          debug a => _8;                   // in scope 1 at $DIR/early_otherwise_branch.rs:6:15: 6:16
+          debug b => _9;                   // in scope 1 at $DIR/early_otherwise_branch.rs:6:24: 6:25
+      }
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:5:11: 5:16
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:5:12: 5:13
+          _4 = _1;                         // scope 0 at $DIR/early_otherwise_branch.rs:5:12: 5:13
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:5:14: 5:15
+          _5 = _2;                         // scope 0 at $DIR/early_otherwise_branch.rs:5:14: 5:15
+          (_3.0: std::option::Option<usize>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:5:11: 5:16
+          (_3.1: std::option::Option<usize>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:5:11: 5:16
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:5:15: 5:16
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:5:15: 5:16
+          _7 = discriminant((_3.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
+-         switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
++         StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
++         _10 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
++         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
++         _11 = Ne(_10, _7);               // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
++         StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
++         switchInt(move _11) -> [false: bb6, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
+      }
+  
+      bb1: {
+          _0 = const 1_usize;              // scope 0 at $DIR/early_otherwise_branch.rs:7:14: 7:15
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x00000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:7:14: 7:15
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) }
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:5:5: 8:6
+      }
+  
+      bb2: {
+          _6 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:6:19: 6:26
+          switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:6:19: 6:26
+      }
+  
+      bb3: {
+          StorageLive(_8);                 // scope 0 at $DIR/early_otherwise_branch.rs:6:15: 6:16
+          _8 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch.rs:6:15: 6:16
+          StorageLive(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:6:24: 6:25
+          _9 = (((_3.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch.rs:6:24: 6:25
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch.rs:6:31: 6:32
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x00000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:6:31: 6:32
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x00000000)) }
+          StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:6:31: 6:32
+          StorageDead(_8);                 // scope 0 at $DIR/early_otherwise_branch.rs:6:31: 6:32
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:5:5: 8:6
+      }
+  
+      bb4: {
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:9:1: 9:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch.rs:9:2: 9:2
++     }
++ 
++     bb5 (cleanup): {
++         resume;                          // scope 0 at $DIR/early_otherwise_branch.rs:4:1: 9:2
++     }
++ 
++     bb6: {
++         switchInt(_7) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:6:19: 6:26
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff.64bit b/src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff.64bit
new file mode 100644
index 00000000000..62a40a440db
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff.64bit
@@ -0,0 +1,88 @@
+- // MIR for `opt1` before EarlyOtherwiseBranch
++ // MIR for `opt1` after EarlyOtherwiseBranch
+  
+  fn opt1(_1: std::option::Option<usize>, _2: std::option::Option<usize>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch.rs:4:9: 4:10
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch.rs:4:27: 4:28
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch.rs:4:47: 4:52
+      let mut _3: (std::option::Option<usize>, std::option::Option<usize>); // in scope 0 at $DIR/early_otherwise_branch.rs:5:11: 5:16
+      let mut _4: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch.rs:5:12: 5:13
+      let mut _5: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch.rs:5:14: 5:15
+      let mut _6: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:6:19: 6:26
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
+      let _8: usize;                       // in scope 0 at $DIR/early_otherwise_branch.rs:6:15: 6:16
+      let _9: usize;                       // in scope 0 at $DIR/early_otherwise_branch.rs:6:24: 6:25
++     let mut _10: isize;                  // in scope 0 at $DIR/early_otherwise_branch.rs:6:19: 6:26
++     let mut _11: bool;                   // in scope 0 at $DIR/early_otherwise_branch.rs:6:19: 6:26
+      scope 1 {
+          debug a => _8;                   // in scope 1 at $DIR/early_otherwise_branch.rs:6:15: 6:16
+          debug b => _9;                   // in scope 1 at $DIR/early_otherwise_branch.rs:6:24: 6:25
+      }
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:5:11: 5:16
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:5:12: 5:13
+          _4 = _1;                         // scope 0 at $DIR/early_otherwise_branch.rs:5:12: 5:13
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:5:14: 5:15
+          _5 = _2;                         // scope 0 at $DIR/early_otherwise_branch.rs:5:14: 5:15
+          (_3.0: std::option::Option<usize>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:5:11: 5:16
+          (_3.1: std::option::Option<usize>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:5:11: 5:16
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:5:15: 5:16
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:5:15: 5:16
+          _7 = discriminant((_3.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
+-         switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
++         StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
++         _10 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
++         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
++         _11 = Ne(_10, _7);               // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
++         StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
++         switchInt(move _11) -> [false: bb6, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:6:10: 6:17
+      }
+  
+      bb1: {
+          _0 = const 1_usize;              // scope 0 at $DIR/early_otherwise_branch.rs:7:14: 7:15
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:7:14: 7:15
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) }
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:5:5: 8:6
+      }
+  
+      bb2: {
+          _6 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:6:19: 6:26
+          switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:6:19: 6:26
+      }
+  
+      bb3: {
+          StorageLive(_8);                 // scope 0 at $DIR/early_otherwise_branch.rs:6:15: 6:16
+          _8 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch.rs:6:15: 6:16
+          StorageLive(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:6:24: 6:25
+          _9 = (((_3.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch.rs:6:24: 6:25
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch.rs:6:31: 6:32
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:6:31: 6:32
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+          StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:6:31: 6:32
+          StorageDead(_8);                 // scope 0 at $DIR/early_otherwise_branch.rs:6:31: 6:32
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:5:5: 8:6
+      }
+  
+      bb4: {
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:9:1: 9:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch.rs:9:2: 9:2
++     }
++ 
++     bb5 (cleanup): {
++         resume;                          // scope 0 at $DIR/early_otherwise_branch.rs:4:1: 9:2
++     }
++ 
++     bb6: {
++         switchInt(_7) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:6:19: 6:26
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
new file mode 100644
index 00000000000..1868f4f5be1
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
@@ -0,0 +1,105 @@
+- // MIR for `opt2` before EarlyOtherwiseBranch
++ // MIR for `opt2` after EarlyOtherwiseBranch
+  
+  fn opt2(_1: std::option::Option<usize>, _2: std::option::Option<usize>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch.rs:13:9: 13:10
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch.rs:13:27: 13:28
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch.rs:13:47: 13:52
+      let mut _3: (std::option::Option<usize>, std::option::Option<usize>); // in scope 0 at $DIR/early_otherwise_branch.rs:14:11: 14:16
+      let mut _4: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch.rs:14:12: 14:13
+      let mut _5: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch.rs:14:14: 14:15
+      let mut _6: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:16:16: 16:20
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:15:19: 15:26
+      let mut _8: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:15:10: 15:17
+      let _9: usize;                       // in scope 0 at $DIR/early_otherwise_branch.rs:15:15: 15:16
+      let _10: usize;                      // in scope 0 at $DIR/early_otherwise_branch.rs:15:24: 15:25
++     let mut _11: isize;                  // in scope 0 at $DIR/early_otherwise_branch.rs:16:16: 16:20
++     let mut _12: bool;                   // in scope 0 at $DIR/early_otherwise_branch.rs:16:16: 16:20
+      scope 1 {
+          debug a => _9;                   // in scope 1 at $DIR/early_otherwise_branch.rs:15:15: 15:16
+          debug b => _10;                  // in scope 1 at $DIR/early_otherwise_branch.rs:15:24: 15:25
+      }
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:14:11: 14:16
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:14:12: 14:13
+          _4 = _1;                         // scope 0 at $DIR/early_otherwise_branch.rs:14:12: 14:13
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:14:14: 14:15
+          _5 = _2;                         // scope 0 at $DIR/early_otherwise_branch.rs:14:14: 14:15
+          (_3.0: std::option::Option<usize>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:14:11: 14:16
+          (_3.1: std::option::Option<usize>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:14:11: 14:16
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:14:15: 14:16
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:14:15: 14:16
+          _8 = discriminant((_3.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:15:10: 15:17
+-         switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:15:10: 15:17
++         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:15:10: 15:17
++         _11 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:15:10: 15:17
++         StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch.rs:15:10: 15:17
++         _12 = Ne(_11, _8);               // scope 0 at $DIR/early_otherwise_branch.rs:15:10: 15:17
++         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:15:10: 15:17
++         switchInt(move _12) -> [false: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:15:10: 15:17
+      }
+  
+      bb1: {
+          _6 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:16:16: 16:20
+          switchInt(move _6) -> [0_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:16:16: 16:20
+      }
+  
+      bb2: {
+          _0 = const 1_usize;              // scope 0 at $DIR/early_otherwise_branch.rs:17:14: 17:15
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:17:14: 17:15
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) }
+          goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:14:5: 18:6
+      }
+  
+      bb3: {
+          _7 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:15:19: 15:26
+          switchInt(move _7) -> [1_isize: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:15:19: 15:26
+      }
+  
+      bb4: {
+          StorageLive(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:15:15: 15:16
+          _9 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch.rs:15:15: 15:16
+          StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:15:24: 15:25
+          _10 = (((_3.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch.rs:15:24: 15:25
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch.rs:15:31: 15:32
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:15:31: 15:32
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+          StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:15:31: 15:32
+          StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:15:31: 15:32
+          goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:14:5: 18:6
+      }
+  
+      bb5: {
+          _0 = const 0_usize;              // scope 0 at $DIR/early_otherwise_branch.rs:16:25: 16:26
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:16:25: 16:26
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+          goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:14:5: 18:6
+      }
+  
+      bb6: {
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:19:1: 19:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch.rs:19:2: 19:2
++     }
++ 
++     bb7 (cleanup): {
++         resume;                          // scope 0 at $DIR/early_otherwise_branch.rs:13:1: 19:2
++     }
++ 
++     bb8: {
++         switchInt(_8) -> [0_isize: bb5, 1_isize: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:16:16: 16:20
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff.32bit b/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff.32bit
new file mode 100644
index 00000000000..38c303dc814
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff.32bit
@@ -0,0 +1,105 @@
+- // MIR for `opt2` before EarlyOtherwiseBranch
++ // MIR for `opt2` after EarlyOtherwiseBranch
+  
+  fn opt2(_1: std::option::Option<usize>, _2: std::option::Option<usize>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch.rs:12:9: 12:10
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch.rs:12:27: 12:28
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch.rs:12:47: 12:52
+      let mut _3: (std::option::Option<usize>, std::option::Option<usize>); // in scope 0 at $DIR/early_otherwise_branch.rs:13:11: 13:16
+      let mut _4: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch.rs:13:12: 13:13
+      let mut _5: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch.rs:13:14: 13:15
+      let mut _6: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:15:16: 15:20
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:14:19: 14:26
+      let mut _8: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
+      let _9: usize;                       // in scope 0 at $DIR/early_otherwise_branch.rs:14:15: 14:16
+      let _10: usize;                      // in scope 0 at $DIR/early_otherwise_branch.rs:14:24: 14:25
++     let mut _11: isize;                  // in scope 0 at $DIR/early_otherwise_branch.rs:15:16: 15:20
++     let mut _12: bool;                   // in scope 0 at $DIR/early_otherwise_branch.rs:15:16: 15:20
+      scope 1 {
+          debug a => _9;                   // in scope 1 at $DIR/early_otherwise_branch.rs:14:15: 14:16
+          debug b => _10;                  // in scope 1 at $DIR/early_otherwise_branch.rs:14:24: 14:25
+      }
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:13:11: 13:16
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:13:12: 13:13
+          _4 = _1;                         // scope 0 at $DIR/early_otherwise_branch.rs:13:12: 13:13
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:13:14: 13:15
+          _5 = _2;                         // scope 0 at $DIR/early_otherwise_branch.rs:13:14: 13:15
+          (_3.0: std::option::Option<usize>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:13:11: 13:16
+          (_3.1: std::option::Option<usize>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:13:11: 13:16
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
+          _8 = discriminant((_3.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
+-         switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
++         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
++         _11 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
++         StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
++         _12 = Ne(_11, _8);               // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
++         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
++         switchInt(move _12) -> [false: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
+      }
+  
+      bb1: {
+          _6 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:15:16: 15:20
+          switchInt(move _6) -> [0_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:15:16: 15:20
+      }
+  
+      bb2: {
+          _0 = const 1_usize;              // scope 0 at $DIR/early_otherwise_branch.rs:16:14: 16:15
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x00000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:16:14: 16:15
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) }
+          goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:13:5: 17:6
+      }
+  
+      bb3: {
+          _7 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:14:19: 14:26
+          switchInt(move _7) -> [1_isize: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:14:19: 14:26
+      }
+  
+      bb4: {
+          StorageLive(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:14:15: 14:16
+          _9 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch.rs:14:15: 14:16
+          StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:14:24: 14:25
+          _10 = (((_3.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch.rs:14:24: 14:25
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch.rs:14:31: 14:32
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x00000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:14:31: 14:32
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x00000000)) }
+          StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:14:31: 14:32
+          StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:14:31: 14:32
+          goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:13:5: 17:6
+      }
+  
+      bb5: {
+          _0 = const 0_usize;              // scope 0 at $DIR/early_otherwise_branch.rs:15:25: 15:26
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x00000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:15:25: 15:26
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x00000000)) }
+          goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:13:5: 17:6
+      }
+  
+      bb6: {
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:18:1: 18:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch.rs:18:2: 18:2
++     }
++ 
++     bb7 (cleanup): {
++         resume;                          // scope 0 at $DIR/early_otherwise_branch.rs:12:1: 18:2
++     }
++ 
++     bb8: {
++         switchInt(_8) -> [0_isize: bb5, 1_isize: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:15:16: 15:20
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff.64bit b/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff.64bit
new file mode 100644
index 00000000000..5449158bff0
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff.64bit
@@ -0,0 +1,105 @@
+- // MIR for `opt2` before EarlyOtherwiseBranch
++ // MIR for `opt2` after EarlyOtherwiseBranch
+  
+  fn opt2(_1: std::option::Option<usize>, _2: std::option::Option<usize>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch.rs:12:9: 12:10
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch.rs:12:27: 12:28
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch.rs:12:47: 12:52
+      let mut _3: (std::option::Option<usize>, std::option::Option<usize>); // in scope 0 at $DIR/early_otherwise_branch.rs:13:11: 13:16
+      let mut _4: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch.rs:13:12: 13:13
+      let mut _5: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch.rs:13:14: 13:15
+      let mut _6: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:15:16: 15:20
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:14:19: 14:26
+      let mut _8: isize;                   // in scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
+      let _9: usize;                       // in scope 0 at $DIR/early_otherwise_branch.rs:14:15: 14:16
+      let _10: usize;                      // in scope 0 at $DIR/early_otherwise_branch.rs:14:24: 14:25
++     let mut _11: isize;                  // in scope 0 at $DIR/early_otherwise_branch.rs:15:16: 15:20
++     let mut _12: bool;                   // in scope 0 at $DIR/early_otherwise_branch.rs:15:16: 15:20
+      scope 1 {
+          debug a => _9;                   // in scope 1 at $DIR/early_otherwise_branch.rs:14:15: 14:16
+          debug b => _10;                  // in scope 1 at $DIR/early_otherwise_branch.rs:14:24: 14:25
+      }
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:13:11: 13:16
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:13:12: 13:13
+          _4 = _1;                         // scope 0 at $DIR/early_otherwise_branch.rs:13:12: 13:13
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:13:14: 13:15
+          _5 = _2;                         // scope 0 at $DIR/early_otherwise_branch.rs:13:14: 13:15
+          (_3.0: std::option::Option<usize>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:13:11: 13:16
+          (_3.1: std::option::Option<usize>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:13:11: 13:16
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
+          _8 = discriminant((_3.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
+-         switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
++         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
++         _11 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
++         StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
++         _12 = Ne(_11, _8);               // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
++         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
++         switchInt(move _12) -> [false: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:14:10: 14:17
+      }
+  
+      bb1: {
+          _6 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:15:16: 15:20
+          switchInt(move _6) -> [0_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:15:16: 15:20
+      }
+  
+      bb2: {
+          _0 = const 1_usize;              // scope 0 at $DIR/early_otherwise_branch.rs:16:14: 16:15
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:16:14: 16:15
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) }
+          goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:13:5: 17:6
+      }
+  
+      bb3: {
+          _7 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch.rs:14:19: 14:26
+          switchInt(move _7) -> [1_isize: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:14:19: 14:26
+      }
+  
+      bb4: {
+          StorageLive(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:14:15: 14:16
+          _9 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch.rs:14:15: 14:16
+          StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:14:24: 14:25
+          _10 = (((_3.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch.rs:14:24: 14:25
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch.rs:14:31: 14:32
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:14:31: 14:32
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+          StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:14:31: 14:32
+          StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:14:31: 14:32
+          goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:13:5: 17:6
+      }
+  
+      bb5: {
+          _0 = const 0_usize;              // scope 0 at $DIR/early_otherwise_branch.rs:15:25: 15:26
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch.rs:15:25: 15:26
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+          goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:13:5: 17:6
+      }
+  
+      bb6: {
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch.rs:18:1: 18:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch.rs:18:2: 18:2
++     }
++ 
++     bb7 (cleanup): {
++         resume;                          // scope 0 at $DIR/early_otherwise_branch.rs:12:1: 18:2
++     }
++ 
++     bb8: {
++         switchInt(_8) -> [0_isize: bb5, 1_isize: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:15:16: 15:20
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch.rs b/src/test/mir-opt/early_otherwise_branch.rs
new file mode 100644
index 00000000000..a1ffcda7467
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Z mir-opt-level=3
+// EMIT_MIR_FOR_EACH_BIT_WIDTH
+// EMIT_MIR early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
+fn opt1(x: Option<usize>, y:Option<usize>) -> usize {
+    match (x,y) {
+        (Some(a), Some(b)) => 0,
+        _ => 1
+    }
+}
+
+// EMIT_MIR early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
+fn opt2(x: Option<usize>, y:Option<usize>) -> usize {
+    match (x,y) {
+        (Some(a), Some(b)) => 0,
+        (None, None) => 0,
+        _ => 1
+    }
+}
+
+fn main() {
+    opt1(None, Some(0));
+    opt2(None, Some(0));
+}
diff --git a/src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
new file mode 100644
index 00000000000..9c326895d29
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
@@ -0,0 +1,117 @@
+- // MIR for `opt1` before EarlyOtherwiseBranch
++ // MIR for `opt1` after EarlyOtherwiseBranch
+  
+  fn opt1(_1: std::option::Option<usize>, _2: std::option::Option<usize>, _3: std::option::Option<usize>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:9: 5:10
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:27: 5:28
+      debug z => _3;                       // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:44: 5:45
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:64: 5:69
+      let mut _4: (std::option::Option<usize>, std::option::Option<usize>, std::option::Option<usize>); // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+      let mut _5: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:12: 6:13
+      let mut _6: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:14: 6:15
+      let mut _7: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:16: 6:17
+      let mut _8: isize;                   // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+      let mut _9: isize;                   // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
+      let mut _10: isize;                  // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
+      let _11: usize;                      // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:15: 7:16
+      let _12: usize;                      // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:24: 7:25
+      let _13: usize;                      // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:33: 7:34
++     let mut _14: isize;                  // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++     let mut _15: bool;                   // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++     let mut _16: isize;                  // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
++     let mut _17: bool;                   // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+      scope 1 {
+          debug a => _11;                  // in scope 1 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:15: 7:16
+          debug b => _12;                  // in scope 1 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:24: 7:25
+          debug c => _13;                  // in scope 1 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:33: 7:34
+      }
+  
+      bb0: {
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:12: 6:13
+          _5 = _1;                         // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:12: 6:13
+          StorageLive(_6);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:14: 6:15
+          _6 = _2;                         // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:14: 6:15
+          StorageLive(_7);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:16: 6:17
+          _7 = _3;                         // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:16: 6:17
+          (_4.0: std::option::Option<usize>) = move _5; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+          (_4.1: std::option::Option<usize>) = move _6; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+          (_4.2: std::option::Option<usize>) = move _7; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+          StorageDead(_7);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:17: 6:18
+          StorageDead(_6);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:17: 6:18
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:17: 6:18
+          _10 = discriminant((_4.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
+-         switchInt(move _10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         StorageLive(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         _14 = discriminant((_4.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         StorageLive(_15);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         _15 = Ne(_14, _10);              // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         StorageDead(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         switchInt(move _15) -> [false: bb7, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
+      }
+  
+      bb1: {
+          _0 = const 1_usize;              // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:8:14: 8:15
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_3_element_tuple.rs:8:14: 8:15
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) }
+          goto -> bb5;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:5: 9:6
+      }
+  
+      bb2: {
+          _9 = discriminant((_4.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
+-         switchInt(move _9) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         StorageLive(_16);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         _16 = discriminant((_4.2: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         StorageLive(_17);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         _17 = Ne(_16, _9);               // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         StorageDead(_16);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         switchInt(move _17) -> [false: bb8, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
+      }
+  
+      bb3: {
+          _8 = discriminant((_4.2: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+          switchInt(move _8) -> [1_isize: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+      }
+  
+      bb4: {
+          StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:15: 7:16
+          _11 = (((_4.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:15: 7:16
+          StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:24: 7:25
+          _12 = (((_4.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:24: 7:25
+          StorageLive(_13);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:33: 7:34
+          _13 = (((_4.2: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:33: 7:34
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+          StorageDead(_13);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+          StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+          StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+          goto -> bb5;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:5: 9:6
+      }
+  
+      bb5: {
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:10:1: 10:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:10:2: 10:2
++     }
++ 
++     bb6 (cleanup): {
++         resume;                          // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:1: 10:2
++     }
++ 
++     bb7: {
++         switchInt(_10) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++     }
++ 
++     bb8: {
++         switchInt(_9) -> [1_isize: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff.32bit b/src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff.32bit
new file mode 100644
index 00000000000..9a3f7614ad0
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff.32bit
@@ -0,0 +1,117 @@
+- // MIR for `opt1` before EarlyOtherwiseBranch
++ // MIR for `opt1` after EarlyOtherwiseBranch
+  
+  fn opt1(_1: std::option::Option<usize>, _2: std::option::Option<usize>, _3: std::option::Option<usize>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:9: 5:10
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:27: 5:28
+      debug z => _3;                       // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:44: 5:45
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:64: 5:69
+      let mut _4: (std::option::Option<usize>, std::option::Option<usize>, std::option::Option<usize>); // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+      let mut _5: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:12: 6:13
+      let mut _6: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:14: 6:15
+      let mut _7: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:16: 6:17
+      let mut _8: isize;                   // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+      let mut _9: isize;                   // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
+      let mut _10: isize;                  // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
+      let _11: usize;                      // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:15: 7:16
+      let _12: usize;                      // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:24: 7:25
+      let _13: usize;                      // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:33: 7:34
++     let mut _14: isize;                  // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++     let mut _15: bool;                   // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++     let mut _16: isize;                  // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
++     let mut _17: bool;                   // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+      scope 1 {
+          debug a => _11;                  // in scope 1 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:15: 7:16
+          debug b => _12;                  // in scope 1 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:24: 7:25
+          debug c => _13;                  // in scope 1 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:33: 7:34
+      }
+  
+      bb0: {
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:12: 6:13
+          _5 = _1;                         // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:12: 6:13
+          StorageLive(_6);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:14: 6:15
+          _6 = _2;                         // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:14: 6:15
+          StorageLive(_7);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:16: 6:17
+          _7 = _3;                         // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:16: 6:17
+          (_4.0: std::option::Option<usize>) = move _5; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+          (_4.1: std::option::Option<usize>) = move _6; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+          (_4.2: std::option::Option<usize>) = move _7; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+          StorageDead(_7);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:17: 6:18
+          StorageDead(_6);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:17: 6:18
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:17: 6:18
+          _10 = discriminant((_4.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
+-         switchInt(move _10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         StorageLive(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         _14 = discriminant((_4.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         StorageLive(_15);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         _15 = Ne(_14, _10);              // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         StorageDead(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         switchInt(move _15) -> [false: bb7, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
+      }
+  
+      bb1: {
+          _0 = const 1_usize;              // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:8:14: 8:15
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x00000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_3_element_tuple.rs:8:14: 8:15
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) }
+          goto -> bb5;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:5: 9:6
+      }
+  
+      bb2: {
+          _9 = discriminant((_4.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
+-         switchInt(move _9) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         StorageLive(_16);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         _16 = discriminant((_4.2: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         StorageLive(_17);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         _17 = Ne(_16, _9);               // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         StorageDead(_16);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         switchInt(move _17) -> [false: bb8, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
+      }
+  
+      bb3: {
+          _8 = discriminant((_4.2: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+          switchInt(move _8) -> [1_isize: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+      }
+  
+      bb4: {
+          StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:15: 7:16
+          _11 = (((_4.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:15: 7:16
+          StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:24: 7:25
+          _12 = (((_4.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:24: 7:25
+          StorageLive(_13);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:33: 7:34
+          _13 = (((_4.2: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:33: 7:34
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x00000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x00000000)) }
+          StorageDead(_13);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+          StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+          StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+          goto -> bb5;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:5: 9:6
+      }
+  
+      bb5: {
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:10:1: 10:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:10:2: 10:2
++     }
++ 
++     bb6 (cleanup): {
++         resume;                          // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:1: 10:2
++     }
++ 
++     bb7: {
++         switchInt(_10) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++     }
++ 
++     bb8: {
++         switchInt(_9) -> [1_isize: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff.64bit b/src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff.64bit
new file mode 100644
index 00000000000..9c326895d29
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff.64bit
@@ -0,0 +1,117 @@
+- // MIR for `opt1` before EarlyOtherwiseBranch
++ // MIR for `opt1` after EarlyOtherwiseBranch
+  
+  fn opt1(_1: std::option::Option<usize>, _2: std::option::Option<usize>, _3: std::option::Option<usize>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:9: 5:10
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:27: 5:28
+      debug z => _3;                       // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:44: 5:45
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:64: 5:69
+      let mut _4: (std::option::Option<usize>, std::option::Option<usize>, std::option::Option<usize>); // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+      let mut _5: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:12: 6:13
+      let mut _6: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:14: 6:15
+      let mut _7: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:16: 6:17
+      let mut _8: isize;                   // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+      let mut _9: isize;                   // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
+      let mut _10: isize;                  // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
+      let _11: usize;                      // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:15: 7:16
+      let _12: usize;                      // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:24: 7:25
+      let _13: usize;                      // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:33: 7:34
++     let mut _14: isize;                  // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++     let mut _15: bool;                   // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++     let mut _16: isize;                  // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
++     let mut _17: bool;                   // in scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+      scope 1 {
+          debug a => _11;                  // in scope 1 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:15: 7:16
+          debug b => _12;                  // in scope 1 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:24: 7:25
+          debug c => _13;                  // in scope 1 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:33: 7:34
+      }
+  
+      bb0: {
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:12: 6:13
+          _5 = _1;                         // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:12: 6:13
+          StorageLive(_6);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:14: 6:15
+          _6 = _2;                         // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:14: 6:15
+          StorageLive(_7);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:16: 6:17
+          _7 = _3;                         // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:16: 6:17
+          (_4.0: std::option::Option<usize>) = move _5; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+          (_4.1: std::option::Option<usize>) = move _6; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+          (_4.2: std::option::Option<usize>) = move _7; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:11: 6:18
+          StorageDead(_7);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:17: 6:18
+          StorageDead(_6);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:17: 6:18
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:17: 6:18
+          _10 = discriminant((_4.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
+-         switchInt(move _10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         StorageLive(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         _14 = discriminant((_4.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         StorageLive(_15);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         _15 = Ne(_14, _10);              // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         StorageDead(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
++         switchInt(move _15) -> [false: bb7, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:10: 7:17
+      }
+  
+      bb1: {
+          _0 = const 1_usize;              // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:8:14: 8:15
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_3_element_tuple.rs:8:14: 8:15
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) }
+          goto -> bb5;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:5: 9:6
+      }
+  
+      bb2: {
+          _9 = discriminant((_4.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
+-         switchInt(move _9) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         StorageLive(_16);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         _16 = discriminant((_4.2: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         StorageLive(_17);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         _17 = Ne(_16, _9);               // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         StorageDead(_16);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++         switchInt(move _17) -> [false: bb8, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
+      }
+  
+      bb3: {
+          _8 = discriminant((_4.2: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+          switchInt(move _8) -> [1_isize: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+      }
+  
+      bb4: {
+          StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:15: 7:16
+          _11 = (((_4.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:15: 7:16
+          StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:24: 7:25
+          _12 = (((_4.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:24: 7:25
+          StorageLive(_13);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:33: 7:34
+          _13 = (((_4.2: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:33: 7:34
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+          StorageDead(_13);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+          StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+          StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:40: 7:41
+          goto -> bb5;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:5: 9:6
+      }
+  
+      bb5: {
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:10:1: 10:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:10:2: 10:2
++     }
++ 
++     bb6 (cleanup): {
++         resume;                          // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:1: 10:2
++     }
++ 
++     bb7: {
++         switchInt(_10) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:19: 7:26
++     }
++ 
++     bb8: {
++         switchInt(_9) -> [1_isize: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:28: 7:35
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch_3_element_tuple.rs b/src/test/mir-opt/early_otherwise_branch_3_element_tuple.rs
new file mode 100644
index 00000000000..ffb5de096c3
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch_3_element_tuple.rs
@@ -0,0 +1,14 @@
+// compile-flags: -Z mir-opt-level=3
+
+// EMIT_MIR_FOR_EACH_BIT_WIDTH
+// EMIT_MIR early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
+fn opt1(x: Option<usize>, y:Option<usize>, z:Option<usize>) -> usize {
+    match (x,y,z) {
+        (Some(a), Some(b), Some(c)) => 0,
+        _ => 1
+    }
+}
+
+fn main() {
+    opt1(None, Some(0), None);
+}
diff --git a/src/test/mir-opt/early_otherwise_branch_68867.rs b/src/test/mir-opt/early_otherwise_branch_68867.rs
new file mode 100644
index 00000000000..abe666f9ca4
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch_68867.rs
@@ -0,0 +1,31 @@
+// compile-flags: -Z mir-opt-level=3
+
+// example from #68867
+type CSSFloat = f32;
+
+pub enum ViewportPercentageLength {
+    Vw(CSSFloat),
+    Vh(CSSFloat),
+    Vmin(CSSFloat),
+    Vmax(CSSFloat),
+}
+
+// EMIT_MIR early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
+#[no_mangle]
+pub extern "C" fn try_sum(x: &ViewportPercentageLength,
+                          other: &ViewportPercentageLength)
+                        -> Result<ViewportPercentageLength, ()> {
+    use self::ViewportPercentageLength::*;
+    Ok(match (x, other) {
+        (&Vw(one), &Vw(other)) => Vw(one + other),
+        (&Vh(one), &Vh(other)) => Vh(one + other),
+        (&Vmin(one), &Vmin(other)) => Vmin(one + other),
+        (&Vmax(one), &Vmax(other)) => Vmax(one + other),
+        _ => return Err(()),
+    })
+}
+
+
+fn main() {
+    try_sum(&ViewportPercentageLength::Vw(1.0), &ViewportPercentageLength::Vw(2.0));
+}
diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
new file mode 100644
index 00000000000..7a02a1c3470
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
@@ -0,0 +1,219 @@
+- // MIR for `try_sum` before EarlyOtherwiseBranch
++ // MIR for `try_sum` after EarlyOtherwiseBranch
+  
+  fn try_sum(_1: &ViewportPercentageLength, _2: &ViewportPercentageLength) -> std::result::Result<ViewportPercentageLength, ()> {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch_68867.rs:15:27: 15:28
+      debug other => _2;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:16:27: 16:32
+      let mut _0: std::result::Result<ViewportPercentageLength, ()>; // return place in scope 0 at $DIR/early_otherwise_branch_68867.rs:17:28: 17:64
+      let mut _3: ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:19:8: 25:6
+      let mut _4: (&ViewportPercentageLength, &ViewportPercentageLength); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:19:14: 19:24
+      let mut _5: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:19:15: 19:16
+      let mut _6: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:19:18: 19:23
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:20:21: 20:30
+      let mut _8: isize;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:21: 21:30
+      let mut _9: isize;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:23: 22:34
+      let mut _10: isize;                  // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:23: 23:34
+      let mut _11: isize;                  // in scope 0 at $DIR/early_otherwise_branch_68867.rs:20:11: 20:18
+      let _12: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:20:14: 20:17
+      let _13: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:20:24: 20:29
+      let mut _14: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:20:38: 20:49
+      let mut _15: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:20:38: 20:41
+      let mut _16: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:20:44: 20:49
+      let _17: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:17
+      let _18: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:24: 21:29
+      let mut _19: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:38: 21:49
+      let mut _20: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:38: 21:41
+      let mut _21: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:44: 21:49
+      let _22: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:16: 22:19
+      let _23: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:28: 22:33
+      let mut _24: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:55
+      let mut _25: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:47
+      let mut _26: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:50: 22:55
+      let _27: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:16: 23:19
+      let _28: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:28: 23:33
+      let mut _29: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:55
+      let mut _30: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:47
+      let mut _31: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:50: 23:55
+      let mut _32: !;                      // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:14: 24:28
+      let mut _33: ();                     // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:25: 24:27
++     let mut _34: isize;                  // in scope 0 at $DIR/early_otherwise_branch_68867.rs:20:21: 20:30
++     let mut _35: bool;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:20:21: 20:30
+      scope 1 {
+          debug one => _12;                // in scope 1 at $DIR/early_otherwise_branch_68867.rs:20:14: 20:17
+          debug other => _13;              // in scope 1 at $DIR/early_otherwise_branch_68867.rs:20:24: 20:29
+      }
+      scope 2 {
+          debug one => _17;                // in scope 2 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:17
+          debug other => _18;              // in scope 2 at $DIR/early_otherwise_branch_68867.rs:21:24: 21:29
+      }
+      scope 3 {
+          debug one => _22;                // in scope 3 at $DIR/early_otherwise_branch_68867.rs:22:16: 22:19
+          debug other => _23;              // in scope 3 at $DIR/early_otherwise_branch_68867.rs:22:28: 22:33
+      }
+      scope 4 {
+          debug one => _27;                // in scope 4 at $DIR/early_otherwise_branch_68867.rs:23:16: 23:19
+          debug other => _28;              // in scope 4 at $DIR/early_otherwise_branch_68867.rs:23:28: 23:33
+      }
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:8: 25:6
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:14: 19:24
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:15: 19:16
+          _5 = _1;                         // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:15: 19:16
+          StorageLive(_6);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:18: 19:23
+          _6 = _2;                         // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:18: 19:23
+          (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:14: 19:24
+          (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:14: 19:24
+          StorageDead(_6);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:23: 19:24
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:23: 19:24
+          _11 = discriminant((*(_4.0: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:11: 20:18
+-         switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:11: 20:18
++         StorageLive(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:11: 20:18
++         _34 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:11: 20:18
++         StorageLive(_35);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:11: 20:18
++         _35 = Ne(_34, _11);              // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:11: 20:18
++         StorageDead(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:11: 20:18
++         switchInt(move _35) -> [false: bb13, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:11: 20:18
+      }
+  
+      bb1: {
+          _7 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:21: 20:30
+          switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:21: 20:30
+      }
+  
+      bb2: {
+          StorageLive(_33);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:25: 24:27
+          ((_0 as Err).0: ()) = const ();  // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:21: 24:28
+                                           // ty::Const
+                                           // + ty: ()
+                                           // + val: Value(Scalar(<ZST>))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_68867.rs:24:21: 24:28
+                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+          discriminant(_0) = 1;            // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:21: 24:28
+          StorageDead(_33);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:27: 24:28
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:6: 25:7
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:1: 26:2
+          goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:14: 24:28
+      }
+  
+      bb3: {
+          _8 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:21: 21:30
+          switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:21: 21:30
+      }
+  
+      bb4: {
+          _9 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:23: 22:34
+          switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:23: 22:34
+      }
+  
+      bb5: {
+          _10 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:23: 23:34
+          switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:23: 23:34
+      }
+  
+      bb6: {
+          StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:14: 20:17
+          _12 = (((*(_4.0: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:14: 20:17
+          StorageLive(_13);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:24: 20:29
+          _13 = (((*(_4.1: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:24: 20:29
+          StorageLive(_14);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:20:38: 20:49
+          StorageLive(_15);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:20:38: 20:41
+          _15 = _12;                       // scope 1 at $DIR/early_otherwise_branch_68867.rs:20:38: 20:41
+          StorageLive(_16);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:20:44: 20:49
+          _16 = _13;                       // scope 1 at $DIR/early_otherwise_branch_68867.rs:20:44: 20:49
+          _14 = Add(move _15, move _16);   // scope 1 at $DIR/early_otherwise_branch_68867.rs:20:38: 20:49
+          StorageDead(_16);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:20:48: 20:49
+          StorageDead(_15);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:20:48: 20:49
+          ((_3 as Vw).0: f32) = move _14;  // scope 1 at $DIR/early_otherwise_branch_68867.rs:20:35: 20:50
+          discriminant(_3) = 0;            // scope 1 at $DIR/early_otherwise_branch_68867.rs:20:35: 20:50
+          StorageDead(_14);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:20:49: 20:50
+          StorageDead(_13);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:49: 20:50
+          StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:49: 20:50
+          goto -> bb11;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:8: 25:6
+      }
+  
+      bb7: {
+          StorageLive(_17);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:17
+          _17 = (((*(_4.0: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:17
+          StorageLive(_18);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:24: 21:29
+          _18 = (((*(_4.1: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:24: 21:29
+          StorageLive(_19);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:21:38: 21:49
+          StorageLive(_20);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:21:38: 21:41
+          _20 = _17;                       // scope 2 at $DIR/early_otherwise_branch_68867.rs:21:38: 21:41
+          StorageLive(_21);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:21:44: 21:49
+          _21 = _18;                       // scope 2 at $DIR/early_otherwise_branch_68867.rs:21:44: 21:49
+          _19 = Add(move _20, move _21);   // scope 2 at $DIR/early_otherwise_branch_68867.rs:21:38: 21:49
+          StorageDead(_21);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:21:48: 21:49
+          StorageDead(_20);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:21:48: 21:49
+          ((_3 as Vh).0: f32) = move _19;  // scope 2 at $DIR/early_otherwise_branch_68867.rs:21:35: 21:50
+          discriminant(_3) = 1;            // scope 2 at $DIR/early_otherwise_branch_68867.rs:21:35: 21:50
+          StorageDead(_19);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:21:49: 21:50
+          StorageDead(_18);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:49: 21:50
+          StorageDead(_17);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:49: 21:50
+          goto -> bb11;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:8: 25:6
+      }
+  
+      bb8: {
+          StorageLive(_22);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:16: 22:19
+          _22 = (((*(_4.0: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:16: 22:19
+          StorageLive(_23);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:28: 22:33
+          _23 = (((*(_4.1: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:28: 22:33
+          StorageLive(_24);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:55
+          StorageLive(_25);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:47
+          _25 = _22;                       // scope 3 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:47
+          StorageLive(_26);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:22:50: 22:55
+          _26 = _23;                       // scope 3 at $DIR/early_otherwise_branch_68867.rs:22:50: 22:55
+          _24 = Add(move _25, move _26);   // scope 3 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:55
+          StorageDead(_26);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:22:54: 22:55
+          StorageDead(_25);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:22:54: 22:55
+          ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:22:39: 22:56
+          discriminant(_3) = 2;            // scope 3 at $DIR/early_otherwise_branch_68867.rs:22:39: 22:56
+          StorageDead(_24);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:22:55: 22:56
+          StorageDead(_23);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:55: 22:56
+          StorageDead(_22);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:55: 22:56
+          goto -> bb11;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:8: 25:6
+      }
+  
+      bb9: {
+          StorageLive(_27);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:16: 23:19
+          _27 = (((*(_4.0: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:16: 23:19
+          StorageLive(_28);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:28: 23:33
+          _28 = (((*(_4.1: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:28: 23:33
+          StorageLive(_29);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:55
+          StorageLive(_30);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:47
+          _30 = _27;                       // scope 4 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:47
+          StorageLive(_31);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:23:50: 23:55
+          _31 = _28;                       // scope 4 at $DIR/early_otherwise_branch_68867.rs:23:50: 23:55
+          _29 = Add(move _30, move _31);   // scope 4 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:55
+          StorageDead(_31);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:23:54: 23:55
+          StorageDead(_30);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:23:54: 23:55
+          ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:23:39: 23:56
+          discriminant(_3) = 3;            // scope 4 at $DIR/early_otherwise_branch_68867.rs:23:39: 23:56
+          StorageDead(_29);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:23:55: 23:56
+          StorageDead(_28);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:55: 23:56
+          StorageDead(_27);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:55: 23:56
+          goto -> bb11;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:8: 25:6
+      }
+  
+      bb10: {
+          return;                          // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:2: 26:2
+      }
+  
+      bb11: {
+          ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:5: 25:7
+          discriminant(_0) = 0;            // scope 0 at $DIR/early_otherwise_branch_68867.rs:19:5: 25:7
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:6: 25:7
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:1: 26:2
+          goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:2: 26:2
++     }
++ 
++     bb12 (cleanup): {
++         resume;                          // scope 0 at $DIR/early_otherwise_branch_68867.rs:15:1: 26:2
++     }
++ 
++     bb13: {
++         switchInt(_11) -> [0_isize: bb6, 1_isize: bb7, 2_isize: bb8, 3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:20:21: 20:30
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
new file mode 100644
index 00000000000..9908843a2d8
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
@@ -0,0 +1,114 @@
+- // MIR for `noopt1` before EarlyOtherwiseBranch
++ // MIR for `noopt1` after EarlyOtherwiseBranch
+  
+  fn noopt1(_1: std::option::Option<usize>, _2: std::option::Option<usize>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:12
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:29: 8:30
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:49: 8:54
+      let mut _3: (std::option::Option<usize>, std::option::Option<usize>); // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:11: 9:16
+      let mut _4: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:12: 9:13
+      let mut _5: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:14: 9:15
+      let mut _6: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:16: 12:23
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:19: 10:26
+      let mut _8: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:10: 10:17
+      let _9: usize;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
+      let _10: usize;                      // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:24: 10:25
+      let _11: usize;                      // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:15: 11:16
+      let _12: usize;                      // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:21: 12:22
+      scope 1 {
+          debug a => _9;                   // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
+          debug b => _10;                  // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:10:24: 10:25
+      }
+      scope 2 {
+          debug a => _11;                  // in scope 2 at $DIR/early_otherwise_branch_noopt.rs:11:15: 11:16
+      }
+      scope 3 {
+          debug b => _12;                  // in scope 3 at $DIR/early_otherwise_branch_noopt.rs:12:21: 12:22
+      }
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:11: 9:16
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:12: 9:13
+          _4 = _1;                         // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:12: 9:13
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:14: 9:15
+          _5 = _2;                         // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:14: 9:15
+          (_3.0: std::option::Option<usize>) = move _4; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:11: 9:16
+          (_3.1: std::option::Option<usize>) = move _5; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:11: 9:16
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16
+          _8 = discriminant((_3.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:10: 10:17
+          switchInt(move _8) -> [0_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:10: 10:17
+      }
+  
+      bb1: {
+          _6 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:16: 12:23
+          switchInt(move _6) -> [0_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:16: 12:23
+      }
+  
+      bb2: {
+          _0 = const 3_usize;              // scope 0 at $DIR/early_otherwise_branch_noopt.rs:13:25: 13:26
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000003))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:13:25: 13:26
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:5: 14:6
+      }
+  
+      bb3: {
+          _7 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:19: 10:26
+          switchInt(move _7) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:19: 10:26
+      }
+  
+      bb4: {
+          StorageLive(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
+          _9 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
+          StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:24: 10:25
+          _10 = (((_3.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:24: 10:25
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch_noopt.rs:10:31: 10:32
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:10:31: 10:32
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+          StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:31: 10:32
+          StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:31: 10:32
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:5: 14:6
+      }
+  
+      bb5: {
+          StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:15: 11:16
+          _11 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:15: 11:16
+          _0 = const 1_usize;              // scope 2 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) }
+          StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:5: 14:6
+      }
+  
+      bb6: {
+          StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:21: 12:22
+          _12 = (((_3.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:21: 12:22
+          _0 = const 2_usize;              // scope 3 at $DIR/early_otherwise_branch_noopt.rs:12:28: 12:29
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000002))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:12:28: 12:29
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000002)) }
+          StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:28: 12:29
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:5: 14:6
+      }
+  
+      bb7: {
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:15:1: 15:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch_noopt.rs:15:2: 15:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff.32bit b/src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff.32bit
new file mode 100644
index 00000000000..26842c74e6f
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff.32bit
@@ -0,0 +1,114 @@
+- // MIR for `noopt1` before EarlyOtherwiseBranch
++ // MIR for `noopt1` after EarlyOtherwiseBranch
+  
+  fn noopt1(_1: std::option::Option<usize>, _2: std::option::Option<usize>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:12
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:29: 8:30
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:49: 8:54
+      let mut _3: (std::option::Option<usize>, std::option::Option<usize>); // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:11: 9:16
+      let mut _4: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:12: 9:13
+      let mut _5: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:14: 9:15
+      let mut _6: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:16: 12:23
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:19: 10:26
+      let mut _8: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:10: 10:17
+      let _9: usize;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
+      let _10: usize;                      // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:24: 10:25
+      let _11: usize;                      // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:15: 11:16
+      let _12: usize;                      // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:21: 12:22
+      scope 1 {
+          debug a => _9;                   // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
+          debug b => _10;                  // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:10:24: 10:25
+      }
+      scope 2 {
+          debug a => _11;                  // in scope 2 at $DIR/early_otherwise_branch_noopt.rs:11:15: 11:16
+      }
+      scope 3 {
+          debug b => _12;                  // in scope 3 at $DIR/early_otherwise_branch_noopt.rs:12:21: 12:22
+      }
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:11: 9:16
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:12: 9:13
+          _4 = _1;                         // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:12: 9:13
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:14: 9:15
+          _5 = _2;                         // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:14: 9:15
+          (_3.0: std::option::Option<usize>) = move _4; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:11: 9:16
+          (_3.1: std::option::Option<usize>) = move _5; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:11: 9:16
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16
+          _8 = discriminant((_3.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:10: 10:17
+          switchInt(move _8) -> [0_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:10: 10:17
+      }
+  
+      bb1: {
+          _6 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:16: 12:23
+          switchInt(move _6) -> [0_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:16: 12:23
+      }
+  
+      bb2: {
+          _0 = const 3_usize;              // scope 0 at $DIR/early_otherwise_branch_noopt.rs:13:25: 13:26
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x00000003))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:13:25: 13:26
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) }
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:5: 14:6
+      }
+  
+      bb3: {
+          _7 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:19: 10:26
+          switchInt(move _7) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:19: 10:26
+      }
+  
+      bb4: {
+          StorageLive(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
+          _9 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
+          StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:24: 10:25
+          _10 = (((_3.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:24: 10:25
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch_noopt.rs:10:31: 10:32
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x00000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:10:31: 10:32
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x00000000)) }
+          StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:31: 10:32
+          StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:31: 10:32
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:5: 14:6
+      }
+  
+      bb5: {
+          StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:15: 11:16
+          _11 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:15: 11:16
+          _0 = const 1_usize;              // scope 2 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x00000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) }
+          StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:5: 14:6
+      }
+  
+      bb6: {
+          StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:21: 12:22
+          _12 = (((_3.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:21: 12:22
+          _0 = const 2_usize;              // scope 3 at $DIR/early_otherwise_branch_noopt.rs:12:28: 12:29
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x00000002))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:12:28: 12:29
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x00000002)) }
+          StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:28: 12:29
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:5: 14:6
+      }
+  
+      bb7: {
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:15:1: 15:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch_noopt.rs:15:2: 15:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff.64bit b/src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff.64bit
new file mode 100644
index 00000000000..9908843a2d8
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff.64bit
@@ -0,0 +1,114 @@
+- // MIR for `noopt1` before EarlyOtherwiseBranch
++ // MIR for `noopt1` after EarlyOtherwiseBranch
+  
+  fn noopt1(_1: std::option::Option<usize>, _2: std::option::Option<usize>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:12
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:29: 8:30
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:49: 8:54
+      let mut _3: (std::option::Option<usize>, std::option::Option<usize>); // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:11: 9:16
+      let mut _4: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:12: 9:13
+      let mut _5: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:14: 9:15
+      let mut _6: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:16: 12:23
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:19: 10:26
+      let mut _8: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:10: 10:17
+      let _9: usize;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
+      let _10: usize;                      // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:24: 10:25
+      let _11: usize;                      // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:15: 11:16
+      let _12: usize;                      // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:21: 12:22
+      scope 1 {
+          debug a => _9;                   // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
+          debug b => _10;                  // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:10:24: 10:25
+      }
+      scope 2 {
+          debug a => _11;                  // in scope 2 at $DIR/early_otherwise_branch_noopt.rs:11:15: 11:16
+      }
+      scope 3 {
+          debug b => _12;                  // in scope 3 at $DIR/early_otherwise_branch_noopt.rs:12:21: 12:22
+      }
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:11: 9:16
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:12: 9:13
+          _4 = _1;                         // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:12: 9:13
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:14: 9:15
+          _5 = _2;                         // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:14: 9:15
+          (_3.0: std::option::Option<usize>) = move _4; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:11: 9:16
+          (_3.1: std::option::Option<usize>) = move _5; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:11: 9:16
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16
+          _8 = discriminant((_3.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:10: 10:17
+          switchInt(move _8) -> [0_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:10: 10:17
+      }
+  
+      bb1: {
+          _6 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:16: 12:23
+          switchInt(move _6) -> [0_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:16: 12:23
+      }
+  
+      bb2: {
+          _0 = const 3_usize;              // scope 0 at $DIR/early_otherwise_branch_noopt.rs:13:25: 13:26
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000003))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:13:25: 13:26
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:5: 14:6
+      }
+  
+      bb3: {
+          _7 = discriminant((_3.1: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:19: 10:26
+          switchInt(move _7) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:19: 10:26
+      }
+  
+      bb4: {
+          StorageLive(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
+          _9 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
+          StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:24: 10:25
+          _10 = (((_3.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:24: 10:25
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch_noopt.rs:10:31: 10:32
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:10:31: 10:32
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+          StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:31: 10:32
+          StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:31: 10:32
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:5: 14:6
+      }
+  
+      bb5: {
+          StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:15: 11:16
+          _11 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:15: 11:16
+          _0 = const 1_usize;              // scope 2 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) }
+          StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:5: 14:6
+      }
+  
+      bb6: {
+          StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:21: 12:22
+          _12 = (((_3.1: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:21: 12:22
+          _0 = const 2_usize;              // scope 3 at $DIR/early_otherwise_branch_noopt.rs:12:28: 12:29
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000002))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:12:28: 12:29
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000002)) }
+          StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:28: 12:29
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:5: 14:6
+      }
+  
+      bb7: {
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:15:1: 15:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch_noopt.rs:15:2: 15:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff
new file mode 100644
index 00000000000..25391ab7920
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff
@@ -0,0 +1,72 @@
+- // MIR for `noopt2` before EarlyOtherwiseBranch
++ // MIR for `noopt2` after EarlyOtherwiseBranch
+  
+  fn noopt2(_1: std::option::Option<usize>, _2: std::option::Option<bool>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:11: 19:12
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:29: 19:30
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:48: 19:53
+      let mut _3: (std::option::Option<usize>, std::option::Option<bool>); // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:11: 20:16
+      let mut _4: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:12: 20:13
+      let mut _5: std::option::Option<bool>; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:14: 20:15
+      let mut _6: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:19: 21:26
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:10: 21:17
+      let _8: usize;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:15: 21:16
+      let _9: bool;                        // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:24: 21:25
+      scope 1 {
+          debug a => _8;                   // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:21:15: 21:16
+          debug b => _9;                   // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:21:24: 21:25
+      }
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:11: 20:16
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:12: 20:13
+          _4 = _1;                         // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:12: 20:13
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:14: 20:15
+          _5 = _2;                         // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:14: 20:15
+          (_3.0: std::option::Option<usize>) = move _4; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:11: 20:16
+          (_3.1: std::option::Option<bool>) = move _5; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:11: 20:16
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:15: 20:16
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:15: 20:16
+          _7 = discriminant((_3.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:10: 21:17
+          switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:10: 21:17
+      }
+  
+      bb1: {
+          _0 = const 1_usize;              // scope 0 at $DIR/early_otherwise_branch_noopt.rs:22:14: 22:15
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:22:14: 22:15
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) }
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:5: 23:6
+      }
+  
+      bb2: {
+          _6 = discriminant((_3.1: std::option::Option<bool>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:19: 21:26
+          switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:19: 21:26
+      }
+  
+      bb3: {
+          StorageLive(_8);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:15: 21:16
+          _8 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:15: 21:16
+          StorageLive(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:24: 21:25
+          _9 = (((_3.1: std::option::Option<bool>) as Some).0: bool); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:24: 21:25
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch_noopt.rs:21:31: 21:32
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:21:31: 21:32
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+          StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:31: 21:32
+          StorageDead(_8);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:31: 21:32
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:5: 23:6
+      }
+  
+      bb4: {
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:24:1: 24:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch_noopt.rs:24:2: 24:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff.32bit b/src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff.32bit
new file mode 100644
index 00000000000..49dad4a02a4
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff.32bit
@@ -0,0 +1,72 @@
+- // MIR for `noopt2` before EarlyOtherwiseBranch
++ // MIR for `noopt2` after EarlyOtherwiseBranch
+  
+  fn noopt2(_1: std::option::Option<usize>, _2: std::option::Option<bool>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:11: 19:12
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:29: 19:30
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:48: 19:53
+      let mut _3: (std::option::Option<usize>, std::option::Option<bool>); // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:11: 20:16
+      let mut _4: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:12: 20:13
+      let mut _5: std::option::Option<bool>; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:14: 20:15
+      let mut _6: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:19: 21:26
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:10: 21:17
+      let _8: usize;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:15: 21:16
+      let _9: bool;                        // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:24: 21:25
+      scope 1 {
+          debug a => _8;                   // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:21:15: 21:16
+          debug b => _9;                   // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:21:24: 21:25
+      }
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:11: 20:16
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:12: 20:13
+          _4 = _1;                         // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:12: 20:13
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:14: 20:15
+          _5 = _2;                         // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:14: 20:15
+          (_3.0: std::option::Option<usize>) = move _4; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:11: 20:16
+          (_3.1: std::option::Option<bool>) = move _5; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:11: 20:16
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:15: 20:16
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:15: 20:16
+          _7 = discriminant((_3.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:10: 21:17
+          switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:10: 21:17
+      }
+  
+      bb1: {
+          _0 = const 1_usize;              // scope 0 at $DIR/early_otherwise_branch_noopt.rs:22:14: 22:15
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x00000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:22:14: 22:15
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) }
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:5: 23:6
+      }
+  
+      bb2: {
+          _6 = discriminant((_3.1: std::option::Option<bool>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:19: 21:26
+          switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:19: 21:26
+      }
+  
+      bb3: {
+          StorageLive(_8);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:15: 21:16
+          _8 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:15: 21:16
+          StorageLive(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:24: 21:25
+          _9 = (((_3.1: std::option::Option<bool>) as Some).0: bool); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:24: 21:25
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch_noopt.rs:21:31: 21:32
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x00000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:21:31: 21:32
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x00000000)) }
+          StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:31: 21:32
+          StorageDead(_8);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:31: 21:32
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:5: 23:6
+      }
+  
+      bb4: {
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:24:1: 24:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch_noopt.rs:24:2: 24:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff.64bit b/src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff.64bit
new file mode 100644
index 00000000000..25391ab7920
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff.64bit
@@ -0,0 +1,72 @@
+- // MIR for `noopt2` before EarlyOtherwiseBranch
++ // MIR for `noopt2` after EarlyOtherwiseBranch
+  
+  fn noopt2(_1: std::option::Option<usize>, _2: std::option::Option<bool>) -> usize {
+      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:11: 19:12
+      debug y => _2;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:29: 19:30
+      let mut _0: usize;                   // return place in scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:48: 19:53
+      let mut _3: (std::option::Option<usize>, std::option::Option<bool>); // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:11: 20:16
+      let mut _4: std::option::Option<usize>; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:12: 20:13
+      let mut _5: std::option::Option<bool>; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:14: 20:15
+      let mut _6: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:19: 21:26
+      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:10: 21:17
+      let _8: usize;                       // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:15: 21:16
+      let _9: bool;                        // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:24: 21:25
+      scope 1 {
+          debug a => _8;                   // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:21:15: 21:16
+          debug b => _9;                   // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:21:24: 21:25
+      }
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:11: 20:16
+          StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:12: 20:13
+          _4 = _1;                         // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:12: 20:13
+          StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:14: 20:15
+          _5 = _2;                         // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:14: 20:15
+          (_3.0: std::option::Option<usize>) = move _4; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:11: 20:16
+          (_3.1: std::option::Option<bool>) = move _5; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:11: 20:16
+          StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:15: 20:16
+          StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:15: 20:16
+          _7 = discriminant((_3.0: std::option::Option<usize>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:10: 21:17
+          switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:10: 21:17
+      }
+  
+      bb1: {
+          _0 = const 1_usize;              // scope 0 at $DIR/early_otherwise_branch_noopt.rs:22:14: 22:15
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000001))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:22:14: 22:15
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) }
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:5: 23:6
+      }
+  
+      bb2: {
+          _6 = discriminant((_3.1: std::option::Option<bool>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:19: 21:26
+          switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:19: 21:26
+      }
+  
+      bb3: {
+          StorageLive(_8);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:15: 21:16
+          _8 = (((_3.0: std::option::Option<usize>) as Some).0: usize); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:15: 21:16
+          StorageLive(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:24: 21:25
+          _9 = (((_3.1: std::option::Option<bool>) as Some).0: bool); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:24: 21:25
+          _0 = const 0_usize;              // scope 1 at $DIR/early_otherwise_branch_noopt.rs:21:31: 21:32
+                                           // ty::Const
+                                           // + ty: usize
+                                           // + val: Value(Scalar(0x0000000000000000))
+                                           // mir::Constant
+                                           // + span: $DIR/early_otherwise_branch_noopt.rs:21:31: 21:32
+                                           // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+          StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:31: 21:32
+          StorageDead(_8);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:31: 21:32
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:5: 23:6
+      }
+  
+      bb4: {
+          StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:24:1: 24:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch_noopt.rs:24:2: 24:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/early_otherwise_branch_noopt.rs b/src/test/mir-opt/early_otherwise_branch_noopt.rs
new file mode 100644
index 00000000000..8c4b37ac7a8
--- /dev/null
+++ b/src/test/mir-opt/early_otherwise_branch_noopt.rs
@@ -0,0 +1,29 @@
+// compile-flags: -Z mir-opt-level=3
+
+// must not optimize as it does not follow the pattern of
+// left and right hand side being the same variant
+
+// EMIT_MIR_FOR_EACH_BIT_WIDTH
+// EMIT_MIR early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
+fn noopt1(x: Option<usize>, y:Option<usize>) -> usize {
+    match (x,y) {
+        (Some(a), Some(b)) => 0,
+        (Some(a), None) => 1,
+        (None, Some(b)) => 2,
+        (None, None) => 3
+    }
+}
+
+// must not optimize as the types being matched on are not identical
+// EMIT_MIR early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff
+fn noopt2(x: Option<usize>, y:Option<bool>) -> usize {
+    match (x,y) {
+        (Some(a), Some(b)) => 0,
+        _ => 1
+    }
+}
+
+fn main() {
+    noopt1(None, Some(0));
+    noopt2(None, Some(true));
+}