//@ test-mir-pass: MatchBranchSimplification #![feature(repr128)] #![feature(core_intrinsics)] #![feature(custom_mir)] #![allow(non_camel_case_types)] use std::intrinsics::mir::*; // EMIT_MIR matches_reduce_branches.foo.MatchBranchSimplification.diff fn foo(bar: Option<()>) { // CHECK-LABEL: fn foo( // CHECK: = Eq( // CHECK: switchInt // CHECK-NOT: switchInt // CHECK: return if matches!(bar, None) { () } } // EMIT_MIR matches_reduce_branches.bar.MatchBranchSimplification.diff fn bar(i: i32) -> (bool, bool, bool, bool) { // CHECK-LABEL: fn bar( // CHECK: = Ne( // CHECK: = Eq( // CHECK-NOT: switchInt // CHECK: return let a; let b; let c; let d; match i { 7 => { a = false; b = true; c = false; d = true; () } _ => { a = true; b = false; c = false; d = true; () } }; (a, b, c, d) } // EMIT_MIR matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff fn match_nested_if() -> bool { // CHECK-LABEL: fn match_nested_if( // CHECK-NOT: switchInt // CHECK: return let val = match () { () if if if if true { true } else { false } { true } else { false } { true } else { false } => { true } _ => false, }; val } // # Fold switchInt into IntToInt. // To simplify writing and checking these test cases, I use the first character of // each case to distinguish the sign of the number: // 'u' for unsigned, '_' for negative, and 'o' for non-negative. // Followed by a decimal number, and add the corresponding radix representation. // For example, o127_0x7f represents 127i8, and _1_0xff represents -1i8. // ## Cast but without numeric conversion. #[repr(u8)] enum EnumAu8 { u0_0x00 = 0, u127_0x7f = 127, u128_0x80 = 128, u255_0xff = 255, } #[repr(i8)] enum EnumAi8 { _128_0x80 = -128, _1_0xff = -1, o0_0x00 = 0, o1_0x01 = 1, o127_0x7f = 127, } // EMIT_MIR matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff fn match_u8_i8(i: EnumAu8) -> i8 { // CHECK-LABEL: fn match_u8_i8( // CHECK-NOT: switchInt // CHECK: return match i { EnumAu8::u0_0x00 => 0, EnumAu8::u127_0x7f => 127, EnumAu8::u128_0x80 => -128, EnumAu8::u255_0xff => -1, } } // EMIT_MIR matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff fn match_u8_i8_failed(i: EnumAu8) -> i8 { // CHECK-LABEL: fn match_u8_i8_failed( // CHECK: switchInt // CHECK: return match i { EnumAu8::u0_0x00 => 0, EnumAu8::u127_0x7f => 127, EnumAu8::u128_0x80 => -128, EnumAu8::u255_0xff => 1, // failed } } // EMIT_MIR matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff fn match_u8_i8_2(i: EnumAu8) -> (i8, i8) { // CHECK-LABEL: fn match_u8_i8_2( // CHECK-NOT: switchInt // CHECK: IntToInt // CHECK: IntToInt // CHECK: return let a: i8; let b: i8; match i { EnumAu8::u0_0x00 => { a = 0; b = 0; () } EnumAu8::u127_0x7f => { a = 127; b = 127; () } EnumAu8::u128_0x80 => { a = -128; b = -128; () } EnumAu8::u255_0xff => { a = -1; b = -1; () } }; (a, b) } // EMIT_MIR matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff fn match_u8_i8_2_failed(i: EnumAu8) -> (i8, i8) { // CHECK-LABEL: fn match_u8_i8_2_failed( // CHECK: switchInt // CHECK: return let a: i8; let b: i8; match i { EnumAu8::u0_0x00 => { a = 0; b = 0; () } EnumAu8::u127_0x7f => { a = 127; b = 127; () } EnumAu8::u128_0x80 => { a = -128; b = -128; () } EnumAu8::u255_0xff => { a = -1; b = 1; // failed () } }; (a, b) } // EMIT_MIR matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff fn match_u8_i8_fallback(i: EnumAu8) -> i8 { // CHECK-LABEL: fn match_u8_i8_fallback( // CHECK: switchInt // CHECK: return match i { EnumAu8::u0_0x00 => 0, EnumAu8::u127_0x7f => 127, EnumAu8::u128_0x80 => -128, _ => -1, } } // EMIT_MIR matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff // Check for different instruction lengths #[custom_mir(dialect = "built")] fn match_u8_i8_failed_len_1(i: EnumAu8) -> i8 { // CHECK-LABEL: fn match_u8_i8_failed_len_1( // CHECK: switchInt // CHECK: return mir! { { let a = Discriminant(i); match a { 0 => bb1, 127 => bb2, 128 => bb3, 255 => bb4, _ => unreachable_bb, } } bb1 = { RET = 0; Goto(ret) } bb2 = { RET = 127; RET = 127; Goto(ret) } bb3 = { RET = -128; Goto(ret) } bb4 = { RET = -1; Goto(ret) } unreachable_bb = { Unreachable() } ret = { Return() } } } // EMIT_MIR matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff // Check for different instruction lengths #[custom_mir(dialect = "built")] fn match_u8_i8_failed_len_2(i: EnumAu8) -> i8 { // CHECK-LABEL: fn match_u8_i8_failed_len_2( // CHECK: switchInt // CHECK: return mir! { { let a = Discriminant(i); match a { 0 => bb1, 127 => bb2, 128 => bb3, 255 => bb4, _ => unreachable_bb, } } bb1 = { RET = 0; Goto(ret) } bb2 = { RET = 127; Goto(ret) } bb3 = { RET = -128; Goto(ret) } bb4 = { RET = -1; RET = -1; Goto(ret) } unreachable_bb = { Unreachable() } ret = { Return() } } } // ## Cast with sext. // EMIT_MIR matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff fn match_sext_i8_i16(i: EnumAi8) -> i16 { // CHECK-LABEL: fn match_sext_i8_i16( // CHECK-NOT: switchInt // CHECK: return match i { EnumAi8::_128_0x80 => -128, EnumAi8::_1_0xff => -1, EnumAi8::o0_0x00 => 0, EnumAi8::o1_0x01 => 1, EnumAi8::o127_0x7f => 127, } } // EMIT_MIR matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff // Converting `-1i8` to `255i16` is zext. fn match_sext_i8_i16_failed(i: EnumAi8) -> i16 { // CHECK-LABEL: fn match_sext_i8_i16_failed( // CHECK: switchInt // CHECK: return match i { EnumAi8::_128_0x80 => -128, EnumAi8::_1_0xff => 255, // failed EnumAi8::o0_0x00 => 0, EnumAi8::o1_0x01 => 1, EnumAi8::o127_0x7f => 127, } } // EMIT_MIR matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff fn match_sext_i8_u16(i: EnumAi8) -> u16 { // CHECK-LABEL: fn match_sext_i8_u16( // CHECK-NOT: switchInt // CHECK: return match i { EnumAi8::_128_0x80 => 0xff80, EnumAi8::_1_0xff => 0xffff, EnumAi8::o0_0x00 => 0, EnumAi8::o1_0x01 => 1, EnumAi8::o127_0x7f => 127, } } // EMIT_MIR matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff // Converting `-1i8` to `255u16` is zext. fn match_sext_i8_u16_failed(i: EnumAi8) -> u16 { // CHECK-LABEL: fn match_sext_i8_u16_failed( // CHECK: switchInt // CHECK: return match i { EnumAi8::_128_0x80 => 0xff80, EnumAi8::_1_0xff => 0x00ff, // failed EnumAi8::o0_0x00 => 0, EnumAi8::o1_0x01 => 1, EnumAi8::o127_0x7f => 127, } } // ## Cast with zext. // EMIT_MIR matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff fn match_zext_u8_u16(i: EnumAu8) -> u16 { // CHECK-LABEL: fn match_zext_u8_u16( // CHECK-NOT: switchInt // CHECK: return match i { EnumAu8::u0_0x00 => 0, EnumAu8::u127_0x7f => 0x7f, EnumAu8::u128_0x80 => 128, EnumAu8::u255_0xff => 255, } } // EMIT_MIR matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff fn match_zext_u8_u16_failed(i: EnumAu8) -> u16 { // CHECK-LABEL: fn match_zext_u8_u16_failed( // CHECK: switchInt // CHECK: return match i { EnumAu8::u0_0x00 => 0, EnumAu8::u127_0x7f => 0xff7f, // failed EnumAu8::u128_0x80 => 128, EnumAu8::u255_0xff => 255, } } // EMIT_MIR matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff fn match_zext_u8_i16(i: EnumAu8) -> i16 { // CHECK-LABEL: fn match_zext_u8_i16( // CHECK-NOT: switchInt // CHECK: return match i { EnumAu8::u0_0x00 => 0, EnumAu8::u127_0x7f => 127, EnumAu8::u128_0x80 => 128, EnumAu8::u255_0xff => 255, } } // EMIT_MIR matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff fn match_zext_u8_i16_failed(i: EnumAu8) -> i16 { // CHECK-LABEL: fn match_zext_u8_i16_failed( // CHECK: switchInt // CHECK: return match i { EnumAu8::u0_0x00 => 0, EnumAu8::u127_0x7f => -127, // failed EnumAu8::u128_0x80 => 128, EnumAu8::u255_0xff => 255, } } // ## Cast with trunc. #[repr(u16)] enum EnumAu16 { // 0x00nn u0_0x0000 = 0, u127_0x007f = 127, u128_0x0080 = 128, u255_0x00ff = 255, // 0xffnn u65280_0xff00 = 65280, u65407_0xff7f = 65407, u65408_0xff80 = 65408, u65535_0xffff = 65535, } #[repr(i16)] enum EnumAi16 { // 0x00nn o128_0x0080 = 128, o255_0x00ff = 255, o0_0x0000 = 0, o1_0x0001 = 1, o127_0x007f = 127, // 0xffnn _128_0xff80 = -128, _1_0xffff = -1, o0_0xff00 = -256, o1_0xff01 = -255, o127_0xff7f = -129, } // EMIT_MIR matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff fn match_trunc_i16_i8(i: EnumAi16) -> i8 { // CHECK-LABEL: fn match_trunc_i16_i8( // CHECK-NOT: switchInt // CHECK: return match i { // 0x00nn EnumAi16::o128_0x0080 => -128, EnumAi16::o255_0x00ff => -1, EnumAi16::o0_0x0000 => 0, EnumAi16::o1_0x0001 => 1, EnumAi16::o127_0x007f => 127, // 0xffnn EnumAi16::_128_0xff80 => -128, EnumAi16::_1_0xffff => -1, EnumAi16::o0_0xff00 => 0, EnumAi16::o1_0xff01 => 1, EnumAi16::o127_0xff7f => 127, } } // EMIT_MIR matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff fn match_trunc_i16_i8_failed(i: EnumAi16) -> i8 { // CHECK-LABEL: fn match_trunc_i16_i8_failed( // CHECK: switchInt // CHECK: return match i { // 0x00nn EnumAi16::o128_0x0080 => -128, EnumAi16::o255_0x00ff => -1, EnumAi16::o0_0x0000 => 0, EnumAi16::o1_0x0001 => 1, EnumAi16::o127_0x007f => 127, // 0xffnn EnumAi16::_128_0xff80 => -128, EnumAi16::_1_0xffff => -1, EnumAi16::o0_0xff00 => 0, EnumAi16::o1_0xff01 => 1, EnumAi16::o127_0xff7f => -127, // failed } } // EMIT_MIR matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff fn match_trunc_i16_u8(i: EnumAi16) -> u8 { // CHECK-LABEL: fn match_trunc_i16_u8( // CHECK-NOT: switchInt // CHECK: return match i { // 0x00nn EnumAi16::o128_0x0080 => 128, EnumAi16::o255_0x00ff => 255, EnumAi16::o0_0x0000 => 0, EnumAi16::o1_0x0001 => 1, EnumAi16::o127_0x007f => 127, // 0xffnn EnumAi16::_128_0xff80 => 128, EnumAi16::_1_0xffff => 255, EnumAi16::o0_0xff00 => 0, EnumAi16::o1_0xff01 => 1, EnumAi16::o127_0xff7f => 127, } } // EMIT_MIR matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff fn match_trunc_i16_u8_failed(i: EnumAi16) -> u8 { // CHECK-LABEL: fn match_trunc_i16_u8_failed( // CHECK: switchInt // CHECK: return match i { // 0x00nn EnumAi16::o128_0x0080 => 128, EnumAi16::o255_0x00ff => 255, EnumAi16::o0_0x0000 => 0, EnumAi16::o1_0x0001 => 1, EnumAi16::o127_0x007f => 127, // 0xffnn EnumAi16::_128_0xff80 => 128, EnumAi16::_1_0xffff => 255, EnumAi16::o0_0xff00 => 0, EnumAi16::o1_0xff01 => 1, EnumAi16::o127_0xff7f => -127i8 as u8, // failed } } // EMIT_MIR matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff fn match_trunc_u16_u8(i: EnumAu16) -> u8 { // CHECK-LABEL: fn match_trunc_u16_u8( // CHECK-NOT: switchInt // CHECK: return match i { // 0x00nn EnumAu16::u0_0x0000 => 0, EnumAu16::u127_0x007f => 127, EnumAu16::u128_0x0080 => 128, EnumAu16::u255_0x00ff => 255, // 0xffnn EnumAu16::u65280_0xff00 => 0, EnumAu16::u65407_0xff7f => 127, EnumAu16::u65408_0xff80 => 128, EnumAu16::u65535_0xffff => 255, } } // EMIT_MIR matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff fn match_trunc_u16_u8_failed(i: EnumAu16) -> u8 { // CHECK-LABEL: fn match_trunc_u16_u8_failed( // CHECK: switchInt // CHECK: return match i { // 0x00nn EnumAu16::u0_0x0000 => 0, EnumAu16::u127_0x007f => 127, EnumAu16::u128_0x0080 => 128, EnumAu16::u255_0x00ff => 255, // 0xffnn EnumAu16::u65280_0xff00 => 0, EnumAu16::u65407_0xff7f => 127, EnumAu16::u65408_0xff80 => 128, EnumAu16::u65535_0xffff => 127, // failed } } // EMIT_MIR matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff fn match_trunc_u16_i8(i: EnumAu16) -> i8 { // CHECK-LABEL: fn match_trunc_u16_i8( // CHECK-NOT: switchInt // CHECK: return match i { // 0x00nn EnumAu16::u0_0x0000 => 0, EnumAu16::u127_0x007f => 127, EnumAu16::u128_0x0080 => -128, EnumAu16::u255_0x00ff => -1, // 0xffnn EnumAu16::u65280_0xff00 => 0, EnumAu16::u65407_0xff7f => 127, EnumAu16::u65408_0xff80 => -128, EnumAu16::u65535_0xffff => -1, } } // EMIT_MIR matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff fn match_trunc_u16_i8_failed(i: EnumAu16) -> i8 { // CHECK-LABEL: fn match_trunc_u16_i8_failed( // CHECK: switchInt // CHECK: return match i { // 0x00nn EnumAu16::u0_0x0000 => 0, EnumAu16::u127_0x007f => 127, EnumAu16::u128_0x0080 => -128, EnumAu16::u255_0x00ff => -1, // 0xffnn EnumAu16::u65280_0xff00 => 0, EnumAu16::u65407_0xff7f => 127, EnumAu16::u65408_0xff80 => -128, EnumAu16::u65535_0xffff => 1, } } #[repr(i128)] enum EnumAi128 { A = 1, B = 2, C = 3, D = -1, } // EMIT_MIR matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff fn match_i128_u128(i: EnumAi128) -> u128 { // CHECK-LABEL: fn match_i128_u128( // CHECK-NOT: switchInt // CHECK: return match i { EnumAi128::A => 1, EnumAi128::B => 2, EnumAi128::C => 3, EnumAi128::D => u128::MAX, } } fn main() { let _ = foo(None); let _ = foo(Some(())); let _ = bar(0); let _ = match_nested_if(); let _: i8 = match_u8_i8(EnumAu8::u0_0x00); let _: i8 = match_u8_i8_failed(EnumAu8::u0_0x00); let _: (i8, i8) = match_u8_i8_2(EnumAu8::u0_0x00); let _: (i8, i8) = match_u8_i8_2_failed(EnumAu8::u0_0x00); let _: i8 = match_u8_i8_fallback(EnumAu8::u0_0x00); let _: i8 = match_u8_i8_failed_len_1(EnumAu8::u0_0x00); let _: i8 = match_u8_i8_failed_len_2(EnumAu8::u0_0x00); let _: i16 = match_sext_i8_i16(EnumAi8::o0_0x00); let _: i16 = match_sext_i8_i16_failed(EnumAi8::o0_0x00); let _: u16 = match_sext_i8_u16(EnumAi8::o0_0x00); let _: u16 = match_sext_i8_u16_failed(EnumAi8::o0_0x00); let _: u16 = match_zext_u8_u16(EnumAu8::u0_0x00); let _: u16 = match_zext_u8_u16_failed(EnumAu8::u0_0x00); let _: i16 = match_zext_u8_i16(EnumAu8::u0_0x00); let _: i16 = match_zext_u8_i16_failed(EnumAu8::u0_0x00); let _: i8 = match_trunc_i16_i8(EnumAi16::o0_0x0000); let _: i8 = match_trunc_i16_i8_failed(EnumAi16::o0_0x0000); let _: u8 = match_trunc_i16_u8(EnumAi16::o0_0x0000); let _: u8 = match_trunc_i16_u8_failed(EnumAi16::o0_0x0000); let _: i8 = match_trunc_u16_i8(EnumAu16::u0_0x0000); let _: i8 = match_trunc_u16_i8_failed(EnumAu16::u0_0x0000); let _: u8 = match_trunc_u16_u8(EnumAu16::u0_0x0000); let _: u8 = match_trunc_u16_u8_failed(EnumAu16::u0_0x0000); let _ = match_i128_u128(EnumAi128::A); }