about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorSimonas Kazlauskas <git@kazlauskas.me>2017-02-02 02:05:56 +0200
committerSimonas Kazlauskas <git@kazlauskas.me>2017-02-10 19:42:41 +0200
commitaac82d9b13f8ba1baebc5a2a1a673831e6f6fbe7 (patch)
tree84cd240a860c08186a117490c5547eae53b89793 /src
parent5d70a7fbe489b96272a25b3a75b5f2ef46a846a3 (diff)
downloadrust-aac82d9b13f8ba1baebc5a2a1a673831e6f6fbe7.tar.gz
rust-aac82d9b13f8ba1baebc5a2a1a673831e6f6fbe7.zip
SwitchInt over Switch
This removes another special case of Switch by replacing it with the more general SwitchInt. While
this is more clunky currently, there’s no reason we can’t make it nice (and efficient) to use.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/const_val.rs1
-rw-r--r--src/librustc/mir/mod.rs17
-rw-r--r--src/librustc/mir/tcx.rs12
-rw-r--r--src/librustc/mir/visit.rs9
-rw-r--r--src/librustc/ty/util.rs20
-rw-r--r--src/librustc_borrowck/borrowck/mir/dataflow/mod.rs1
-rw-r--r--src/librustc_borrowck/borrowck/mir/elaborate_drops.rs49
-rw-r--r--src/librustc_borrowck/borrowck/mir/gather_moves.rs3
-rw-r--r--src/librustc_const_math/int.rs8
-rw-r--r--src/librustc_data_structures/bitvec.rs4
-rw-r--r--src/librustc_mir/build/matches/test.rs52
-rw-r--r--src/librustc_mir/lib.rs2
-rw-r--r--src/librustc_mir/transform/no_landing_pads.rs1
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs1
-rw-r--r--src/librustc_mir/transform/simplify.rs1
-rw-r--r--src/librustc_mir/transform/type_check.rs14
-rw-r--r--src/librustc_passes/mir_stats.rs1
-rw-r--r--src/librustc_trans/mir/analyze.rs1
-rw-r--r--src/librustc_trans/mir/block.rs38
19 files changed, 105 insertions, 130 deletions
diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs
index f583f601726..c4e3827fef2 100644
--- a/src/librustc/middle/const_val.rs
+++ b/src/librustc/middle/const_val.rs
@@ -14,6 +14,7 @@ use std::rc::Rc;
 use hir::def_id::DefId;
 use rustc_const_math::*;
 use self::ConstVal::*;
+pub use rustc_const_math::ConstInt;
 
 use std::collections::BTreeMap;
 
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index fa7ba3e6a62..b0a6784c3c3 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -453,13 +453,6 @@ pub enum TerminatorKind<'tcx> {
         target: BasicBlock,
     },
 
-    /// lvalue evaluates to some enum; jump depending on the branch
-    Switch {
-        discr: Lvalue<'tcx>,
-        adt_def: &'tcx AdtDef,
-        targets: Vec<BasicBlock>,
-    },
-
     /// operand evaluates to an integer; jump depending on its value
     /// to one of the targets, and otherwise fallback to `otherwise`
     SwitchInt {
@@ -471,6 +464,7 @@ pub enum TerminatorKind<'tcx> {
 
         /// Possible values. The locations to branch to in each case
         /// are found in the corresponding indices from the `targets` vector.
+        // FIXME: ConstVal doesn’t quite make any sense here? Its a Switch*Int*.
         values: Vec<ConstVal>,
 
         /// Possible branch sites. The length of this vector should be
@@ -544,7 +538,6 @@ impl<'tcx> TerminatorKind<'tcx> {
         use self::TerminatorKind::*;
         match *self {
             Goto { target: ref b } => slice::ref_slice(b).into_cow(),
-            Switch { targets: ref b, .. } => b[..].into_cow(),
             SwitchInt { targets: ref b, .. } => b[..].into_cow(),
             Resume => (&[]).into_cow(),
             Return => (&[]).into_cow(),
@@ -573,7 +566,6 @@ impl<'tcx> TerminatorKind<'tcx> {
         use self::TerminatorKind::*;
         match *self {
             Goto { target: ref mut b } => vec![b],
-            Switch { targets: ref mut b, .. } => b.iter_mut().collect(),
             SwitchInt { targets: ref mut b, .. } => b.iter_mut().collect(),
             Resume => Vec::new(),
             Return => Vec::new(),
@@ -651,7 +643,6 @@ impl<'tcx> TerminatorKind<'tcx> {
         use self::TerminatorKind::*;
         match *self {
             Goto { .. } => write!(fmt, "goto"),
-            Switch { discr: ref lv, .. } => write!(fmt, "switch({:?})", lv),
             SwitchInt { discr: ref lv, .. } => write!(fmt, "switchInt({:?})", lv),
             Return => write!(fmt, "return"),
             Resume => write!(fmt, "resume"),
@@ -701,12 +692,6 @@ impl<'tcx> TerminatorKind<'tcx> {
         match *self {
             Return | Resume | Unreachable => vec![],
             Goto { .. } => vec!["".into()],
-            Switch { ref adt_def, .. } => {
-                adt_def.variants
-                       .iter()
-                       .map(|variant| variant.name.to_string().into())
-                       .collect()
-            }
             SwitchInt { ref values, .. } => {
                 values.iter()
                       .map(|const_val| {
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 68fbadd5d60..fcfd1c57672 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -17,6 +17,7 @@ use mir::*;
 use ty::subst::{Subst, Substs};
 use ty::{self, AdtDef, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use syntax::attr;
 use hir;
 
 #[derive(Copy, Clone, Debug)]
@@ -170,9 +171,14 @@ impl<'tcx> Rvalue<'tcx> {
                 Some(operand.ty(mir, tcx))
             }
             Rvalue::Discriminant(ref lval) => {
-                if let ty::TyAdt(_, _) = lval.ty(mir, tcx).to_ty(tcx).sty {
-                    // TODO
-                    None
+                if let ty::TyAdt(adt_def, _) = lval.ty(mir, tcx).to_ty(tcx).sty {
+                    // FIXME: Why this does not work?
+                    // Some(adt_def.discr_ty.to_ty(tcx))
+                    let ty = match adt_def.discr_ty {
+                        attr::SignedInt(i) => tcx.mk_mach_int(i),
+                        attr::UnsignedInt(i) => tcx.mk_mach_uint(i),
+                    };
+                    Some(ty)
                 } else {
                     None
                 }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 1e27a02287f..ca20cf6236b 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -362,15 +362,6 @@ macro_rules! make_mir_visitor {
                         self.visit_branch(block, target);
                     }
 
-                    TerminatorKind::Switch { ref $($mutability)* discr,
-                                             adt_def: _,
-                                             ref targets } => {
-                        self.visit_lvalue(discr, LvalueContext::Inspect, source_location);
-                        for &target in targets {
-                            self.visit_branch(block, target);
-                        }
-                    }
-
                     TerminatorKind::SwitchInt { ref $($mutability)* discr,
                                                 ref $($mutability)* switch_ty,
                                                 ref $($mutability)* values,
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 1df87da4227..fe4b6dad30e 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -39,27 +39,17 @@ use rustc_i128::i128;
 use hir;
 
 pub trait IntTypeExt {
-    fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx>;
+    fn to_ty<'a, 'tcx>(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx>;
     fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option<Disr>)
                            -> Option<Disr>;
     fn initial_discriminant<'a, 'tcx>(&self, _: TyCtxt<'a, 'tcx, 'tcx>) -> Disr;
 }
 
 impl IntTypeExt for attr::IntType {
-    fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
-        match *self {
-            SignedInt(ast::IntTy::I8)      => tcx.types.i8,
-            SignedInt(ast::IntTy::I16)     => tcx.types.i16,
-            SignedInt(ast::IntTy::I32)     => tcx.types.i32,
-            SignedInt(ast::IntTy::I64)     => tcx.types.i64,
-            SignedInt(ast::IntTy::I128)     => tcx.types.i128,
-            SignedInt(ast::IntTy::Is)   => tcx.types.isize,
-            UnsignedInt(ast::UintTy::U8)    => tcx.types.u8,
-            UnsignedInt(ast::UintTy::U16)   => tcx.types.u16,
-            UnsignedInt(ast::UintTy::U32)   => tcx.types.u32,
-            UnsignedInt(ast::UintTy::U64)   => tcx.types.u64,
-            UnsignedInt(ast::UintTy::U128)   => tcx.types.u128,
-            UnsignedInt(ast::UintTy::Us) => tcx.types.usize,
+    fn to_ty<'a, 'gcx, 'tcx>(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
+        match self {
+            SignedInt(i) => tcx.mk_mach_int(i),
+            UnsignedInt(i) => tcx.mk_mach_uint(i),
         }
     }
 
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
index 8dd591fa2e7..8b246105f61 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
+++ b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
@@ -454,7 +454,6 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
                 self.propagate_bits_into_entry_set_for(in_out, changed, target);
                 self.propagate_bits_into_entry_set_for(in_out, changed, unwind);
             }
-            mir::TerminatorKind::Switch { ref targets, .. } |
             mir::TerminatorKind::SwitchInt { ref targets, .. } => {
                 for target in targets {
                     self.propagate_bits_into_entry_set_for(in_out, changed, target);
diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
index 45f534767e4..8f3dcd0b8d6 100644
--- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
+++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
@@ -17,9 +17,10 @@ use super::{DropFlagState, MoveDataParamEnv};
 use super::patch::MirPatch;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::{Kind, Subst, Substs};
+use rustc::ty::util::IntTypeExt;
 use rustc::mir::*;
 use rustc::mir::transform::{Pass, MirPass, MirSource};
-use rustc::middle::const_val::ConstVal;
+use rustc::middle::const_val::{ConstVal, ConstInt};
 use rustc::middle::lang_items;
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_set::IdxSetBuf;
@@ -672,12 +673,15 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                 self.drop_ladder(c, fields)
             }
             _ => {
-                let variant_drops : Vec<BasicBlock> =
-                    (0..adt.variants.len()).map(|i| {
-                        self.open_drop_for_variant(c, &mut drop_block,
-                                                   adt, substs, i)
-                    }).collect();
-
+                let mut values = Vec::with_capacity(adt.variants.len());
+                let mut blocks = Vec::with_capacity(adt.variants.len() + 1);
+                for (idx, variant) in adt.variants.iter().enumerate() {
+                    let discr = ConstInt::new_inttype(variant.disr_val, adt.discr_ty,
+                                                      self.tcx.sess.target.uint_type,
+                                                      self.tcx.sess.target.int_type).unwrap();
+                    values.push(ConstVal::Integral(discr));
+                    blocks.push(self.open_drop_for_variant(c, &mut drop_block, adt, substs, idx));
+                }
                 // If there are multiple variants, then if something
                 // is present within the enum the discriminant, tracked
                 // by the rest path, must be initialized.
@@ -685,14 +689,29 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                 // Additionally, we do not want to switch on the
                 // discriminant after it is free-ed, because that
                 // way lies only trouble.
-
-                let switch_block = self.new_block(
-                    c, c.is_cleanup, TerminatorKind::Switch {
-                        discr: c.lvalue.clone(),
-                        adt_def: adt,
-                        targets: variant_drops
-                    });
-
+                let discr_ty = adt.discr_ty.to_ty(self.tcx);
+                let discr = Lvalue::Local(self.patch.new_temp(discr_ty));
+                let switch_block = self.patch.new_block(BasicBlockData {
+                    statements: vec![
+                        Statement {
+                            source_info: c.source_info,
+                            kind: StatementKind::Assign(discr.clone(),
+                                                        Rvalue::Discriminant(c.lvalue.clone()))
+                        }
+                    ],
+                    terminator: Some(Terminator {
+                        source_info: c.source_info,
+                        kind: TerminatorKind::SwitchInt {
+                            discr: Operand::Consume(discr),
+                            switch_ty: discr_ty,
+                            values: values,
+                            targets: blocks,
+                            // adt_def: adt,
+                            // targets: variant_drops
+                        }
+                    }),
+                    is_cleanup: c.is_cleanup,
+                });
                 self.drop_flag_test_block(c, switch_block)
             }
         }
diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs
index 9e7e5ec9ee8..0c7e922c48a 100644
--- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs
@@ -465,8 +465,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
             }
 
             TerminatorKind::Assert { .. } |
-            TerminatorKind::SwitchInt { .. } |
-            TerminatorKind::Switch { .. } => {
+            TerminatorKind::SwitchInt { .. } => {
                 // branching terminators - these don't move anything
             }
 
diff --git a/src/librustc_const_math/int.rs b/src/librustc_const_math/int.rs
index 17714f2fb2d..bc3809db1c6 100644
--- a/src/librustc_const_math/int.rs
+++ b/src/librustc_const_math/int.rs
@@ -77,6 +77,14 @@ mod ibounds {
 }
 
 impl ConstInt {
+    pub fn new_inttype(val: u128, ty: IntType, usize_ty: UintTy, isize_ty: IntTy)
+    -> Option<ConstInt> {
+        match ty {
+            IntType::SignedInt(i) => ConstInt::new_signed(val as i128, i, isize_ty),
+            IntType::UnsignedInt(i) => ConstInt::new_unsigned(val, i, usize_ty),
+        }
+    }
+
     /// Creates a new unsigned ConstInt with matching type while also checking that overflow does
     /// not happen.
     pub fn new_unsigned(val: u128, ty: UintTy, usize_ty: UintTy) -> Option<ConstInt> {
diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs
index 3700d46c346..ffcd25a4cdd 100644
--- a/src/librustc_data_structures/bitvec.rs
+++ b/src/librustc_data_structures/bitvec.rs
@@ -30,6 +30,10 @@ impl BitVector {
         }
     }
 
+    pub fn count(&self) -> usize {
+        self.data.iter().map(|e| e.count_ones() as usize).sum()
+    }
+
     #[inline]
     pub fn contains(&self, bit: usize) -> bool {
         let (word, mask) = word_mask(bit);
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 291bd65d577..528e37e73c4 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -20,11 +20,12 @@ use build::matches::{Candidate, MatchPair, Test, TestKind};
 use hair::*;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::bitvec::BitVector;
-use rustc::middle::const_val::ConstVal;
+use rustc::middle::const_val::{ConstVal, ConstInt};
 use rustc::ty::{self, Ty};
 use rustc::mir::*;
 use rustc::hir::RangeEnd;
 use syntax_pos::Span;
+use syntax::attr;
 use std::cmp::Ordering;
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
@@ -182,24 +183,51 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let source_info = self.source_info(test.span);
         match test.kind {
             TestKind::Switch { adt_def, ref variants } => {
+                // Variants is a BitVec of indexes into adt_def.variants.
                 let num_enum_variants = self.hir.num_variants(adt_def);
+                let used_variants = variants.count();
                 let mut otherwise_block = None;
-                let target_blocks: Vec<_> = (0..num_enum_variants).map(|i| {
-                    if variants.contains(i) {
-                        self.cfg.start_new_block()
+                let mut target_blocks = Vec::with_capacity(num_enum_variants);
+                let mut targets = Vec::with_capacity(used_variants + 1);
+                let mut values = Vec::with_capacity(used_variants);
+                let tcx = self.hir.tcx();
+                for (idx, variant) in adt_def.variants.iter().enumerate() {
+                    target_blocks.place_back() <- if variants.contains(idx) {
+                        let discr = ConstInt::new_inttype(variant.disr_val, adt_def.discr_ty,
+                                                          tcx.sess.target.uint_type,
+                                                          tcx.sess.target.int_type).unwrap();
+                        values.push(ConstVal::Integral(discr));
+                        *(targets.place_back() <- self.cfg.start_new_block())
                     } else {
                         if otherwise_block.is_none() {
                             otherwise_block = Some(self.cfg.start_new_block());
                         }
                         otherwise_block.unwrap()
-                    }
-                }).collect();
-                debug!("num_enum_variants: {}, num tested variants: {}, variants: {:?}",
-                       num_enum_variants, variants.iter().count(), variants);
-                self.cfg.terminate(block, source_info, TerminatorKind::Switch {
-                    discr: lvalue.clone(),
-                    adt_def: adt_def,
-                    targets: target_blocks.clone()
+                    };
+                }
+                if let Some(otherwise_block) = otherwise_block {
+                    targets.push(otherwise_block);
+                } else {
+                    values.pop();
+                }
+                debug!("num_enum_variants: {}, tested variants: {:?}, variants: {:?}",
+                       num_enum_variants, values, variants);
+                // FIXME: WHY THIS DOES NOT WORK?!
+                // let discr_ty = adt_def.discr_ty.to_ty(tcx);
+                let discr_ty = match adt_def.discr_ty {
+                    attr::SignedInt(i) => tcx.mk_mach_int(i),
+                    attr::UnsignedInt(i) => tcx.mk_mach_uint(i),
+                };
+
+                let discr = self.temp(discr_ty);
+                self.cfg.push_assign(block, source_info, &discr,
+                                     Rvalue::Discriminant(lvalue.clone()));
+                assert_eq!(values.len() + 1, targets.len());
+                self.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
+                    discr: Operand::Consume(discr),
+                    switch_ty: discr_ty,
+                    values: values,
+                    targets: targets
                 });
                 target_blocks
             }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 61ba9d90fef..9a8fb1099d0 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -26,6 +26,8 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
+#![feature(placement_in_syntax)]
+#![feature(collection_placement)]
 
 #[macro_use] extern crate log;
 extern crate graphviz as dot;
diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs
index 425df65659c..55a26f4b37f 100644
--- a/src/librustc_mir/transform/no_landing_pads.rs
+++ b/src/librustc_mir/transform/no_landing_pads.rs
@@ -28,7 +28,6 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
             TerminatorKind::Resume |
             TerminatorKind::Return |
             TerminatorKind::Unreachable |
-            TerminatorKind::Switch { .. } |
             TerminatorKind::SwitchInt { .. } => {
                 /* nothing to do */
             },
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index bda4c94625f..922521726c6 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -394,7 +394,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
                     return Qualif::empty();
                 }
 
-                TerminatorKind::Switch {..} |
                 TerminatorKind::SwitchInt {..} |
                 TerminatorKind::DropAndReplace { .. } |
                 TerminatorKind::Resume |
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index 1127f50fe50..e93a412dc74 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -209,7 +209,6 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
     // turn a branch with all successors identical to a goto
     fn simplify_branch(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
         match terminator.kind {
-            TerminatorKind::Switch { .. } |
             TerminatorKind::SwitchInt { .. } => {},
             _ => return false
         };
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index 9d2ad314386..8ede7aaab5f 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -436,19 +436,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 }
                 // FIXME: check the values
             }
-            TerminatorKind::Switch { ref discr, adt_def, ref targets } => {
-                let discr_ty = discr.ty(mir, tcx).to_ty(tcx);
-                match discr_ty.sty {
-                    ty::TyAdt(def, _) if def.is_enum() &&
-                                         def == adt_def &&
-                                         adt_def.variants.len() == targets.len()
-                      => {},
-                    _ => {
-                        span_mirbug!(self, term, "bad Switch ({:?} on {:?})",
-                                     adt_def, discr_ty);
-                    }
-                }
-            }
             TerminatorKind::Call { ref func, ref args, ref destination, .. } => {
                 let func_ty = func.ty(mir, tcx);
                 debug!("check_terminator: call, func_ty={:?}", func_ty);
@@ -593,7 +580,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         match block.terminator().kind {
             TerminatorKind::Goto { target } =>
                 self.assert_iscleanup(mir, block, target, is_cleanup),
-            TerminatorKind::Switch { ref targets, .. } |
             TerminatorKind::SwitchInt { ref targets, .. } => {
                 for target in targets {
                     self.assert_iscleanup(mir, block, *target, is_cleanup);
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
index fef61128d04..517a4720563 100644
--- a/src/librustc_passes/mir_stats.rs
+++ b/src/librustc_passes/mir_stats.rs
@@ -148,7 +148,6 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
         self.record("TerminatorKind", kind);
         self.record(match *kind {
             TerminatorKind::Goto { .. } => "TerminatorKind::Goto",
-            TerminatorKind::Switch { .. } => "TerminatorKind::Switch",
             TerminatorKind::SwitchInt { .. } => "TerminatorKind::SwitchInt",
             TerminatorKind::Resume => "TerminatorKind::Resume",
             TerminatorKind::Return => "TerminatorKind::Return",
diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs
index 97118a72062..37725bfa2de 100644
--- a/src/librustc_trans/mir/analyze.rs
+++ b/src/librustc_trans/mir/analyze.rs
@@ -204,7 +204,6 @@ pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Mir<'tcx>) -> IndexVec<mir::BasicBlock
                 TerminatorKind::Resume |
                 TerminatorKind::Return |
                 TerminatorKind::Unreachable |
-                TerminatorKind::Switch { .. } |
                 TerminatorKind::SwitchInt { .. } => {
                     /* nothing to do */
                 }
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index b22c16a2955..2ed2cc61062 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -14,14 +14,12 @@ use rustc::middle::lang_items;
 use rustc::ty::{self, layout, TypeFoldable};
 use rustc::mir;
 use abi::{Abi, FnType, ArgType};
-use adt;
 use base::{self, Lifetime};
 use callee::{Callee, CalleeData, Fn, Intrinsic, NamedTupleConstructor, Virtual};
 use builder::Builder;
 use common::{self, Funclet};
 use common::{C_bool, C_str_slice, C_struct, C_u32, C_undef};
 use consts;
-use Disr;
 use machine::{llalign_of_min, llbitsize_of_real};
 use meth;
 use type_of::{self, align_of};
@@ -29,7 +27,6 @@ use glue;
 use type_::Type;
 
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_data_structures::fx::FxHashMap;
 use syntax::symbol::Symbol;
 
 use std::cmp;
@@ -136,41 +133,6 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 funclet_br(self, bcx, target);
             }
 
-            mir::TerminatorKind::Switch { ref discr, ref adt_def, ref targets } => {
-                let discr_lvalue = self.trans_lvalue(&bcx, discr);
-                let ty = discr_lvalue.ty.to_ty(bcx.tcx());
-                let discr = adt::trans_get_discr(
-                    &bcx, ty, discr_lvalue.llval, discr_lvalue.alignment,
-                    None, true);
-
-                let mut bb_hist = FxHashMap();
-                for target in targets {
-                    *bb_hist.entry(target).or_insert(0) += 1;
-                }
-                let (default_bb, default_blk) = match bb_hist.iter().max_by_key(|&(_, c)| c) {
-                    // If a single target basic blocks is predominant, promote that to be the
-                    // default case for the switch instruction to reduce the size of the generated
-                    // code. This is especially helpful in cases like an if-let on a huge enum.
-                    // Note: This optimization is only valid for exhaustive matches.
-                    Some((&&bb, &c)) if c > targets.len() / 2 => {
-                        (Some(bb), llblock(self, bb))
-                    }
-                    // We're generating an exhaustive switch, so the else branch
-                    // can't be hit.  Branching to an unreachable instruction
-                    // lets LLVM know this
-                    _ => (None, self.unreachable_block())
-                };
-                let switch = bcx.switch(discr, default_blk, targets.len());
-                assert_eq!(adt_def.variants.len(), targets.len());
-                for (adt_variant, &target) in adt_def.variants.iter().zip(targets) {
-                    if default_bb != Some(target) {
-                        let llbb = llblock(self, target);
-                        let llval = adt::trans_case(&bcx, ty, Disr::from(adt_variant.disr_val));
-                        bcx.add_case(switch, llval, llbb)
-                    }
-                }
-            }
-
             mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
                 // TODO: cond_br if only 1 value
                 let (otherwise, targets) = targets.split_last().unwrap();