diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 6ab4ec6fe7e69..fd52ec3b2a712 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -41,10 +41,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { should_cleanup = true; continue; } - // unsound: https://github.com/rust-lang/rust/issues/124150 - if tcx.sess.opts.unstable_opts.unsound_mir_opts - && SimplifyToExp::default().simplify(tcx, body, bb_idx, param_env).is_some() - { + if SimplifyToExp::default().simplify(tcx, body, bb_idx, param_env).is_some() { should_cleanup = true; continue; } @@ -263,33 +260,49 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { } } +/// Check if the cast constant using `IntToInt` is equal to the target constant. +fn can_cast( + from_val: impl Into, + from_size: Size, + target_scalar: ScalarInt, + target_is_signed: bool, +) -> bool { + let from_scalar = ScalarInt::try_from_uint(from_val.into(), from_size).unwrap(); + let to_size = target_scalar.size(); + let cast_scalar = if target_is_signed { + ScalarInt::try_from_int(from_scalar.to_int(from_size), to_size).unwrap() + } else { + ScalarInt::try_from_uint(from_scalar.to_uint(from_size), to_size).unwrap() + }; + cast_scalar == target_scalar +} + #[derive(Default)] struct SimplifyToExp { - transfrom_types: Vec, + transfrom_kinds: Vec, } #[derive(Clone, Copy)] -enum CompareType<'tcx, 'a> { +enum ExpectedTransformKind<'tcx, 'a> { /// Identical statements. Same(&'a StatementKind<'tcx>), /// Assignment statements have the same value. - Eq(&'a Place<'tcx>, Ty<'tcx>, ScalarInt), + SameByEq { place: &'a Place<'tcx>, ty: Ty<'tcx>, scalar: ScalarInt }, /// Enum variant comparison type. - Discr { place: &'a Place<'tcx>, ty: Ty<'tcx>, is_signed: bool }, + Cast { place: &'a Place<'tcx>, ty: Ty<'tcx> }, } -enum TransfromType { +enum TransfromKind { Same, - Eq, - Discr, + Cast, } -impl From> for TransfromType { - fn from(compare_type: CompareType<'_, '_>) -> Self { +impl From> for TransfromKind { + fn from(compare_type: ExpectedTransformKind<'_, '_>) -> Self { match compare_type { - CompareType::Same(_) => TransfromType::Same, - CompareType::Eq(_, _, _) => TransfromType::Eq, - CompareType::Discr { .. } => TransfromType::Discr, + ExpectedTransformKind::Same(_) => TransfromKind::Same, + ExpectedTransformKind::SameByEq { .. } => TransfromKind::Same, + ExpectedTransformKind::Cast { .. } => TransfromKind::Cast, } } } @@ -353,7 +366,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { return None; } let mut target_iter = targets.iter(); - let (first_val, first_target) = target_iter.next().unwrap(); + let (first_case_val, first_target) = target_iter.next().unwrap(); let first_terminator_kind = &bbs[first_target].terminator().kind; // Check that destinations are identical, and if not, then don't optimize this block if !targets @@ -365,22 +378,18 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { let discr_size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size; let first_stmts = &bbs[first_target].statements; - let (second_val, second_target) = target_iter.next().unwrap(); + let (second_case_val, second_target) = target_iter.next().unwrap(); let second_stmts = &bbs[second_target].statements; if first_stmts.len() != second_stmts.len() { return None; } - fn int_equal(l: ScalarInt, r: impl Into, size: Size) -> bool { - l.to_bits_unchecked() == ScalarInt::try_from_uint(r, size).unwrap().to_bits_unchecked() - } - // We first compare the two branches, and then the other branches need to fulfill the same conditions. - let mut compare_types = Vec::new(); + let mut expected_transform_kinds = Vec::new(); for (f, s) in iter::zip(first_stmts, second_stmts) { let compare_type = match (&f.kind, &s.kind) { // If two statements are exactly the same, we can optimize. - (f_s, s_s) if f_s == s_s => CompareType::Same(f_s), + (f_s, s_s) if f_s == s_s => ExpectedTransformKind::Same(f_s), // If two statements are assignments with the match values to the same place, we can optimize. ( @@ -394,22 +403,27 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { f_c.const_.try_eval_scalar_int(tcx, param_env), s_c.const_.try_eval_scalar_int(tcx, param_env), ) { - (Some(f), Some(s)) if f == s => CompareType::Eq(lhs_f, f_c.const_.ty(), f), - // Enum variants can also be simplified to an assignment statement if their values are equal. - // We need to consider both unsigned and signed scenarios here. + (Some(f), Some(s)) if f == s => ExpectedTransformKind::SameByEq { + place: lhs_f, + ty: f_c.const_.ty(), + scalar: f, + }, + // Enum variants can also be simplified to an assignment statement, + // if we can use `IntToInt` cast to get an equal value. (Some(f), Some(s)) - if ((f_c.const_.ty().is_signed() || discr_ty.is_signed()) - && int_equal(f, first_val, discr_size) - && int_equal(s, second_val, discr_size)) - || (Some(f) == ScalarInt::try_from_uint(first_val, f.size()) - && Some(s) - == ScalarInt::try_from_uint(second_val, s.size())) => + if (can_cast( + first_case_val, + discr_size, + f, + f_c.const_.ty().is_signed(), + ) && can_cast( + second_case_val, + discr_size, + s, + s_c.const_.ty().is_signed(), + )) => { - CompareType::Discr { - place: lhs_f, - ty: f_c.const_.ty(), - is_signed: f_c.const_.ty().is_signed() || discr_ty.is_signed(), - } + ExpectedTransformKind::Cast { place: lhs_f, ty: f_c.const_.ty() } } _ => { return None; @@ -420,47 +434,36 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { // Otherwise we cannot optimize. Try another block. _ => return None, }; - compare_types.push(compare_type); + expected_transform_kinds.push(compare_type); } // All remaining BBs need to fulfill the same pattern as the two BBs from the previous step. for (other_val, other_target) in target_iter { let other_stmts = &bbs[other_target].statements; - if compare_types.len() != other_stmts.len() { + if expected_transform_kinds.len() != other_stmts.len() { return None; } - for (f, s) in iter::zip(&compare_types, other_stmts) { + for (f, s) in iter::zip(&expected_transform_kinds, other_stmts) { match (*f, &s.kind) { - (CompareType::Same(f_s), s_s) if f_s == s_s => {} + (ExpectedTransformKind::Same(f_s), s_s) if f_s == s_s => {} ( - CompareType::Eq(lhs_f, f_ty, val), + ExpectedTransformKind::SameByEq { place: lhs_f, ty: f_ty, scalar }, StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), ) if lhs_f == lhs_s && s_c.const_.ty() == f_ty - && s_c.const_.try_eval_scalar_int(tcx, param_env) == Some(val) => {} + && s_c.const_.try_eval_scalar_int(tcx, param_env) == Some(scalar) => {} ( - CompareType::Discr { place: lhs_f, ty: f_ty, is_signed }, + ExpectedTransformKind::Cast { place: lhs_f, ty: f_ty }, StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), - ) if lhs_f == lhs_s && s_c.const_.ty() == f_ty => { - let Some(f) = s_c.const_.try_eval_scalar_int(tcx, param_env) else { - return None; - }; - if is_signed - && s_c.const_.ty().is_signed() - && int_equal(f, other_val, discr_size) - { - continue; - } - if Some(f) == ScalarInt::try_from_uint(other_val, f.size()) { - continue; - } - return None; - } + ) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, param_env) + && lhs_f == lhs_s + && s_c.const_.ty() == f_ty + && can_cast(other_val, discr_size, f, f_ty.is_signed()) => {} _ => return None, } } } - self.transfrom_types = compare_types.into_iter().map(|c| c.into()).collect(); + self.transfrom_kinds = expected_transform_kinds.into_iter().map(|c| c.into()).collect(); Some(()) } @@ -478,13 +481,13 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { let (_, first) = targets.iter().next().unwrap(); let first = &bbs[first]; - for (t, s) in iter::zip(&self.transfrom_types, &first.statements) { + for (t, s) in iter::zip(&self.transfrom_kinds, &first.statements) { match (t, &s.kind) { - (TransfromType::Same, _) | (TransfromType::Eq, _) => { + (TransfromKind::Same, _) => { patch.add_statement(parent_end, s.kind.clone()); } ( - TransfromType::Discr, + TransfromKind::Cast, StatementKind::Assign(box (lhs, Rvalue::Use(Operand::Constant(f_c)))), ) => { let operand = Operand::Copy(Place::from(discr_local)); diff --git a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff index 1f20349fdece4..31ce51dc6de25 100644 --- a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff @@ -5,37 +5,42 @@ debug i => _1; let mut _0: u128; let mut _2: i128; ++ let mut _3: i128; bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [1: bb3, 2: bb4, 3: bb5, 340282366920938463463374607431768211455: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const core::num::::MAX; - goto -> bb6; - } - - bb3: { - _0 = const 1_u128; - goto -> bb6; - } - - bb4: { - _0 = const 2_u128; - goto -> bb6; - } - - bb5: { - _0 = const 3_u128; - goto -> bb6; - } - - bb6: { +- switchInt(move _2) -> [1: bb3, 2: bb4, 3: bb5, 340282366920938463463374607431768211455: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const core::num::::MAX; +- goto -> bb6; +- } +- +- bb3: { +- _0 = const 1_u128; +- goto -> bb6; +- } +- +- bb4: { +- _0 = const 2_u128; +- goto -> bb6; +- } +- +- bb5: { +- _0 = const 3_u128; +- goto -> bb6; +- } +- +- bb6: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u128 (IntToInt); ++ StorageDead(_3); return; } } diff --git a/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff index 4b435310916a7..e1b537b1b7190 100644 --- a/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff @@ -5,32 +5,37 @@ debug i => _1; let mut _0: i8; let mut _2: i16; ++ let mut _3: i16; bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [65535: bb3, 2: bb4, 65533: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const -3_i8; - goto -> bb5; - } - - bb3: { - _0 = const -1_i8; - goto -> bb5; - } - - bb4: { - _0 = const 2_i8; - goto -> bb5; - } - - bb5: { +- switchInt(move _2) -> [65535: bb3, 2: bb4, 65533: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const -3_i8; +- goto -> bb5; +- } +- +- bb3: { +- _0 = const -1_i8; +- goto -> bb5; +- } +- +- bb4: { +- _0 = const 2_i8; +- goto -> bb5; +- } +- +- bb5: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i8 (IntToInt); ++ StorageDead(_3); return; } } diff --git a/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff index 8a390736add15..cabc5a44cd81d 100644 --- a/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff @@ -5,32 +5,37 @@ debug i => _1; let mut _0: i16; let mut _2: i8; ++ let mut _3: i8; bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [255: bb3, 2: bb4, 253: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const -3_i16; - goto -> bb5; - } - - bb3: { - _0 = const -1_i16; - goto -> bb5; - } - - bb4: { - _0 = const 2_i16; - goto -> bb5; - } - - bb5: { +- switchInt(move _2) -> [255: bb3, 2: bb4, 253: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const -3_i16; +- goto -> bb5; +- } +- +- bb3: { +- _0 = const -1_i16; +- goto -> bb5; +- } +- +- bb4: { +- _0 = const 2_i16; +- goto -> bb5; +- } +- +- bb5: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i16 (IntToInt); ++ StorageDead(_3); return; } } diff --git a/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed_2.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..e2cdd95fdfe3e --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed_2.MatchBranchSimplification.diff @@ -0,0 +1,37 @@ +- // MIR for `match_i8_i16_failed_2` before MatchBranchSimplification ++ // MIR for `match_i8_i16_failed_2` after MatchBranchSimplification + + fn match_i8_i16_failed_2(_1: EnumAi8) -> i16 { + debug i => _1; + let mut _0: i16; + let mut _2: i8; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [255: bb3, 2: bb4, 253: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const -3_i16; + goto -> bb5; + } + + bb3: { + _0 = const 255_i16; + goto -> bb5; + } + + bb4: { + _0 = const 2_i16; + goto -> bb5; + } + + bb5: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff index 72ad60956ab78..9ee01a87a9132 100644 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff @@ -5,27 +5,32 @@ debug i => _1; let mut _0: i16; let mut _2: u8; ++ let mut _3: u8; bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 2_i16; - goto -> bb4; - } - - bb3: { - _0 = const 1_i16; - goto -> bb4; - } - - bb4: { +- switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 2_i16; +- goto -> bb4; +- } +- +- bb3: { +- _0 = const 1_i16; +- goto -> bb4; +- } +- +- bb4: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i16 (IntToInt); ++ StorageDead(_3); return; } } diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff index 043fdb197a3ac..aa9fcc60a3e13 100644 --- a/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff @@ -5,32 +5,37 @@ debug i => _1; let mut _0: u16; let mut _2: u8; ++ let mut _3: u8; bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [1: bb3, 2: bb4, 5: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 5_u16; - goto -> bb5; - } - - bb3: { - _0 = const 1_u16; - goto -> bb5; - } - - bb4: { - _0 = const 2_u16; - goto -> bb5; - } - - bb5: { +- switchInt(move _2) -> [1: bb3, 2: bb4, 5: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 5_u16; +- goto -> bb5; +- } +- +- bb3: { +- _0 = const 1_u16; +- goto -> bb5; +- } +- +- bb4: { +- _0 = const 2_u16; +- goto -> bb5; +- } +- +- bb5: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u16 (IntToInt); ++ StorageDead(_3); return; } } diff --git a/tests/mir-opt/matches_reduce_branches.rs b/tests/mir-opt/matches_reduce_branches.rs index 176d68bcd4019..df06dd028b94f 100644 --- a/tests/mir-opt/matches_reduce_branches.rs +++ b/tests/mir-opt/matches_reduce_branches.rs @@ -1,4 +1,5 @@ //@ test-mir-pass: MatchBranchSimplification +//@ compile-flags: -Zunsound-mir-opts #![feature(repr128)] #![feature(core_intrinsics)] @@ -75,7 +76,9 @@ enum EnumAu8 { // EMIT_MIR matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff fn match_u8_i16(i: EnumAu8) -> i16 { // CHECK-LABEL: fn match_u8_i16( - // CHECK: switchInt + // CHECK-NOT: switchInt + // CHECK: _0 = _3 as i16 (IntToInt); + // CHECH: return match i { EnumAu8::A => 1, EnumAu8::B => 2, @@ -144,7 +147,9 @@ enum EnumBu8 { // EMIT_MIR matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff fn match_u8_u16(i: EnumBu8) -> u16 { // CHECK-LABEL: fn match_u8_u16( - // CHECK: switchInt + // CHECK-NOT: switchInt + // CHECK: _0 = _3 as u16 (IntToInt); + // CHECH: return match i { EnumBu8::A => 1, EnumBu8::B => 2, @@ -200,7 +205,9 @@ enum EnumAi8 { // EMIT_MIR matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff fn match_i8_i16(i: EnumAi8) -> i16 { // CHECK-LABEL: fn match_i8_i16( - // CHECK: switchInt + // CHECK-NOT: switchInt + // CHECK: _0 = _3 as i16 (IntToInt); + // CHECH: return match i { EnumAi8::A => -1, EnumAi8::B => 2, @@ -226,10 +233,26 @@ enum EnumAi16 { C = -3, } +// We cannot transform it, even though `-1i8` and `255i16` are the same in terms of bits, +// what we actually require is that they are considered equal in a signed comparison, +// after sign-extending to the larger type. +// EMIT_MIR matches_reduce_branches.match_i8_i16_failed_2.MatchBranchSimplification.diff +fn match_i8_i16_failed_2(i: EnumAi8) -> i16 { + // CHECK-LABEL: fn match_i8_i16_failed_2( + // CHECK: switchInt + match i { + EnumAi8::A => 255, + EnumAi8::B => 2, + EnumAi8::C => -3, + } +} + // EMIT_MIR matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff fn match_i16_i8(i: EnumAi16) -> i8 { // CHECK-LABEL: fn match_i16_i8( - // CHECK: switchInt + // CHECK-NOT: switchInt + // CHECK: _0 = _3 as i8 (IntToInt); + // CHECH: return match i { EnumAi16::A => -1, EnumAi16::B => 2, @@ -248,7 +271,9 @@ enum EnumAi128 { // EMIT_MIR matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff fn match_i128_u128(i: EnumAi128) -> u128 { // CHECK-LABEL: fn match_i128_u128( - // CHECK: switchInt + // CHECK-NOT: switchInt + // CHECK: _0 = _3 as u128 (IntToInt); + // CHECH: return match i { EnumAi128::A => 1, EnumAi128::B => 2, @@ -270,6 +295,7 @@ fn main() { let _ = match_u8_u16_2(EnumBu8::A); let _ = match_i8_i16(EnumAi8::A); let _ = match_i8_i16_failed(EnumAi8::A); + let _ = match_i8_i16_failed_2(EnumAi8::A); let _ = match_i8_i16(EnumAi8::A); let _ = match_i16_i8(EnumAi16::A); let _ = match_i128_u128(EnumAi128::A); diff --git a/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff b/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff index 157f9c98353e7..11a18f58e3a1f 100644 --- a/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff @@ -5,27 +5,32 @@ debug e => _1; let mut _0: u8; let mut _2: isize; ++ let mut _3: isize; bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 1_u8; - goto -> bb4; - } - - bb3: { - _0 = const 0_u8; - goto -> bb4; - } - - bb4: { +- switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 1_u8; +- goto -> bb4; +- } +- +- bb3: { +- _0 = const 0_u8; +- goto -> bb4; +- } +- +- bb4: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u8 (IntToInt); ++ StorageDead(_3); return; } } diff --git a/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff index 19083771fd954..809badc41ba71 100644 --- a/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff @@ -5,27 +5,32 @@ debug e => _1; let mut _0: i8; let mut _2: isize; ++ let mut _3: isize; bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 1_i8; - goto -> bb4; - } - - bb3: { - _0 = const 0_i8; - goto -> bb4; - } - - bb4: { +- switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 1_i8; +- goto -> bb4; +- } +- +- bb3: { +- _0 = const 0_i8; +- goto -> bb4; +- } +- +- bb4: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i8 (IntToInt); ++ StorageDead(_3); return; } }