about summary refs log tree commit diff
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2023-03-22 01:06:19 -0700
committerScott McMurray <scottmcm@users.noreply.github.com>2023-03-22 13:32:12 -0700
commitb537e6bc53bfee64d1e8f8f8d28b2418bddc5a91 (patch)
tree366bb36dcff9ea564a11ad3e9dc97f1af00425f7
parentec25f087488a1913982fc6b28b66574ee4791d14 (diff)
downloadrust-b537e6bc53bfee64d1e8f8f8d28b2418bddc5a91.tar.gz
rust-b537e6bc53bfee64d1e8f8f8d28b2418bddc5a91.zip
Generate simpler MIR for shifts
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs56
-rw-r--r--compiler/rustc_type_ir/src/lib.rs22
-rw-r--r--tests/mir-opt/building/shifts.shift_signed.built.after.mir48
-rw-r--r--tests/mir-opt/building/shifts.shift_unsigned.built.after.mir176
-rw-r--r--tests/mir-opt/issue_101973.inner.ConstProp.diff28
5 files changed, 175 insertions, 155 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 140d1154718..3b775f590a4 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -566,41 +566,51 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 Rvalue::Use(Operand::Move(val))
             }
             BinOp::Shl | BinOp::Shr if self.check_overflow && ty.is_integral() => {
-                // Consider that the shift overflows if `rhs < 0` or `rhs >= bits`.
-                // This can be encoded as a single operation as `(rhs & -bits) != 0`.
-                let (size, _) = ty.int_size_and_signed(self.tcx);
-                let bits = size.bits();
-                debug_assert!(bits.is_power_of_two());
-                let mask = !((bits - 1) as u128);
-
+                // For an unsigned RHS, the shift is in-range for `rhs < bits`.
+                // For a signed RHS, `IntToInt` cast to the equivalent unsigned
+                // type and do that same comparison.  Because the type is the
+                // same size, there's no negative shift amount that ends up
+                // overlapping with valid ones, thus it catches negatives too.
+                let (lhs_size, _) = ty.int_size_and_signed(self.tcx);
                 let rhs_ty = rhs.ty(&self.local_decls, self.tcx);
                 let (rhs_size, _) = rhs_ty.int_size_and_signed(self.tcx);
-                let mask = Operand::const_from_scalar(
+
+                let (unsigned_rhs, unsigned_ty) = match rhs_ty.kind() {
+                    ty::Uint(_) => (rhs.to_copy(), rhs_ty),
+                    ty::Int(int_width) => {
+                        let uint_ty = self.tcx.mk_mach_uint(int_width.to_unsigned());
+                        let rhs_temp = self.temp(uint_ty, span);
+                        self.cfg.push_assign(
+                            block,
+                            source_info,
+                            rhs_temp,
+                            Rvalue::Cast(CastKind::IntToInt, rhs.to_copy(), uint_ty),
+                        );
+                        (Operand::Move(rhs_temp), uint_ty)
+                    }
+                    _ => unreachable!("only integers are shiftable"),
+                };
+
+                // This can't overflow because the largest shiftable types are 128-bit,
+                // which fits in `u8`, the smallest possible `unsigned_ty`.
+                // (And `from_uint` will `bug!` if that's ever no longer true.)
+                let lhs_bits = Operand::const_from_scalar(
                     self.tcx,
-                    rhs_ty,
-                    Scalar::from_uint(rhs_size.truncate(mask), rhs_size),
+                    unsigned_ty,
+                    Scalar::from_uint(lhs_size.bits(), rhs_size),
                     span,
                 );
 
-                let outer_bits = self.temp(rhs_ty, span);
-                self.cfg.push_assign(
-                    block,
-                    source_info,
-                    outer_bits,
-                    Rvalue::BinaryOp(BinOp::BitAnd, Box::new((rhs.to_copy(), mask))),
-                );
-
-                let overflows = self.temp(bool_ty, span);
-                let zero = self.zero_literal(span, rhs_ty);
+                let inbounds = self.temp(bool_ty, span);
                 self.cfg.push_assign(
                     block,
                     source_info,
-                    overflows,
-                    Rvalue::BinaryOp(BinOp::Ne, Box::new((Operand::Move(outer_bits), zero))),
+                    inbounds,
+                    Rvalue::BinaryOp(BinOp::Lt, Box::new((unsigned_rhs, lhs_bits))),
                 );
 
                 let overflow_err = AssertKind::Overflow(op, lhs.to_copy(), rhs.to_copy());
-                block = self.assert(block, Operand::Move(overflows), false, overflow_err, span);
+                block = self.assert(block, Operand::Move(inbounds), true, overflow_err, span);
                 Rvalue::BinaryOp(op, Box::new((lhs, rhs)))
             }
             BinOp::Div | BinOp::Rem if ty.is_integral() => {
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 5a991e03dee..8b23fbc7583 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -432,6 +432,17 @@ impl IntTy {
             _ => *self,
         }
     }
+
+    pub fn to_unsigned(self) -> UintTy {
+        match self {
+            IntTy::Isize => UintTy::Usize,
+            IntTy::I8 => UintTy::U8,
+            IntTy::I16 => UintTy::U16,
+            IntTy::I32 => UintTy::U32,
+            IntTy::I64 => UintTy::U64,
+            IntTy::I128 => UintTy::U128,
+        }
+    }
 }
 
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)]
@@ -479,6 +490,17 @@ impl UintTy {
             _ => *self,
         }
     }
+
+    pub fn to_signed(self) -> IntTy {
+        match self {
+            UintTy::Usize => IntTy::Isize,
+            UintTy::U8 => IntTy::I8,
+            UintTy::U16 => IntTy::I16,
+            UintTy::U32 => IntTy::I32,
+            UintTy::U64 => IntTy::I64,
+            UintTy::U128 => IntTy::I128,
+        }
+    }
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
diff --git a/tests/mir-opt/building/shifts.shift_signed.built.after.mir b/tests/mir-opt/building/shifts.shift_signed.built.after.mir
index 10fcff02837..028777cefdd 100644
--- a/tests/mir-opt/building/shifts.shift_signed.built.after.mir
+++ b/tests/mir-opt/building/shifts.shift_signed.built.after.mir
@@ -11,33 +11,33 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128;
     let mut _7: i8;                      // in scope 0 at $DIR/shifts.rs:+2:10: +2:20
     let mut _8: i8;                      // in scope 0 at $DIR/shifts.rs:+2:10: +2:15
     let mut _9: i8;                      // in scope 0 at $DIR/shifts.rs:+2:19: +2:20
-    let mut _10: i8;                     // in scope 0 at $DIR/shifts.rs:+2:10: +2:20
+    let mut _10: u8;                     // in scope 0 at $DIR/shifts.rs:+2:10: +2:20
     let mut _11: bool;                   // in scope 0 at $DIR/shifts.rs:+2:10: +2:20
     let mut _12: i8;                     // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
     let mut _13: i8;                     // in scope 0 at $DIR/shifts.rs:+2:22: +2:27
     let mut _14: i32;                    // in scope 0 at $DIR/shifts.rs:+2:31: +2:32
-    let mut _15: i32;                    // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
+    let mut _15: u32;                    // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
     let mut _16: bool;                   // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
     let mut _17: i8;                     // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
     let mut _18: i8;                     // in scope 0 at $DIR/shifts.rs:+2:34: +2:39
     let mut _19: i128;                   // in scope 0 at $DIR/shifts.rs:+2:43: +2:44
-    let mut _20: i128;                   // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
+    let mut _20: u128;                   // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
     let mut _21: bool;                   // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
     let mut _22: [u128; 3];              // in scope 0 at $DIR/shifts.rs:+3:9: +3:39
     let mut _23: u128;                   // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
     let mut _24: u128;                   // in scope 0 at $DIR/shifts.rs:+3:10: +3:13
     let mut _25: i8;                     // in scope 0 at $DIR/shifts.rs:+3:17: +3:18
-    let mut _26: i8;                     // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
+    let mut _26: u8;                     // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
     let mut _27: bool;                   // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
     let mut _28: u128;                   // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
     let mut _29: u128;                   // in scope 0 at $DIR/shifts.rs:+3:20: +3:23
     let mut _30: i32;                    // in scope 0 at $DIR/shifts.rs:+3:27: +3:28
-    let mut _31: i32;                    // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
+    let mut _31: u32;                    // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
     let mut _32: bool;                   // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
     let mut _33: u128;                   // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
     let mut _34: u128;                   // in scope 0 at $DIR/shifts.rs:+3:30: +3:33
     let mut _35: i128;                   // in scope 0 at $DIR/shifts.rs:+3:37: +3:38
-    let mut _36: i128;                   // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
+    let mut _36: u128;                   // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
     let mut _37: bool;                   // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
 
     bb0: {
@@ -47,9 +47,9 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128;
         _8 = _1;                         // scope 0 at $DIR/shifts.rs:+2:10: +2:15
         StorageLive(_9);                 // scope 0 at $DIR/shifts.rs:+2:19: +2:20
         _9 = _3;                         // scope 0 at $DIR/shifts.rs:+2:19: +2:20
-        _10 = BitAnd(_9, const -8_i8);   // scope 0 at $DIR/shifts.rs:+2:10: +2:20
-        _11 = Ne(move _10, const 0_i8);  // scope 0 at $DIR/shifts.rs:+2:10: +2:20
-        assert(!move _11, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20
+        _10 = _9 as u8 (IntToInt);       // scope 0 at $DIR/shifts.rs:+2:10: +2:20
+        _11 = Lt(move _10, const 8_u8);  // scope 0 at $DIR/shifts.rs:+2:10: +2:20
+        assert(move _11, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20
     }
 
     bb1: {
@@ -61,9 +61,9 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128;
         _13 = _1;                        // scope 0 at $DIR/shifts.rs:+2:22: +2:27
         StorageLive(_14);                // scope 0 at $DIR/shifts.rs:+2:31: +2:32
         _14 = _4;                        // scope 0 at $DIR/shifts.rs:+2:31: +2:32
-        _15 = BitAnd(_14, const -8_i32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32
-        _16 = Ne(move _15, const 0_i32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32
-        assert(!move _16, "attempt to shift right by `{}`, which would overflow", _14) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32
+        _15 = _14 as u32 (IntToInt);     // scope 0 at $DIR/shifts.rs:+2:22: +2:32
+        _16 = Lt(move _15, const 8_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32
+        assert(move _16, "attempt to shift right by `{}`, which would overflow", _14) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32
     }
 
     bb2: {
@@ -75,9 +75,9 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128;
         _18 = _1;                        // scope 0 at $DIR/shifts.rs:+2:34: +2:39
         StorageLive(_19);                // scope 0 at $DIR/shifts.rs:+2:43: +2:44
         _19 = _5;                        // scope 0 at $DIR/shifts.rs:+2:43: +2:44
-        _20 = BitAnd(_19, const -8_i128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44
-        _21 = Ne(move _20, const 0_i128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44
-        assert(!move _21, "attempt to shift right by `{}`, which would overflow", _19) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44
+        _20 = _19 as u128 (IntToInt);    // scope 0 at $DIR/shifts.rs:+2:34: +2:44
+        _21 = Lt(move _20, const 8_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44
+        assert(move _21, "attempt to shift right by `{}`, which would overflow", _19) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44
     }
 
     bb3: {
@@ -94,9 +94,9 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128;
         _24 = _2;                        // scope 0 at $DIR/shifts.rs:+3:10: +3:13
         StorageLive(_25);                // scope 0 at $DIR/shifts.rs:+3:17: +3:18
         _25 = _3;                        // scope 0 at $DIR/shifts.rs:+3:17: +3:18
-        _26 = BitAnd(_25, const i8::MIN); // scope 0 at $DIR/shifts.rs:+3:10: +3:18
-        _27 = Ne(move _26, const 0_i8);  // scope 0 at $DIR/shifts.rs:+3:10: +3:18
-        assert(!move _27, "attempt to shift left by `{}`, which would overflow", _25) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18
+        _26 = _25 as u8 (IntToInt);      // scope 0 at $DIR/shifts.rs:+3:10: +3:18
+        _27 = Lt(move _26, const 128_u8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18
+        assert(move _27, "attempt to shift left by `{}`, which would overflow", _25) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18
     }
 
     bb4: {
@@ -108,9 +108,9 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128;
         _29 = _2;                        // scope 0 at $DIR/shifts.rs:+3:20: +3:23
         StorageLive(_30);                // scope 0 at $DIR/shifts.rs:+3:27: +3:28
         _30 = _4;                        // scope 0 at $DIR/shifts.rs:+3:27: +3:28
-        _31 = BitAnd(_30, const -128_i32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28
-        _32 = Ne(move _31, const 0_i32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28
-        assert(!move _32, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28
+        _31 = _30 as u32 (IntToInt);     // scope 0 at $DIR/shifts.rs:+3:20: +3:28
+        _32 = Lt(move _31, const 128_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28
+        assert(move _32, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28
     }
 
     bb5: {
@@ -122,9 +122,9 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128;
         _34 = _2;                        // scope 0 at $DIR/shifts.rs:+3:30: +3:33
         StorageLive(_35);                // scope 0 at $DIR/shifts.rs:+3:37: +3:38
         _35 = _5;                        // scope 0 at $DIR/shifts.rs:+3:37: +3:38
-        _36 = BitAnd(_35, const -128_i128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38
-        _37 = Ne(move _36, const 0_i128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38
-        assert(!move _37, "attempt to shift left by `{}`, which would overflow", _35) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38
+        _36 = _35 as u128 (IntToInt);    // scope 0 at $DIR/shifts.rs:+3:30: +3:38
+        _37 = Lt(move _36, const 128_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38
+        assert(move _37, "attempt to shift left by `{}`, which would overflow", _35) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38
     }
 
     bb6: {
diff --git a/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir b/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir
index 89b9cb24cfd..04da2d20d24 100644
--- a/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir
+++ b/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir
@@ -11,34 +11,28 @@ fn shift_unsigned(_1: u8, _2: i128, _3: u8, _4: u32, _5: u128) -> ([u8; 3], [i12
     let mut _7: u8;                      // in scope 0 at $DIR/shifts.rs:+2:10: +2:20
     let mut _8: u8;                      // in scope 0 at $DIR/shifts.rs:+2:10: +2:15
     let mut _9: u8;                      // in scope 0 at $DIR/shifts.rs:+2:19: +2:20
-    let mut _10: u8;                     // in scope 0 at $DIR/shifts.rs:+2:10: +2:20
-    let mut _11: bool;                   // in scope 0 at $DIR/shifts.rs:+2:10: +2:20
-    let mut _12: u8;                     // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
-    let mut _13: u8;                     // in scope 0 at $DIR/shifts.rs:+2:22: +2:27
-    let mut _14: u32;                    // in scope 0 at $DIR/shifts.rs:+2:31: +2:32
-    let mut _15: u32;                    // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
-    let mut _16: bool;                   // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
-    let mut _17: u8;                     // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
-    let mut _18: u8;                     // in scope 0 at $DIR/shifts.rs:+2:34: +2:39
-    let mut _19: u128;                   // in scope 0 at $DIR/shifts.rs:+2:43: +2:44
-    let mut _20: u128;                   // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
-    let mut _21: bool;                   // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
-    let mut _22: [i128; 3];              // in scope 0 at $DIR/shifts.rs:+3:9: +3:39
-    let mut _23: i128;                   // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
-    let mut _24: i128;                   // in scope 0 at $DIR/shifts.rs:+3:10: +3:13
-    let mut _25: u8;                     // in scope 0 at $DIR/shifts.rs:+3:17: +3:18
-    let mut _26: u8;                     // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
-    let mut _27: bool;                   // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
-    let mut _28: i128;                   // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
-    let mut _29: i128;                   // in scope 0 at $DIR/shifts.rs:+3:20: +3:23
-    let mut _30: u32;                    // in scope 0 at $DIR/shifts.rs:+3:27: +3:28
-    let mut _31: u32;                    // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
-    let mut _32: bool;                   // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
-    let mut _33: i128;                   // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
-    let mut _34: i128;                   // in scope 0 at $DIR/shifts.rs:+3:30: +3:33
-    let mut _35: u128;                   // in scope 0 at $DIR/shifts.rs:+3:37: +3:38
-    let mut _36: u128;                   // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
-    let mut _37: bool;                   // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
+    let mut _10: bool;                   // in scope 0 at $DIR/shifts.rs:+2:10: +2:20
+    let mut _11: u8;                     // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
+    let mut _12: u8;                     // in scope 0 at $DIR/shifts.rs:+2:22: +2:27
+    let mut _13: u32;                    // in scope 0 at $DIR/shifts.rs:+2:31: +2:32
+    let mut _14: bool;                   // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
+    let mut _15: u8;                     // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
+    let mut _16: u8;                     // in scope 0 at $DIR/shifts.rs:+2:34: +2:39
+    let mut _17: u128;                   // in scope 0 at $DIR/shifts.rs:+2:43: +2:44
+    let mut _18: bool;                   // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
+    let mut _19: [i128; 3];              // in scope 0 at $DIR/shifts.rs:+3:9: +3:39
+    let mut _20: i128;                   // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
+    let mut _21: i128;                   // in scope 0 at $DIR/shifts.rs:+3:10: +3:13
+    let mut _22: u8;                     // in scope 0 at $DIR/shifts.rs:+3:17: +3:18
+    let mut _23: bool;                   // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
+    let mut _24: i128;                   // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
+    let mut _25: i128;                   // in scope 0 at $DIR/shifts.rs:+3:20: +3:23
+    let mut _26: u32;                    // in scope 0 at $DIR/shifts.rs:+3:27: +3:28
+    let mut _27: bool;                   // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
+    let mut _28: i128;                   // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
+    let mut _29: i128;                   // in scope 0 at $DIR/shifts.rs:+3:30: +3:33
+    let mut _30: u128;                   // in scope 0 at $DIR/shifts.rs:+3:37: +3:38
+    let mut _31: bool;                   // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
 
     bb0: {
         StorageLive(_6);                 // scope 0 at $DIR/shifts.rs:+2:9: +2:45
@@ -47,96 +41,90 @@ fn shift_unsigned(_1: u8, _2: i128, _3: u8, _4: u32, _5: u128) -> ([u8; 3], [i12
         _8 = _1;                         // scope 0 at $DIR/shifts.rs:+2:10: +2:15
         StorageLive(_9);                 // scope 0 at $DIR/shifts.rs:+2:19: +2:20
         _9 = _3;                         // scope 0 at $DIR/shifts.rs:+2:19: +2:20
-        _10 = BitAnd(_9, const 248_u8);  // scope 0 at $DIR/shifts.rs:+2:10: +2:20
-        _11 = Ne(move _10, const 0_u8);  // scope 0 at $DIR/shifts.rs:+2:10: +2:20
-        assert(!move _11, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20
+        _10 = Lt(_9, const 8_u8);        // scope 0 at $DIR/shifts.rs:+2:10: +2:20
+        assert(move _10, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20
     }
 
     bb1: {
         _7 = Shr(move _8, move _9);      // scope 0 at $DIR/shifts.rs:+2:10: +2:20
         StorageDead(_9);                 // scope 0 at $DIR/shifts.rs:+2:19: +2:20
         StorageDead(_8);                 // scope 0 at $DIR/shifts.rs:+2:19: +2:20
-        StorageLive(_12);                // scope 0 at $DIR/shifts.rs:+2:22: +2:32
-        StorageLive(_13);                // scope 0 at $DIR/shifts.rs:+2:22: +2:27
-        _13 = _1;                        // scope 0 at $DIR/shifts.rs:+2:22: +2:27
-        StorageLive(_14);                // scope 0 at $DIR/shifts.rs:+2:31: +2:32
-        _14 = _4;                        // scope 0 at $DIR/shifts.rs:+2:31: +2:32
-        _15 = BitAnd(_14, const 4294967288_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32
-        _16 = Ne(move _15, const 0_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32
-        assert(!move _16, "attempt to shift right by `{}`, which would overflow", _14) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32
+        StorageLive(_11);                // scope 0 at $DIR/shifts.rs:+2:22: +2:32
+        StorageLive(_12);                // scope 0 at $DIR/shifts.rs:+2:22: +2:27
+        _12 = _1;                        // scope 0 at $DIR/shifts.rs:+2:22: +2:27
+        StorageLive(_13);                // scope 0 at $DIR/shifts.rs:+2:31: +2:32
+        _13 = _4;                        // scope 0 at $DIR/shifts.rs:+2:31: +2:32
+        _14 = Lt(_13, const 8_u32);      // scope 0 at $DIR/shifts.rs:+2:22: +2:32
+        assert(move _14, "attempt to shift right by `{}`, which would overflow", _13) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32
     }
 
     bb2: {
-        _12 = Shr(move _13, move _14);   // scope 0 at $DIR/shifts.rs:+2:22: +2:32
-        StorageDead(_14);                // scope 0 at $DIR/shifts.rs:+2:31: +2:32
+        _11 = Shr(move _12, move _13);   // scope 0 at $DIR/shifts.rs:+2:22: +2:32
         StorageDead(_13);                // scope 0 at $DIR/shifts.rs:+2:31: +2:32
-        StorageLive(_17);                // scope 0 at $DIR/shifts.rs:+2:34: +2:44
-        StorageLive(_18);                // scope 0 at $DIR/shifts.rs:+2:34: +2:39
-        _18 = _1;                        // scope 0 at $DIR/shifts.rs:+2:34: +2:39
-        StorageLive(_19);                // scope 0 at $DIR/shifts.rs:+2:43: +2:44
-        _19 = _5;                        // scope 0 at $DIR/shifts.rs:+2:43: +2:44
-        _20 = BitAnd(_19, const 340282366920938463463374607431768211448_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44
-        _21 = Ne(move _20, const 0_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44
-        assert(!move _21, "attempt to shift right by `{}`, which would overflow", _19) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44
+        StorageDead(_12);                // scope 0 at $DIR/shifts.rs:+2:31: +2:32
+        StorageLive(_15);                // scope 0 at $DIR/shifts.rs:+2:34: +2:44
+        StorageLive(_16);                // scope 0 at $DIR/shifts.rs:+2:34: +2:39
+        _16 = _1;                        // scope 0 at $DIR/shifts.rs:+2:34: +2:39
+        StorageLive(_17);                // scope 0 at $DIR/shifts.rs:+2:43: +2:44
+        _17 = _5;                        // scope 0 at $DIR/shifts.rs:+2:43: +2:44
+        _18 = Lt(_17, const 8_u128);     // scope 0 at $DIR/shifts.rs:+2:34: +2:44
+        assert(move _18, "attempt to shift right by `{}`, which would overflow", _17) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44
     }
 
     bb3: {
-        _17 = Shr(move _18, move _19);   // scope 0 at $DIR/shifts.rs:+2:34: +2:44
-        StorageDead(_19);                // scope 0 at $DIR/shifts.rs:+2:43: +2:44
-        StorageDead(_18);                // scope 0 at $DIR/shifts.rs:+2:43: +2:44
-        _6 = [move _7, move _12, move _17]; // scope 0 at $DIR/shifts.rs:+2:9: +2:45
-        StorageDead(_17);                // scope 0 at $DIR/shifts.rs:+2:44: +2:45
-        StorageDead(_12);                // scope 0 at $DIR/shifts.rs:+2:44: +2:45
+        _15 = Shr(move _16, move _17);   // scope 0 at $DIR/shifts.rs:+2:34: +2:44
+        StorageDead(_17);                // scope 0 at $DIR/shifts.rs:+2:43: +2:44
+        StorageDead(_16);                // scope 0 at $DIR/shifts.rs:+2:43: +2:44
+        _6 = [move _7, move _11, move _15]; // scope 0 at $DIR/shifts.rs:+2:9: +2:45
+        StorageDead(_15);                // scope 0 at $DIR/shifts.rs:+2:44: +2:45
+        StorageDead(_11);                // scope 0 at $DIR/shifts.rs:+2:44: +2:45
         StorageDead(_7);                 // scope 0 at $DIR/shifts.rs:+2:44: +2:45
-        StorageLive(_22);                // scope 0 at $DIR/shifts.rs:+3:9: +3:39
-        StorageLive(_23);                // scope 0 at $DIR/shifts.rs:+3:10: +3:18
-        StorageLive(_24);                // scope 0 at $DIR/shifts.rs:+3:10: +3:13
-        _24 = _2;                        // scope 0 at $DIR/shifts.rs:+3:10: +3:13
-        StorageLive(_25);                // scope 0 at $DIR/shifts.rs:+3:17: +3:18
-        _25 = _3;                        // scope 0 at $DIR/shifts.rs:+3:17: +3:18
-        _26 = BitAnd(_25, const 128_u8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18
-        _27 = Ne(move _26, const 0_u8);  // scope 0 at $DIR/shifts.rs:+3:10: +3:18
-        assert(!move _27, "attempt to shift left by `{}`, which would overflow", _25) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18
+        StorageLive(_19);                // scope 0 at $DIR/shifts.rs:+3:9: +3:39
+        StorageLive(_20);                // scope 0 at $DIR/shifts.rs:+3:10: +3:18
+        StorageLive(_21);                // scope 0 at $DIR/shifts.rs:+3:10: +3:13
+        _21 = _2;                        // scope 0 at $DIR/shifts.rs:+3:10: +3:13
+        StorageLive(_22);                // scope 0 at $DIR/shifts.rs:+3:17: +3:18
+        _22 = _3;                        // scope 0 at $DIR/shifts.rs:+3:17: +3:18
+        _23 = Lt(_22, const 128_u8);     // scope 0 at $DIR/shifts.rs:+3:10: +3:18
+        assert(move _23, "attempt to shift left by `{}`, which would overflow", _22) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18
     }
 
     bb4: {
-        _23 = Shl(move _24, move _25);   // scope 0 at $DIR/shifts.rs:+3:10: +3:18
-        StorageDead(_25);                // scope 0 at $DIR/shifts.rs:+3:17: +3:18
-        StorageDead(_24);                // scope 0 at $DIR/shifts.rs:+3:17: +3:18
-        StorageLive(_28);                // scope 0 at $DIR/shifts.rs:+3:20: +3:28
-        StorageLive(_29);                // scope 0 at $DIR/shifts.rs:+3:20: +3:23
-        _29 = _2;                        // scope 0 at $DIR/shifts.rs:+3:20: +3:23
-        StorageLive(_30);                // scope 0 at $DIR/shifts.rs:+3:27: +3:28
-        _30 = _4;                        // scope 0 at $DIR/shifts.rs:+3:27: +3:28
-        _31 = BitAnd(_30, const 4294967168_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28
-        _32 = Ne(move _31, const 0_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28
-        assert(!move _32, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28
+        _20 = Shl(move _21, move _22);   // scope 0 at $DIR/shifts.rs:+3:10: +3:18
+        StorageDead(_22);                // scope 0 at $DIR/shifts.rs:+3:17: +3:18
+        StorageDead(_21);                // scope 0 at $DIR/shifts.rs:+3:17: +3:18
+        StorageLive(_24);                // scope 0 at $DIR/shifts.rs:+3:20: +3:28
+        StorageLive(_25);                // scope 0 at $DIR/shifts.rs:+3:20: +3:23
+        _25 = _2;                        // scope 0 at $DIR/shifts.rs:+3:20: +3:23
+        StorageLive(_26);                // scope 0 at $DIR/shifts.rs:+3:27: +3:28
+        _26 = _4;                        // scope 0 at $DIR/shifts.rs:+3:27: +3:28
+        _27 = Lt(_26, const 128_u32);    // scope 0 at $DIR/shifts.rs:+3:20: +3:28
+        assert(move _27, "attempt to shift left by `{}`, which would overflow", _26) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28
     }
 
     bb5: {
-        _28 = Shl(move _29, move _30);   // scope 0 at $DIR/shifts.rs:+3:20: +3:28
-        StorageDead(_30);                // scope 0 at $DIR/shifts.rs:+3:27: +3:28
-        StorageDead(_29);                // scope 0 at $DIR/shifts.rs:+3:27: +3:28
-        StorageLive(_33);                // scope 0 at $DIR/shifts.rs:+3:30: +3:38
-        StorageLive(_34);                // scope 0 at $DIR/shifts.rs:+3:30: +3:33
-        _34 = _2;                        // scope 0 at $DIR/shifts.rs:+3:30: +3:33
-        StorageLive(_35);                // scope 0 at $DIR/shifts.rs:+3:37: +3:38
-        _35 = _5;                        // scope 0 at $DIR/shifts.rs:+3:37: +3:38
-        _36 = BitAnd(_35, const 340282366920938463463374607431768211328_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38
-        _37 = Ne(move _36, const 0_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38
-        assert(!move _37, "attempt to shift left by `{}`, which would overflow", _35) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38
+        _24 = Shl(move _25, move _26);   // scope 0 at $DIR/shifts.rs:+3:20: +3:28
+        StorageDead(_26);                // scope 0 at $DIR/shifts.rs:+3:27: +3:28
+        StorageDead(_25);                // scope 0 at $DIR/shifts.rs:+3:27: +3:28
+        StorageLive(_28);                // scope 0 at $DIR/shifts.rs:+3:30: +3:38
+        StorageLive(_29);                // scope 0 at $DIR/shifts.rs:+3:30: +3:33
+        _29 = _2;                        // scope 0 at $DIR/shifts.rs:+3:30: +3:33
+        StorageLive(_30);                // scope 0 at $DIR/shifts.rs:+3:37: +3:38
+        _30 = _5;                        // scope 0 at $DIR/shifts.rs:+3:37: +3:38
+        _31 = Lt(_30, const 128_u128);   // scope 0 at $DIR/shifts.rs:+3:30: +3:38
+        assert(move _31, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38
     }
 
     bb6: {
-        _33 = Shl(move _34, move _35);   // scope 0 at $DIR/shifts.rs:+3:30: +3:38
-        StorageDead(_35);                // scope 0 at $DIR/shifts.rs:+3:37: +3:38
-        StorageDead(_34);                // scope 0 at $DIR/shifts.rs:+3:37: +3:38
-        _22 = [move _23, move _28, move _33]; // scope 0 at $DIR/shifts.rs:+3:9: +3:39
-        StorageDead(_33);                // scope 0 at $DIR/shifts.rs:+3:38: +3:39
+        _28 = Shl(move _29, move _30);   // scope 0 at $DIR/shifts.rs:+3:30: +3:38
+        StorageDead(_30);                // scope 0 at $DIR/shifts.rs:+3:37: +3:38
+        StorageDead(_29);                // scope 0 at $DIR/shifts.rs:+3:37: +3:38
+        _19 = [move _20, move _24, move _28]; // scope 0 at $DIR/shifts.rs:+3:9: +3:39
         StorageDead(_28);                // scope 0 at $DIR/shifts.rs:+3:38: +3:39
-        StorageDead(_23);                // scope 0 at $DIR/shifts.rs:+3:38: +3:39
-        _0 = (move _6, move _22);        // scope 0 at $DIR/shifts.rs:+1:5: +4:6
-        StorageDead(_22);                // scope 0 at $DIR/shifts.rs:+4:5: +4:6
+        StorageDead(_24);                // scope 0 at $DIR/shifts.rs:+3:38: +3:39
+        StorageDead(_20);                // scope 0 at $DIR/shifts.rs:+3:38: +3:39
+        _0 = (move _6, move _19);        // scope 0 at $DIR/shifts.rs:+1:5: +4:6
+        StorageDead(_19);                // scope 0 at $DIR/shifts.rs:+4:5: +4:6
         StorageDead(_6);                 // scope 0 at $DIR/shifts.rs:+4:5: +4:6
         return;                          // scope 0 at $DIR/shifts.rs:+5:2: +5:2
     }
diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.diff b/tests/mir-opt/issue_101973.inner.ConstProp.diff
index fb0b3866e69..b377a65b964 100644
--- a/tests/mir-opt/issue_101973.inner.ConstProp.diff
+++ b/tests/mir-opt/issue_101973.inner.ConstProp.diff
@@ -12,9 +12,9 @@
       let mut _7: u32;                     // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:52
       let mut _8: u32;                     // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
       let mut _9: u32;                     // in scope 0 at $DIR/issue_101973.rs:+1:33: +1:39
-      let mut _10: i32;                    // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
+      let mut _10: u32;                    // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
       let mut _11: bool;                   // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
-      let mut _12: i32;                    // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
+      let mut _12: u32;                    // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
       let mut _13: bool;                   // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
       scope 1 (inlined imm8) {             // at $DIR/issue_101973.rs:14:5: 14:17
           debug x => _1;                   // in scope 1 at $DIR/issue_101973.rs:5:13: 5:14
@@ -43,24 +43,24 @@
           StorageLive(_6);                 // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
           StorageLive(_7);                 // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52
           StorageLive(_8);                 // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
--         _10 = BitAnd(const 8_i32, const -32_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
--         _11 = Ne(move _10, const 0_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
--         assert(!move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
-+         _10 = const 0_i32;               // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
-+         _11 = const false;               // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
-+         assert(!const false, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
+-         _10 = const 8_i32 as u32 (IntToInt); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
+-         _11 = Lt(move _10, const 32_u32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
+-         assert(move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
++         _10 = const 8_u32;               // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
++         _11 = const true;                // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
++         assert(const true, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
       }
   
       bb1: {
           _8 = Shr(_1, const 8_i32);       // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
           _7 = BitAnd(move _8, const 15_u32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52
           StorageDead(_8);                 // scope 0 at $DIR/issue_101973.rs:+1:51: +1:52
--         _12 = BitAnd(const 1_i32, const -32_i32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
--         _13 = Ne(move _12, const 0_i32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
--         assert(!move _13, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
-+         _12 = const 0_i32;               // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
-+         _13 = const false;               // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
-+         assert(!const false, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
+-         _12 = const 1_i32 as u32 (IntToInt); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
+-         _13 = Lt(move _12, const 32_u32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
+-         assert(move _13, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
++         _12 = const 1_u32;               // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
++         _13 = const true;                // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
++         assert(const true, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
       }
   
       bb2: {