about summary refs log tree commit diff
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2023-05-14 22:29:26 -0700
committerScott McMurray <scottmcm@users.noreply.github.com>2023-05-18 10:28:36 -0700
commit400866b7ab74cb9a4e705e0c4536a8b8130eb59e (patch)
treed6135528b235d767d0b317fc8ce57c46941f29b0
parentc2ccc855e74aec03e434405eca3c247ee2432e53 (diff)
downloadrust-400866b7ab74cb9a4e705e0c4536a8b8130eb59e.tar.gz
rust-400866b7ab74cb9a4e705e0c4536a8b8130eb59e.zip
Also assume wrap-around discriminants in `as` MIR building
Resolves this FIXME:

https://github.com/rust-lang/rust/blob/8d18c32b61476ed16dd15074e71be3970368d6d7/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs#L231
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs101
-rw-r--r--tests/assembly/option-nonzero-eq.rs28
-rw-r--r--tests/codegen/option-nonzero-eq.rs12
-rw-r--r--tests/mir-opt/building/enum_cast.bar.built.after.mir9
-rw-r--r--tests/mir-opt/building/enum_cast.boo.built.after.mir9
-rw-r--r--tests/mir-opt/building/enum_cast.droppy.built.after.mir9
-rw-r--r--tests/mir-opt/building/enum_cast.far.built.after.mir22
-rw-r--r--tests/mir-opt/building/enum_cast.offsetty.built.after.mir26
-rw-r--r--tests/mir-opt/building/enum_cast.rs42
-rw-r--r--tests/mir-opt/building/enum_cast.signy.built.after.mir26
-rw-r--r--tests/mir-opt/building/enum_cast.unsigny.built.after.mir17
11 files changed, 234 insertions, 67 deletions
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 0105a265ffb..0fa7dc5a5e3 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -15,6 +15,7 @@ use rustc_middle::mir::Place;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
+use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{self, Ty, UpvarSubsts};
 use rustc_span::Span;
 
@@ -225,49 +226,63 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     );
                     let (op,ty) = (Operand::Move(discr), discr_ty);
 
-                    if let Abi::Scalar(scalar) = layout.unwrap().abi{
-                        if let Primitive::Int(_, signed) = scalar.primitive() {
-                            let range = scalar.valid_range(&this.tcx);
-                            // FIXME: Handle wraparound cases too.
-                            if range.end >= range.start {
-                                let mut assumer = |range: u128, bin_op: BinOp| {
-                                    // We will be overwriting this val if our scalar is signed value
-                                    // because sign extension on unsigned types might cause unintended things
-                                    let mut range_val =
-                                        ConstantKind::from_bits(this.tcx, range, ty::ParamEnv::empty().and(discr_ty));
-                                    let bool_ty = this.tcx.types.bool;
-                                    if signed {
-                                        let scalar_size_extend = scalar.size(&this.tcx).sign_extend(range);
-                                        let discr_layout = this.tcx.layout_of(this.param_env.and(discr_ty));
-                                        let truncated_val = discr_layout.unwrap().size.truncate(scalar_size_extend);
-                                        range_val = ConstantKind::from_bits(
-                                            this.tcx,
-                                            truncated_val,
-                                            ty::ParamEnv::empty().and(discr_ty),
-                                        );
-                                    }
-                                    let lit_op = this.literal_operand(expr.span, range_val);
-                                    let is_bin_op = this.temp(bool_ty, expr_span);
-                                    this.cfg.push_assign(
-                                        block,
-                                        source_info,
-                                        is_bin_op,
-                                        Rvalue::BinaryOp(bin_op, Box::new(((lit_op), (Operand::Copy(discr))))),
-                                    );
-                                    this.cfg.push(
-                                        block,
-                                        Statement {
-                                            source_info,
-                                            kind: StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(
-                                                Operand::Copy(is_bin_op),
-                                            ))),
-                                        },
-                                    )
-                                };
-                                assumer(range.end, BinOp::Ge);
-                                assumer(range.start, BinOp::Le);
-                            }
-                        }
+                    if let Abi::Scalar(scalar) = layout.unwrap().abi
+                        && !scalar.is_always_valid(&this.tcx)
+                        && let Primitive::Int(int_width, _signed) = scalar.primitive()
+                    {
+                        let unsigned_ty = int_width.to_ty(this.tcx, false);
+                        let unsigned_place = this.temp(unsigned_ty, expr_span);
+                        this.cfg.push_assign(
+                            block,
+                            source_info,
+                            unsigned_place,
+                            Rvalue::Cast(CastKind::IntToInt, Operand::Copy(discr), unsigned_ty));
+
+                        let bool_ty = this.tcx.types.bool;
+                        let range = scalar.valid_range(&this.tcx);
+                        let merge_op =
+                            if range.start <= range.end {
+                                BinOp::BitAnd
+                            } else {
+                                BinOp::BitOr
+                            };
+
+                        let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> {
+                            let range_val =
+                                ConstantKind::from_bits(this.tcx, range, ty::ParamEnv::empty().and(unsigned_ty));
+                            let lit_op = this.literal_operand(expr.span, range_val);
+                            let is_bin_op = this.temp(bool_ty, expr_span);
+                            this.cfg.push_assign(
+                                block,
+                                source_info,
+                                is_bin_op,
+                                Rvalue::BinaryOp(bin_op, Box::new((Operand::Copy(unsigned_place), lit_op))),
+                            );
+                            is_bin_op
+                        };
+                        let assert_place = if range.start == 0 {
+                            comparer(range.end, BinOp::Le)
+                        } else {
+                            let start_place = comparer(range.start, BinOp::Ge);
+                            let end_place = comparer(range.end, BinOp::Le);
+                            let merge_place = this.temp(bool_ty, expr_span);
+                            this.cfg.push_assign(
+                                block,
+                                source_info,
+                                merge_place,
+                                Rvalue::BinaryOp(merge_op, Box::new((Operand::Move(start_place), Operand::Move(end_place)))),
+                            );
+                            merge_place
+                        };
+                        this.cfg.push(
+                            block,
+                            Statement {
+                                source_info,
+                                kind: StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(
+                                    Operand::Move(assert_place),
+                                ))),
+                            },
+                        );
                     }
 
                     (op,ty)
diff --git a/tests/assembly/option-nonzero-eq.rs b/tests/assembly/option-nonzero-eq.rs
new file mode 100644
index 00000000000..f5d88de76dd
--- /dev/null
+++ b/tests/assembly/option-nonzero-eq.rs
@@ -0,0 +1,28 @@
+// revisions: WIN LIN
+// [WIN] only-windows
+// [LIN] only-linux
+// assembly-output: emit-asm
+// compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel
+// only-x86_64
+// ignore-sgx
+// ignore-debug
+
+use std::cmp::Ordering;
+
+// CHECK-lABEL: ordering_eq:
+#[no_mangle]
+pub fn ordering_eq(l: Option<Ordering>, r: Option<Ordering>) -> bool {
+    // Linux (System V): first two arguments are rdi then rsi
+    // Windows: first two arguments are rcx then rdx
+    // Both use rax for the return value.
+
+    // CHECK-NOT: mov
+    // CHECK-NOT: test
+    // CHECK-NOT: cmp
+
+    // LIN: cmp dil, sil
+    // WIN: cmp cl, dl
+    // CHECK-NEXT: sete al
+    // CHECK-NEXT: ret
+    l == r
+}
diff --git a/tests/codegen/option-nonzero-eq.rs b/tests/codegen/option-nonzero-eq.rs
index 835decd3e5f..a394695f3bd 100644
--- a/tests/codegen/option-nonzero-eq.rs
+++ b/tests/codegen/option-nonzero-eq.rs
@@ -7,6 +7,9 @@ use core::cmp::Ordering;
 use core::num::{NonZeroU32, NonZeroI64};
 use core::ptr::NonNull;
 
+// See also tests/assembly/option-nonzero-eq.rs, for cases with `assume`s in the
+// LLVM and thus don't optimize down clearly here, but do in assembly.
+
 // CHECK-lABEL: @non_zero_eq
 #[no_mangle]
 pub fn non_zero_eq(l: Option<NonZeroU32>, r: Option<NonZeroU32>) -> bool {
@@ -33,12 +36,3 @@ pub fn non_null_eq(l: Option<NonNull<u8>>, r: Option<NonNull<u8>>) -> bool {
     // CHECK-NEXT: ret i1
     l == r
 }
-
-// CHECK-lABEL: @ordering_eq
-#[no_mangle]
-pub fn ordering_eq(l: Option<Ordering>, r: Option<Ordering>) -> bool {
-    // CHECK: start:
-    // CHECK-NEXT: icmp eq i8
-    // CHECK-NEXT: ret i1
-    l == r
-}
diff --git a/tests/mir-opt/building/enum_cast.bar.built.after.mir b/tests/mir-opt/building/enum_cast.bar.built.after.mir
index 0746e0b498e..9f14c028465 100644
--- a/tests/mir-opt/building/enum_cast.bar.built.after.mir
+++ b/tests/mir-opt/building/enum_cast.bar.built.after.mir
@@ -5,17 +5,16 @@ fn bar(_1: Bar) -> usize {
     let mut _0: usize;                   // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
     let _2: Bar;                         // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
     let mut _3: isize;                   // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
-    let mut _4: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+    let mut _4: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
     let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
 
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
         _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
         _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        _4 = Ge(const 1_isize, _3);      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        assume(_4);                      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        _5 = Le(const 0_isize, _3);      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        assume(_5);                      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _4 = _3 as u8 (IntToInt);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _5 = Le(_4, const 1_u8);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        assume(move _5);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
         _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
         StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
         return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
diff --git a/tests/mir-opt/building/enum_cast.boo.built.after.mir b/tests/mir-opt/building/enum_cast.boo.built.after.mir
index 699c876b01a..715dedcf24d 100644
--- a/tests/mir-opt/building/enum_cast.boo.built.after.mir
+++ b/tests/mir-opt/building/enum_cast.boo.built.after.mir
@@ -5,17 +5,16 @@ fn boo(_1: Boo) -> usize {
     let mut _0: usize;                   // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
     let _2: Boo;                         // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
     let mut _3: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
-    let mut _4: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+    let mut _4: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
     let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
 
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
         _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
         _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        _4 = Ge(const 1_u8, _3);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        assume(_4);                      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        _5 = Le(const 0_u8, _3);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        assume(_5);                      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _4 = _3 as u8 (IntToInt);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _5 = Le(_4, const 1_u8);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        assume(move _5);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
         _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
         StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
         return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
diff --git a/tests/mir-opt/building/enum_cast.droppy.built.after.mir b/tests/mir-opt/building/enum_cast.droppy.built.after.mir
index 1112177fbbf..6c177c61eca 100644
--- a/tests/mir-opt/building/enum_cast.droppy.built.after.mir
+++ b/tests/mir-opt/building/enum_cast.droppy.built.after.mir
@@ -6,7 +6,7 @@ fn droppy() -> () {
     let _2: Droppy;                      // in scope 0 at $DIR/enum_cast.rs:+2:13: +2:14
     let _4: Droppy;                      // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18
     let mut _5: isize;                   // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18
-    let mut _6: bool;                    // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
+    let mut _6: u8;                      // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
     let mut _7: bool;                    // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
     let _8: Droppy;                      // in scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
     scope 1 {
@@ -31,10 +31,9 @@ fn droppy() -> () {
         StorageLive(_4);                 // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
         _4 = move _2;                    // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
         _5 = discriminant(_4);           // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
-        _6 = Ge(const 2_isize, _5);      // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
-        assume(_6);                      // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
-        _7 = Le(const 0_isize, _5);      // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
-        assume(_7);                      // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
+        _6 = _5 as u8 (IntToInt);        // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
+        _7 = Le(_6, const 2_u8);         // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
+        assume(move _7);                 // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
         _3 = move _5 as usize (IntToInt); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
         drop(_4) -> [return: bb1, unwind: bb4]; // scope 3 at $DIR/enum_cast.rs:+5:26: +5:27
     }
diff --git a/tests/mir-opt/building/enum_cast.far.built.after.mir b/tests/mir-opt/building/enum_cast.far.built.after.mir
new file mode 100644
index 00000000000..ab8129ca01c
--- /dev/null
+++ b/tests/mir-opt/building/enum_cast.far.built.after.mir
@@ -0,0 +1,22 @@
+// MIR for `far` after built
+
+fn far(_1: Far) -> isize {
+    debug far => _1;                     // in scope 0 at $DIR/enum_cast.rs:+0:8: +0:11
+    let mut _0: isize;                   // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
+    let _2: Far;                         // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
+    let mut _3: i16;                     // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
+    let mut _4: u16;                     // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+    let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
+        _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
+        _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _4 = _3 as u16 (IntToInt);       // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _5 = Le(_4, const 1_u16);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        assume(move _5);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _0 = move _3 as isize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
+        return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
+    }
+}
diff --git a/tests/mir-opt/building/enum_cast.offsetty.built.after.mir b/tests/mir-opt/building/enum_cast.offsetty.built.after.mir
new file mode 100644
index 00000000000..7b2b583f20f
--- /dev/null
+++ b/tests/mir-opt/building/enum_cast.offsetty.built.after.mir
@@ -0,0 +1,26 @@
+// MIR for `offsetty` after built
+
+fn offsetty(_1: NotStartingAtZero) -> u32 {
+    debug x => _1;                       // in scope 0 at $DIR/enum_cast.rs:+0:13: +0:14
+    let mut _0: u32;                     // return place in scope 0 at $DIR/enum_cast.rs:+0:38: +0:41
+    let _2: NotStartingAtZero;           // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+    let mut _3: isize;                   // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+    let mut _4: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _6: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _7: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+        _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+        _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _4 = _3 as u8 (IntToInt);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _5 = Ge(_4, const 4_u8);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _6 = Le(_4, const 8_u8);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _7 = BitAnd(move _5, move _6);   // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        assume(move _7);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _0 = move _3 as u32 (IntToInt);  // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:12: +1:13
+        return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
+    }
+}
diff --git a/tests/mir-opt/building/enum_cast.rs b/tests/mir-opt/building/enum_cast.rs
index 98fd5acfb14..431b5c708b9 100644
--- a/tests/mir-opt/building/enum_cast.rs
+++ b/tests/mir-opt/building/enum_cast.rs
@@ -1,6 +1,7 @@
 // EMIT_MIR enum_cast.foo.built.after.mir
 // EMIT_MIR enum_cast.bar.built.after.mir
 // EMIT_MIR enum_cast.boo.built.after.mir
+// EMIT_MIR enum_cast.far.built.after.mir
 
 enum Foo {
     A
@@ -15,6 +16,11 @@ enum Boo {
     A, B
 }
 
+#[repr(i16)]
+enum Far {
+    A, B
+}
+
 fn foo(foo: Foo) -> usize {
     foo as usize
 }
@@ -27,6 +33,10 @@ fn boo(boo: Boo) -> usize {
     boo as usize
 }
 
+fn far(far: Far) -> isize {
+    far as isize
+}
+
 // EMIT_MIR enum_cast.droppy.built.after.mir
 enum Droppy {
     A, B, C
@@ -46,5 +56,37 @@ fn droppy() {
     let z = Droppy::B;
 }
 
+#[repr(i16)]
+enum SignedAroundZero {
+    A = -2,
+    B = 0,
+    C = 2,
+}
+
+#[repr(u16)]
+enum UnsignedAroundZero {
+    A = 65535,
+    B = 0,
+    C = 1,
+}
+
+// EMIT_MIR enum_cast.signy.built.after.mir
+fn signy(x: SignedAroundZero) -> i16 {
+    x as i16
+}
+
+// EMIT_MIR enum_cast.unsigny.built.after.mir
+fn unsigny(x: UnsignedAroundZero) -> u16 {
+    // FIXME: This doesn't get an around-the-end range today, sadly.
+    x as u16
+}
+
+enum NotStartingAtZero { A = 4, B = 6, C = 8 }
+
+// EMIT_MIR enum_cast.offsetty.built.after.mir
+fn offsetty(x: NotStartingAtZero) -> u32 {
+    x as u32
+}
+
 fn main() {
 }
diff --git a/tests/mir-opt/building/enum_cast.signy.built.after.mir b/tests/mir-opt/building/enum_cast.signy.built.after.mir
new file mode 100644
index 00000000000..ef4fea604ec
--- /dev/null
+++ b/tests/mir-opt/building/enum_cast.signy.built.after.mir
@@ -0,0 +1,26 @@
+// MIR for `signy` after built
+
+fn signy(_1: SignedAroundZero) -> i16 {
+    debug x => _1;                       // in scope 0 at $DIR/enum_cast.rs:+0:10: +0:11
+    let mut _0: i16;                     // return place in scope 0 at $DIR/enum_cast.rs:+0:34: +0:37
+    let _2: SignedAroundZero;            // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+    let mut _3: i16;                     // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+    let mut _4: u16;                     // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _6: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _7: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+        _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+        _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _4 = _3 as u16 (IntToInt);       // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _5 = Ge(_4, const 65534_u16);    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _6 = Le(_4, const 2_u16);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _7 = BitOr(move _5, move _6);    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        assume(move _7);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _0 = move _3 as i16 (IntToInt);  // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:12: +1:13
+        return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
+    }
+}
diff --git a/tests/mir-opt/building/enum_cast.unsigny.built.after.mir b/tests/mir-opt/building/enum_cast.unsigny.built.after.mir
new file mode 100644
index 00000000000..7ca147b1596
--- /dev/null
+++ b/tests/mir-opt/building/enum_cast.unsigny.built.after.mir
@@ -0,0 +1,17 @@
+// MIR for `unsigny` after built
+
+fn unsigny(_1: UnsignedAroundZero) -> u16 {
+    debug x => _1;                       // in scope 0 at $DIR/enum_cast.rs:+0:12: +0:13
+    let mut _0: u16;                     // return place in scope 0 at $DIR/enum_cast.rs:+0:38: +0:41
+    let _2: UnsignedAroundZero;          // in scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
+    let mut _3: u16;                     // in scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
+        _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
+        _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+2:5: +2:13
+        _0 = move _3 as u16 (IntToInt);  // scope 0 at $DIR/enum_cast.rs:+2:5: +2:13
+        StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+2:12: +2:13
+        return;                          // scope 0 at $DIR/enum_cast.rs:+3:2: +3:2
+    }
+}