diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index b16163edf14..9d99344d5bd 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -226,6 +226,11 @@ impl ScalarInt { } } + #[inline] + pub fn try_from_target_usize(i: impl Into, tcx: TyCtxt<'_>) -> Option { + Self::try_from_uint(i, tcx.data_layout.pointer_size) + } + #[inline] pub fn assert_bits(self, target_size: Size) -> u128 { self.to_bits(target_size).unwrap_or_else(|size| { diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index e713a6cf006..91bed82a634 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -193,47 +193,64 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { rvalue: &Rvalue<'tcx>, state: &mut State, ) -> ValueOrPlace { - match rvalue { - Rvalue::Cast( - kind @ (CastKind::IntToInt - | CastKind::FloatToInt - | CastKind::FloatToFloat - | CastKind::IntToFloat), - operand, - ty, - ) => match self.eval_operand(operand, state) { - FlatSet::Elem(op) => match kind { - CastKind::IntToInt | CastKind::IntToFloat => { - self.ecx.int_to_int_or_float(&op, *ty) - } - CastKind::FloatToInt | CastKind::FloatToFloat => { - self.ecx.float_to_float_or_int(&op, *ty) - } - _ => unreachable!(), + let val = match rvalue { + Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat, operand, ty) => { + match self.eval_operand(operand, state) { + FlatSet::Elem(op) => self + .ecx + .int_to_int_or_float(&op, *ty) + .map_or(FlatSet::Top, |result| self.wrap_immediate(result)), + FlatSet::Bottom => FlatSet::Bottom, + FlatSet::Top => FlatSet::Top, } - .map(|result| ValueOrPlace::Value(self.wrap_immediate(result))) - .unwrap_or(ValueOrPlace::TOP), - _ => ValueOrPlace::TOP, - }, + } + Rvalue::Cast(CastKind::FloatToInt | CastKind::FloatToFloat, operand, ty) => { + match self.eval_operand(operand, state) { + FlatSet::Elem(op) => self + .ecx + .float_to_float_or_int(&op, *ty) + .map_or(FlatSet::Top, |result| self.wrap_immediate(result)), + FlatSet::Bottom => FlatSet::Bottom, + FlatSet::Top => FlatSet::Top, + } + } + Rvalue::Cast(CastKind::Transmute, operand, _) => { + match self.eval_operand(operand, state) { + FlatSet::Elem(op) => self.wrap_immediate(*op), + FlatSet::Bottom => FlatSet::Bottom, + FlatSet::Top => FlatSet::Top, + } + } Rvalue::BinaryOp(op, box (left, right)) => { // Overflows must be ignored here. let (val, _overflow) = self.binary_op(state, *op, left, right); - ValueOrPlace::Value(val) + val } Rvalue::UnaryOp(op, operand) => match self.eval_operand(operand, state) { - FlatSet::Elem(value) => self - .ecx - .unary_op(*op, &value) - .map(|val| ValueOrPlace::Value(self.wrap_immty(val))) - .unwrap_or(ValueOrPlace::Value(FlatSet::Top)), - FlatSet::Bottom => ValueOrPlace::Value(FlatSet::Bottom), - FlatSet::Top => ValueOrPlace::Value(FlatSet::Top), + FlatSet::Elem(value) => { + self.ecx.unary_op(*op, &value).map_or(FlatSet::Top, |val| self.wrap_immty(val)) + } + FlatSet::Bottom => FlatSet::Bottom, + FlatSet::Top => FlatSet::Top, }, - Rvalue::Discriminant(place) => { - ValueOrPlace::Value(state.get_discr(place.as_ref(), self.map())) + Rvalue::NullaryOp(null_op, ty) => { + let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else { + return ValueOrPlace::Value(FlatSet::Top); + }; + let val = match null_op { + NullOp::SizeOf if layout.is_sized() => layout.size.bytes(), + NullOp::AlignOf if layout.is_sized() => layout.align.abi.bytes(), + NullOp::OffsetOf(fields) => layout + .offset_of_subfield(&self.ecx, fields.iter().map(|f| f.index())) + .bytes(), + _ => return ValueOrPlace::Value(FlatSet::Top), + }; + ScalarInt::try_from_target_usize(val, self.tcx).map_or(FlatSet::Top, FlatSet::Elem) } - _ => self.super_rvalue(rvalue, state), - } + Rvalue::Discriminant(place) => state.get_discr(place.as_ref(), self.map()), + _ => return self.super_rvalue(rvalue, state), + }; + ValueOrPlace::Value(val) } fn handle_constant( diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-abort.diff new file mode 100644 index 00000000000..c61414b6541 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-abort.diff @@ -0,0 +1,76 @@ +- // MIR for `concrete` before DataflowConstProp ++ // MIR for `concrete` after DataflowConstProp + + fn concrete() -> () { + let mut _0: (); + let _1: usize; + let mut _2: usize; + let mut _4: usize; + let mut _6: usize; + let mut _8: usize; + scope 1 { + debug x => _1; + let _3: usize; + scope 2 { + debug y => _3; + let _5: usize; + scope 3 { + debug z0 => _5; + let _7: usize; + scope 4 { + debug z1 => _7; + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); +- _2 = OffsetOf(Alpha, [0]); +- _1 = must_use::(move _2) -> [return: bb1, unwind unreachable]; ++ _2 = const 4_usize; ++ _1 = must_use::(const 4_usize) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_2); + StorageLive(_3); + StorageLive(_4); +- _4 = OffsetOf(Alpha, [1]); +- _3 = must_use::(move _4) -> [return: bb2, unwind unreachable]; ++ _4 = const 0_usize; ++ _3 = must_use::(const 0_usize) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_4); + StorageLive(_5); + StorageLive(_6); +- _6 = OffsetOf(Alpha, [2, 0]); +- _5 = must_use::(move _6) -> [return: bb3, unwind unreachable]; ++ _6 = const 2_usize; ++ _5 = must_use::(const 2_usize) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_6); + StorageLive(_7); + StorageLive(_8); +- _8 = OffsetOf(Alpha, [2, 1]); +- _7 = must_use::(move _8) -> [return: bb4, unwind unreachable]; ++ _8 = const 3_usize; ++ _7 = must_use::(const 3_usize) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_8); + _0 = const (); + StorageDead(_7); + StorageDead(_5); + StorageDead(_3); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-unwind.diff new file mode 100644 index 00000000000..0c3939a3456 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-unwind.diff @@ -0,0 +1,76 @@ +- // MIR for `concrete` before DataflowConstProp ++ // MIR for `concrete` after DataflowConstProp + + fn concrete() -> () { + let mut _0: (); + let _1: usize; + let mut _2: usize; + let mut _4: usize; + let mut _6: usize; + let mut _8: usize; + scope 1 { + debug x => _1; + let _3: usize; + scope 2 { + debug y => _3; + let _5: usize; + scope 3 { + debug z0 => _5; + let _7: usize; + scope 4 { + debug z1 => _7; + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); +- _2 = OffsetOf(Alpha, [0]); +- _1 = must_use::(move _2) -> [return: bb1, unwind continue]; ++ _2 = const 4_usize; ++ _1 = must_use::(const 4_usize) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_2); + StorageLive(_3); + StorageLive(_4); +- _4 = OffsetOf(Alpha, [1]); +- _3 = must_use::(move _4) -> [return: bb2, unwind continue]; ++ _4 = const 0_usize; ++ _3 = must_use::(const 0_usize) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_4); + StorageLive(_5); + StorageLive(_6); +- _6 = OffsetOf(Alpha, [2, 0]); +- _5 = must_use::(move _6) -> [return: bb3, unwind continue]; ++ _6 = const 2_usize; ++ _5 = must_use::(const 2_usize) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_6); + StorageLive(_7); + StorageLive(_8); +- _8 = OffsetOf(Alpha, [2, 1]); +- _7 = must_use::(move _8) -> [return: bb4, unwind continue]; ++ _8 = const 3_usize; ++ _7 = must_use::(const 3_usize) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_8); + _0 = const (); + StorageDead(_7); + StorageDead(_5); + StorageDead(_3); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-abort.diff new file mode 100644 index 00000000000..d54d4687060 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-abort.diff @@ -0,0 +1,72 @@ +- // MIR for `generic` before DataflowConstProp ++ // MIR for `generic` after DataflowConstProp + + fn generic() -> () { + let mut _0: (); + let _1: usize; + let mut _2: usize; + let mut _4: usize; + let mut _6: usize; + let mut _8: usize; + scope 1 { + debug gx => _1; + let _3: usize; + scope 2 { + debug gy => _3; + let _5: usize; + scope 3 { + debug dx => _5; + let _7: usize; + scope 4 { + debug dy => _7; + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = OffsetOf(Gamma, [0]); + _1 = must_use::(move _2) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_2); + StorageLive(_3); + StorageLive(_4); + _4 = OffsetOf(Gamma, [1]); + _3 = must_use::(move _4) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_4); + StorageLive(_5); + StorageLive(_6); +- _6 = OffsetOf(Delta, [1]); +- _5 = must_use::(move _6) -> [return: bb3, unwind unreachable]; ++ _6 = const 0_usize; ++ _5 = must_use::(const 0_usize) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_6); + StorageLive(_7); + StorageLive(_8); +- _8 = OffsetOf(Delta, [2]); +- _7 = must_use::(move _8) -> [return: bb4, unwind unreachable]; ++ _8 = const 2_usize; ++ _7 = must_use::(const 2_usize) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_8); + _0 = const (); + StorageDead(_7); + StorageDead(_5); + StorageDead(_3); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-unwind.diff new file mode 100644 index 00000000000..6032a2274ef --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-unwind.diff @@ -0,0 +1,72 @@ +- // MIR for `generic` before DataflowConstProp ++ // MIR for `generic` after DataflowConstProp + + fn generic() -> () { + let mut _0: (); + let _1: usize; + let mut _2: usize; + let mut _4: usize; + let mut _6: usize; + let mut _8: usize; + scope 1 { + debug gx => _1; + let _3: usize; + scope 2 { + debug gy => _3; + let _5: usize; + scope 3 { + debug dx => _5; + let _7: usize; + scope 4 { + debug dy => _7; + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = OffsetOf(Gamma, [0]); + _1 = must_use::(move _2) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_2); + StorageLive(_3); + StorageLive(_4); + _4 = OffsetOf(Gamma, [1]); + _3 = must_use::(move _4) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_4); + StorageLive(_5); + StorageLive(_6); +- _6 = OffsetOf(Delta, [1]); +- _5 = must_use::(move _6) -> [return: bb3, unwind continue]; ++ _6 = const 0_usize; ++ _5 = must_use::(const 0_usize) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_6); + StorageLive(_7); + StorageLive(_8); +- _8 = OffsetOf(Delta, [2]); +- _7 = must_use::(move _8) -> [return: bb4, unwind continue]; ++ _8 = const 2_usize; ++ _7 = must_use::(const 2_usize) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_8); + _0 = const (); + StorageDead(_7); + StorageDead(_5); + StorageDead(_3); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs new file mode 100644 index 00000000000..ccc90790e52 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs @@ -0,0 +1,49 @@ +// unit-test: DataflowConstProp +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + +#![feature(offset_of)] + +use std::marker::PhantomData; +use std::mem::offset_of; + +struct Alpha { + x: u8, + y: u16, + z: Beta, +} + +struct Beta(u8, u8); + +struct Gamma { + x: u8, + y: u16, + _t: T, +} + +#[repr(C)] +struct Delta { + _phantom: PhantomData, + x: u8, + y: u16, +} + +// EMIT_MIR offset_of.concrete.DataflowConstProp.diff +fn concrete() { + let x = offset_of!(Alpha, x); + let y = offset_of!(Alpha, y); + let z0 = offset_of!(Alpha, z.0); + let z1 = offset_of!(Alpha, z.1); +} + +// EMIT_MIR offset_of.generic.DataflowConstProp.diff +fn generic() { + let gx = offset_of!(Gamma, x); + let gy = offset_of!(Gamma, y); + let dx = offset_of!(Delta, x); + let dy = offset_of!(Delta, y); +} + +fn main() { + concrete(); + generic::<()>(); +} diff --git a/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.32bit.diff new file mode 100644 index 00000000000..52f096ac0e4 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.32bit.diff @@ -0,0 +1,15 @@ +- // MIR for `from_char` before DataflowConstProp ++ // MIR for `from_char` after DataflowConstProp + + fn from_char() -> i32 { + let mut _0: i32; + scope 1 { + } + + bb0: { +- _0 = const 'R' as i32 (Transmute); ++ _0 = const 82_i32; + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.64bit.diff new file mode 100644 index 00000000000..52f096ac0e4 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.64bit.diff @@ -0,0 +1,15 @@ +- // MIR for `from_char` before DataflowConstProp ++ // MIR for `from_char` after DataflowConstProp + + fn from_char() -> i32 { + let mut _0: i32; + scope 1 { + } + + bb0: { +- _0 = const 'R' as i32 (Transmute); ++ _0 = const 82_i32; + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.32bit.diff new file mode 100644 index 00000000000..3972eb209a1 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.32bit.diff @@ -0,0 +1,15 @@ +- // MIR for `invalid_bool` before DataflowConstProp ++ // MIR for `invalid_bool` after DataflowConstProp + + fn invalid_bool() -> bool { + let mut _0: bool; + scope 1 { + } + + bb0: { +- _0 = const -1_i8 as bool (Transmute); ++ _0 = const {transmute(0xff): bool}; + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.64bit.diff new file mode 100644 index 00000000000..3972eb209a1 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.64bit.diff @@ -0,0 +1,15 @@ +- // MIR for `invalid_bool` before DataflowConstProp ++ // MIR for `invalid_bool` after DataflowConstProp + + fn invalid_bool() -> bool { + let mut _0: bool; + scope 1 { + } + + bb0: { +- _0 = const -1_i8 as bool (Transmute); ++ _0 = const {transmute(0xff): bool}; + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.32bit.diff new file mode 100644 index 00000000000..837dabde42a --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.32bit.diff @@ -0,0 +1,15 @@ +- // MIR for `invalid_char` before DataflowConstProp ++ // MIR for `invalid_char` after DataflowConstProp + + fn invalid_char() -> char { + let mut _0: char; + scope 1 { + } + + bb0: { +- _0 = const _ as char (Transmute); ++ _0 = const {transmute(0x7fffffff): char}; + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.64bit.diff new file mode 100644 index 00000000000..837dabde42a --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.64bit.diff @@ -0,0 +1,15 @@ +- // MIR for `invalid_char` before DataflowConstProp ++ // MIR for `invalid_char` after DataflowConstProp + + fn invalid_char() -> char { + let mut _0: char; + scope 1 { + } + + bb0: { +- _0 = const _ as char (Transmute); ++ _0 = const {transmute(0x7fffffff): char}; + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.32bit.diff new file mode 100644 index 00000000000..6091e169e8e --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.32bit.diff @@ -0,0 +1,18 @@ +- // MIR for `less_as_i8` before DataflowConstProp ++ // MIR for `less_as_i8` after DataflowConstProp + + fn less_as_i8() -> i8 { + let mut _0: i8; + let mut _1: std::cmp::Ordering; + scope 1 { + } + + bb0: { + StorageLive(_1); + _1 = Less; + _0 = move _1 as i8 (Transmute); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.64bit.diff new file mode 100644 index 00000000000..6091e169e8e --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.64bit.diff @@ -0,0 +1,18 @@ +- // MIR for `less_as_i8` before DataflowConstProp ++ // MIR for `less_as_i8` after DataflowConstProp + + fn less_as_i8() -> i8 { + let mut _0: i8; + let mut _1: std::cmp::Ordering; + scope 1 { + } + + bb0: { + StorageLive(_1); + _1 = Less; + _0 = move _1 as i8 (Transmute); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.rs b/tests/mir-opt/dataflow-const-prop/transmute.rs new file mode 100644 index 00000000000..c25e33ab0b6 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.rs @@ -0,0 +1,63 @@ +// unit-test: DataflowConstProp +// compile-flags: -O --crate-type=lib +// ignore-endian-big +// EMIT_MIR_FOR_EACH_BIT_WIDTH + +use std::mem::transmute; + +// EMIT_MIR transmute.less_as_i8.DataflowConstProp.diff +pub fn less_as_i8() -> i8 { + unsafe { transmute(std::cmp::Ordering::Less) } +} + +// EMIT_MIR transmute.from_char.DataflowConstProp.diff +pub fn from_char() -> i32 { + unsafe { transmute('R') } +} + +// EMIT_MIR transmute.valid_char.DataflowConstProp.diff +pub fn valid_char() -> char { + unsafe { transmute(0x52_u32) } +} + +// EMIT_MIR transmute.invalid_char.DataflowConstProp.diff +pub unsafe fn invalid_char() -> char { + unsafe { transmute(i32::MAX) } +} + +// EMIT_MIR transmute.invalid_bool.DataflowConstProp.diff +pub unsafe fn invalid_bool() -> bool { + unsafe { transmute(-1_i8) } +} + +// EMIT_MIR transmute.undef_union_as_integer.DataflowConstProp.diff +pub unsafe fn undef_union_as_integer() -> u32 { + union Union32 { value: u32, unit: () } + unsafe { transmute(Union32 { unit: () }) } +} + +// EMIT_MIR transmute.unreachable_direct.DataflowConstProp.diff +pub unsafe fn unreachable_direct() -> ! { + let x: Never = unsafe { transmute(()) }; + match x {} +} + +// EMIT_MIR transmute.unreachable_ref.DataflowConstProp.diff +pub unsafe fn unreachable_ref() -> ! { + let x: &Never = unsafe { transmute(1_usize) }; + match *x {} +} + +// EMIT_MIR transmute.unreachable_mut.DataflowConstProp.diff +pub unsafe fn unreachable_mut() -> ! { + let x: &mut Never = unsafe { transmute(1_usize) }; + match *x {} +} + +// EMIT_MIR transmute.unreachable_box.DataflowConstProp.diff +pub unsafe fn unreachable_box() -> ! { + let x: Box = unsafe { transmute(1_usize) }; + match *x {} +} + +enum Never {} diff --git a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff new file mode 100644 index 00000000000..fc0634b1f8f --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff @@ -0,0 +1,22 @@ +- // MIR for `undef_union_as_integer` before DataflowConstProp ++ // MIR for `undef_union_as_integer` after DataflowConstProp + + fn undef_union_as_integer() -> u32 { + let mut _0: u32; + let mut _1: undef_union_as_integer::Union32; + let mut _2: (); + scope 1 { + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = (); + _1 = Union32 { value: move _2 }; + StorageDead(_2); + _0 = move _1 as u32 (Transmute); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff new file mode 100644 index 00000000000..fc0634b1f8f --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff @@ -0,0 +1,22 @@ +- // MIR for `undef_union_as_integer` before DataflowConstProp ++ // MIR for `undef_union_as_integer` after DataflowConstProp + + fn undef_union_as_integer() -> u32 { + let mut _0: u32; + let mut _1: undef_union_as_integer::Union32; + let mut _2: (); + scope 1 { + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = (); + _1 = Union32 { value: move _2 }; + StorageDead(_2); + _0 = move _1 as u32 (Transmute); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff new file mode 100644 index 00000000000..d0c298ba233 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff @@ -0,0 +1,20 @@ +- // MIR for `unreachable_box` before DataflowConstProp ++ // MIR for `unreachable_box` after DataflowConstProp + + fn unreachable_box() -> ! { + let mut _0: !; + let _1: std::boxed::Box; + scope 1 { + debug x => _1; + } + scope 2 { + } + + bb0: { + StorageLive(_1); +- _1 = const 1_usize as std::boxed::Box (Transmute); ++ _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData:: }}, std::alloc::Global); + unreachable; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff new file mode 100644 index 00000000000..d0c298ba233 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff @@ -0,0 +1,20 @@ +- // MIR for `unreachable_box` before DataflowConstProp ++ // MIR for `unreachable_box` after DataflowConstProp + + fn unreachable_box() -> ! { + let mut _0: !; + let _1: std::boxed::Box; + scope 1 { + debug x => _1; + } + scope 2 { + } + + bb0: { + StorageLive(_1); +- _1 = const 1_usize as std::boxed::Box (Transmute); ++ _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData:: }}, std::alloc::Global); + unreachable; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff new file mode 100644 index 00000000000..acbb5cd1bc7 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff @@ -0,0 +1,22 @@ +- // MIR for `unreachable_direct` before DataflowConstProp ++ // MIR for `unreachable_direct` after DataflowConstProp + + fn unreachable_direct() -> ! { + let mut _0: !; + let _1: Never; + let mut _2: (); + scope 1 { + debug x => _1; + } + scope 2 { + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = (); + _1 = move _2 as Never (Transmute); + unreachable; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff new file mode 100644 index 00000000000..acbb5cd1bc7 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff @@ -0,0 +1,22 @@ +- // MIR for `unreachable_direct` before DataflowConstProp ++ // MIR for `unreachable_direct` after DataflowConstProp + + fn unreachable_direct() -> ! { + let mut _0: !; + let _1: Never; + let mut _2: (); + scope 1 { + debug x => _1; + } + scope 2 { + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = (); + _1 = move _2 as Never (Transmute); + unreachable; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.32bit.diff new file mode 100644 index 00000000000..2ffaeea72db --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.32bit.diff @@ -0,0 +1,24 @@ +- // MIR for `unreachable_mut` before DataflowConstProp ++ // MIR for `unreachable_mut` after DataflowConstProp + + fn unreachable_mut() -> ! { + let mut _0: !; + let _1: &mut Never; + let mut _2: &mut Never; + scope 1 { + debug x => _1; + } + scope 2 { + } + + bb0: { + StorageLive(_1); + StorageLive(_2); +- _2 = const 1_usize as &mut Never (Transmute); ++ _2 = const {0x1 as &mut Never}; + _1 = &mut (*_2); + StorageDead(_2); + unreachable; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.64bit.diff new file mode 100644 index 00000000000..2ffaeea72db --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.64bit.diff @@ -0,0 +1,24 @@ +- // MIR for `unreachable_mut` before DataflowConstProp ++ // MIR for `unreachable_mut` after DataflowConstProp + + fn unreachable_mut() -> ! { + let mut _0: !; + let _1: &mut Never; + let mut _2: &mut Never; + scope 1 { + debug x => _1; + } + scope 2 { + } + + bb0: { + StorageLive(_1); + StorageLive(_2); +- _2 = const 1_usize as &mut Never (Transmute); ++ _2 = const {0x1 as &mut Never}; + _1 = &mut (*_2); + StorageDead(_2); + unreachable; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.32bit.diff new file mode 100644 index 00000000000..31fcaafc5bc --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.32bit.diff @@ -0,0 +1,20 @@ +- // MIR for `unreachable_ref` before DataflowConstProp ++ // MIR for `unreachable_ref` after DataflowConstProp + + fn unreachable_ref() -> ! { + let mut _0: !; + let _1: &Never; + scope 1 { + debug x => _1; + } + scope 2 { + } + + bb0: { + StorageLive(_1); +- _1 = const 1_usize as &Never (Transmute); ++ _1 = const {0x1 as &Never}; + unreachable; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.64bit.diff new file mode 100644 index 00000000000..31fcaafc5bc --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.64bit.diff @@ -0,0 +1,20 @@ +- // MIR for `unreachable_ref` before DataflowConstProp ++ // MIR for `unreachable_ref` after DataflowConstProp + + fn unreachable_ref() -> ! { + let mut _0: !; + let _1: &Never; + scope 1 { + debug x => _1; + } + scope 2 { + } + + bb0: { + StorageLive(_1); +- _1 = const 1_usize as &Never (Transmute); ++ _1 = const {0x1 as &Never}; + unreachable; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.32bit.diff new file mode 100644 index 00000000000..402ef754a64 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.32bit.diff @@ -0,0 +1,15 @@ +- // MIR for `valid_char` before DataflowConstProp ++ // MIR for `valid_char` after DataflowConstProp + + fn valid_char() -> char { + let mut _0: char; + scope 1 { + } + + bb0: { +- _0 = const 82_u32 as char (Transmute); ++ _0 = const 'R'; + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.64bit.diff new file mode 100644 index 00000000000..402ef754a64 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.64bit.diff @@ -0,0 +1,15 @@ +- // MIR for `valid_char` before DataflowConstProp ++ // MIR for `valid_char` after DataflowConstProp + + fn valid_char() -> char { + let mut _0: char; + scope 1 { + } + + bb0: { +- _0 = const 82_u32 as char (Transmute); ++ _0 = const 'R'; + return; + } + } +