diff options
Diffstat (limited to 'tests')
15 files changed, 563 insertions, 159 deletions
diff --git a/tests/codegen/enum/enum-early-otherwise-branch.rs b/tests/codegen/enum/enum-early-otherwise-branch.rs new file mode 100644 index 00000000000..6c7548912da --- /dev/null +++ b/tests/codegen/enum/enum-early-otherwise-branch.rs @@ -0,0 +1,26 @@ +//@ compile-flags: -O +//@ min-llvm-version: 18 + +#![crate_type = "lib"] + +pub enum Enum { + A(u32), + B(u32), + C(u32), +} + +#[no_mangle] +pub fn foo(lhs: &Enum, rhs: &Enum) -> bool { + // CHECK-LABEL: define{{.*}}i1 @foo( + // CHECK-NOT: switch + // CHECK-NOT: br + // CHECK: [[SELECT:%.*]] = select + // CHECK-NEXT: ret i1 [[SELECT]] + // CHECK-NEXT: } + match (lhs, rhs) { + (Enum::A(lhs), Enum::A(rhs)) => lhs == rhs, + (Enum::B(lhs), Enum::B(rhs)) => lhs == rhs, + (Enum::C(lhs), Enum::C(rhs)) => lhs == rhs, + _ => false, + } +} diff --git a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff index 7a374c5675a..4af3ed3e1d1 100644 --- a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff @@ -12,8 +12,6 @@ let mut _7: isize; let _8: u32; let _9: u32; -+ let mut _10: isize; -+ let mut _11: bool; scope 1 { debug a => _8; debug b => _9; @@ -29,28 +27,20 @@ StorageDead(_5); StorageDead(_4); _7 = discriminant((_3.0: std::option::Option<u32>)); -- switchInt(move _7) -> [1: bb2, otherwise: bb1]; -+ StorageLive(_10); -+ _10 = discriminant((_3.1: std::option::Option<u32>)); -+ StorageLive(_11); -+ _11 = Ne(_7, move _10); -+ StorageDead(_10); -+ switchInt(move _11) -> [0: bb4, otherwise: bb1]; + switchInt(move _7) -> [1: bb2, 0: bb1, otherwise: bb5]; } bb1: { -+ StorageDead(_11); _0 = const 1_u32; -- goto -> bb4; -+ goto -> bb3; + goto -> bb4; } bb2: { -- _6 = discriminant((_3.1: std::option::Option<u32>)); -- switchInt(move _6) -> [1: bb3, otherwise: bb1]; -- } -- -- bb3: { + _6 = discriminant((_3.1: std::option::Option<u32>)); + switchInt(move _6) -> [1: bb3, 0: bb1, otherwise: bb5]; + } + + bb3: { StorageLive(_8); _8 = (((_3.0: std::option::Option<u32>) as Some).0: u32); StorageLive(_9); @@ -58,19 +48,16 @@ _0 = const 0_u32; StorageDead(_9); StorageDead(_8); -- goto -> bb4; -+ goto -> bb3; + goto -> bb4; } -- bb4: { -+ bb3: { + bb4: { StorageDead(_3); return; -+ } -+ -+ bb4: { -+ StorageDead(_11); -+ switchInt(_7) -> [1: bb2, otherwise: bb1]; + } + + bb5: { + unreachable; } } diff --git a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff index 1348bdd739a..7776ff0fde7 100644 --- a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff @@ -13,8 +13,6 @@ let mut _8: isize; let _9: u32; let _10: u32; -+ let mut _11: isize; -+ let mut _12: bool; scope 1 { debug a => _9; debug b => _10; @@ -30,33 +28,25 @@ StorageDead(_5); StorageDead(_4); _8 = discriminant((_3.0: std::option::Option<u32>)); -- switchInt(move _8) -> [0: bb3, 1: bb2, otherwise: bb1]; -+ StorageLive(_11); -+ _11 = discriminant((_3.1: std::option::Option<u32>)); -+ StorageLive(_12); -+ _12 = Ne(_8, move _11); -+ StorageDead(_11); -+ switchInt(move _12) -> [0: bb5, otherwise: bb1]; + switchInt(move _8) -> [0: bb3, 1: bb2, otherwise: bb7]; } bb1: { -+ StorageDead(_12); _0 = const 1_u32; -- goto -> bb6; -+ goto -> bb4; + goto -> bb6; } bb2: { -- _6 = discriminant((_3.1: std::option::Option<u32>)); -- switchInt(move _6) -> [1: bb4, otherwise: bb1]; -- } -- -- bb3: { -- _7 = discriminant((_3.1: std::option::Option<u32>)); -- switchInt(move _7) -> [0: bb5, otherwise: bb1]; -- } -- -- bb4: { + _6 = discriminant((_3.1: std::option::Option<u32>)); + switchInt(move _6) -> [1: bb4, 0: bb1, otherwise: bb7]; + } + + bb3: { + _7 = discriminant((_3.1: std::option::Option<u32>)); + switchInt(move _7) -> [0: bb5, 1: bb1, otherwise: bb7]; + } + + bb4: { StorageLive(_9); _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); StorageLive(_10); @@ -64,26 +54,21 @@ _0 = const 0_u32; StorageDead(_10); StorageDead(_9); -- goto -> bb6; -+ goto -> bb4; + goto -> bb6; } -- bb5: { -+ bb3: { - _0 = const 0_u32; -- goto -> bb6; -+ goto -> bb4; + bb5: { + _0 = const 2_u32; + goto -> bb6; } -- bb6: { -+ bb4: { + bb6: { StorageDead(_3); return; -+ } -+ -+ bb5: { -+ StorageDead(_12); -+ switchInt(_8) -> [0: bb3, 1: bb2, otherwise: bb1]; + } + + bb7: { + unreachable; } } diff --git a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff index e058c409cb5..b41e952d80f 100644 --- a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff @@ -1,76 +1,107 @@ - // MIR for `opt3` before EarlyOtherwiseBranch + // MIR for `opt3` after EarlyOtherwiseBranch - fn opt3(_1: Option<u32>, _2: Option<bool>) -> u32 { + fn opt3(_1: Option2<u32>, _2: Option2<bool>) -> u32 { debug x => _1; debug y => _2; let mut _0: u32; - let mut _3: (std::option::Option<u32>, std::option::Option<bool>); - let mut _4: std::option::Option<u32>; - let mut _5: std::option::Option<bool>; + let mut _3: (Option2<u32>, Option2<bool>); + let mut _4: Option2<u32>; + let mut _5: Option2<bool>; let mut _6: isize; let mut _7: isize; - let _8: u32; - let _9: bool; -+ let mut _10: isize; -+ let mut _11: bool; + let mut _8: isize; + let mut _9: isize; + let _10: u32; + let _11: bool; ++ let mut _12: isize; ++ let mut _13: bool; scope 1 { - debug a => _8; - debug b => _9; + debug a => _10; + debug b => _11; } bb0: { StorageLive(_3); StorageLive(_4); - _4 = _1; + _4 = move _1; StorageLive(_5); - _5 = _2; + _5 = move _2; _3 = (move _4, move _5); StorageDead(_5); StorageDead(_4); - _7 = discriminant((_3.0: std::option::Option<u32>)); -- switchInt(move _7) -> [1: bb2, otherwise: bb1]; -+ StorageLive(_10); -+ _10 = discriminant((_3.1: std::option::Option<bool>)); -+ StorageLive(_11); -+ _11 = Ne(_7, move _10); -+ StorageDead(_10); -+ switchInt(move _11) -> [0: bb4, otherwise: bb1]; + _9 = discriminant((_3.0: Option2<u32>)); +- switchInt(move _9) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb9]; ++ StorageLive(_12); ++ _12 = discriminant((_3.1: Option2<bool>)); ++ StorageLive(_13); ++ _13 = Ne(_9, move _12); ++ StorageDead(_12); ++ switchInt(move _13) -> [0: bb7, otherwise: bb1]; } bb1: { -+ StorageDead(_11); ++ StorageDead(_13); _0 = const 1_u32; -- goto -> bb4; -+ goto -> bb3; +- goto -> bb8; ++ goto -> bb5; } bb2: { -- _6 = discriminant((_3.1: std::option::Option<bool>)); -- switchInt(move _6) -> [1: bb3, otherwise: bb1]; +- _6 = discriminant((_3.1: Option2<bool>)); +- switchInt(move _6) -> [0: bb5, otherwise: bb1]; - } - - bb3: { - StorageLive(_8); - _8 = (((_3.0: std::option::Option<u32>) as Some).0: u32); - StorageLive(_9); - _9 = (((_3.1: std::option::Option<bool>) as Some).0: bool); +- _7 = discriminant((_3.1: Option2<bool>)); +- switchInt(move _7) -> [1: bb6, otherwise: bb1]; +- } +- +- bb4: { +- _8 = discriminant((_3.1: Option2<bool>)); +- switchInt(move _8) -> [2: bb7, otherwise: bb1]; +- } +- +- bb5: { + StorageLive(_10); + _10 = (((_3.0: Option2<u32>) as Some).0: u32); + StorageLive(_11); + _11 = (((_3.1: Option2<bool>) as Some).0: bool); _0 = const 0_u32; - StorageDead(_9); - StorageDead(_8); -- goto -> bb4; -+ goto -> bb3; + StorageDead(_11); + StorageDead(_10); +- goto -> bb8; ++ goto -> bb5; } -- bb4: { +- bb6: { + bb3: { + _0 = const 2_u32; +- goto -> bb8; ++ goto -> bb5; + } + +- bb7: { ++ bb4: { + _0 = const 3_u32; +- goto -> bb8; ++ goto -> bb5; + } + +- bb8: { ++ bb5: { StorageDead(_3); return; + } + +- bb9: { ++ bb6: { + unreachable; + } + -+ bb4: { -+ StorageDead(_11); -+ switchInt(_7) -> [1: bb2, otherwise: bb1]; ++ bb7: { ++ StorageDead(_13); ++ switchInt(_9) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb6]; } } diff --git a/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff new file mode 100644 index 00000000000..18dea56f430 --- /dev/null +++ b/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff @@ -0,0 +1,107 @@ +- // MIR for `opt4` before EarlyOtherwiseBranch ++ // MIR for `opt4` after EarlyOtherwiseBranch + + fn opt4(_1: Option2<u32>, _2: Option2<u32>) -> u32 { + debug x => _1; + debug y => _2; + let mut _0: u32; + let mut _3: (Option2<u32>, Option2<u32>); + let mut _4: Option2<u32>; + let mut _5: Option2<u32>; + let mut _6: isize; + let mut _7: isize; + let mut _8: isize; + let mut _9: isize; + let _10: u32; + let _11: u32; ++ let mut _12: isize; ++ let mut _13: bool; + scope 1 { + debug a => _10; + debug b => _11; + } + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = move _1; + StorageLive(_5); + _5 = move _2; + _3 = (move _4, move _5); + StorageDead(_5); + StorageDead(_4); + _9 = discriminant((_3.0: Option2<u32>)); +- switchInt(move _9) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb9]; ++ StorageLive(_12); ++ _12 = discriminant((_3.1: Option2<u32>)); ++ StorageLive(_13); ++ _13 = Ne(_9, move _12); ++ StorageDead(_12); ++ switchInt(move _13) -> [0: bb7, otherwise: bb1]; + } + + bb1: { ++ StorageDead(_13); + _0 = const 1_u32; +- goto -> bb8; ++ goto -> bb5; + } + + bb2: { +- _6 = discriminant((_3.1: Option2<u32>)); +- switchInt(move _6) -> [0: bb5, otherwise: bb1]; +- } +- +- bb3: { +- _7 = discriminant((_3.1: Option2<u32>)); +- switchInt(move _7) -> [1: bb6, otherwise: bb1]; +- } +- +- bb4: { +- _8 = discriminant((_3.1: Option2<u32>)); +- switchInt(move _8) -> [2: bb7, otherwise: bb1]; +- } +- +- bb5: { + StorageLive(_10); + _10 = (((_3.0: Option2<u32>) as Some).0: u32); + StorageLive(_11); + _11 = (((_3.1: Option2<u32>) as Some).0: u32); + _0 = const 0_u32; + StorageDead(_11); + StorageDead(_10); +- goto -> bb8; ++ goto -> bb5; + } + +- bb6: { ++ bb3: { + _0 = const 2_u32; +- goto -> bb8; ++ goto -> bb5; + } + +- bb7: { ++ bb4: { + _0 = const 3_u32; +- goto -> bb8; ++ goto -> bb5; + } + +- bb8: { ++ bb5: { + StorageDead(_3); + return; + } + +- bb9: { ++ bb6: { + unreachable; ++ } ++ ++ bb7: { ++ StorageDead(_13); ++ switchInt(_9) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb6]; + } + } + diff --git a/tests/mir-opt/early_otherwise_branch.rs b/tests/mir-opt/early_otherwise_branch.rs index c984c271ccd..bfeb1f7bbc6 100644 --- a/tests/mir-opt/early_otherwise_branch.rs +++ b/tests/mir-opt/early_otherwise_branch.rs @@ -1,27 +1,79 @@ -// skip-filecheck //@ unit-test: EarlyOtherwiseBranch +//@ compile-flags: -Zmir-enable-passes=+UnreachableEnumBranching + +enum Option2<T> { + Some(T), + None, + Other, +} + +// We can't optimize it because y may be an invalid value. // EMIT_MIR early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff fn opt1(x: Option<u32>, y: Option<u32>) -> u32 { + // CHECK-LABEL: fn opt1( + // CHECK: bb0: { + // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}}); + // CHECK-NOT: Ne + // CHECK-NOT: discriminant + // CHECK: switchInt(move [[LOCAL1]]) -> [ + // CHECK-NEXT: } match (x, y) { (Some(a), Some(b)) => 0, _ => 1, } } +// FIXME: `switchInt` will have three targets after `UnreachableEnumBranching`, +// otherwise is unreachable. We can consume the UB fact to transform back to if else pattern. // EMIT_MIR early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff fn opt2(x: Option<u32>, y: Option<u32>) -> u32 { + // CHECK-LABEL: fn opt2( + // CHECK: bb0: { + // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}}); + // CHECK-NOT: Ne + // CHECK-NOT: discriminant + // CHECK: switchInt(move [[LOCAL1]]) -> [ + // CHECK-NEXT: } match (x, y) { (Some(a), Some(b)) => 0, - (None, None) => 0, + (None, None) => 2, _ => 1, } } // optimize despite different types // EMIT_MIR early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff -fn opt3(x: Option<u32>, y: Option<bool>) -> u32 { +fn opt3(x: Option2<u32>, y: Option2<bool>) -> u32 { + // CHECK-LABEL: fn opt3( + // CHECK: let mut [[CMP_LOCAL:_.*]]: bool; + // CHECK: bb0: { + // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}}); + // CHECK: [[LOCAL2:_.*]] = discriminant({{.*}}); + // CHECK: [[CMP_LOCAL]] = Ne([[LOCAL1]], move [[LOCAL2]]); + // CHECK: switchInt(move [[CMP_LOCAL]]) -> [ + // CHECK-NEXT: } match (x, y) { - (Some(a), Some(b)) => 0, + (Option2::Some(a), Option2::Some(b)) => 0, + (Option2::None, Option2::None) => 2, + (Option2::Other, Option2::Other) => 3, + _ => 1, + } +} + +// EMIT_MIR early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff +fn opt4(x: Option2<u32>, y: Option2<u32>) -> u32 { + // CHECK-LABEL: fn opt4( + // CHECK: let mut [[CMP_LOCAL:_.*]]: bool; + // CHECK: bb0: { + // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}}); + // CHECK: [[LOCAL2:_.*]] = discriminant({{.*}}); + // CHECK: [[CMP_LOCAL]] = Ne([[LOCAL1]], move [[LOCAL2]]); + // CHECK: switchInt(move [[CMP_LOCAL]]) -> [ + // CHECK-NEXT: } + match (x, y) { + (Option2::Some(a), Option2::Some(b)) => 0, + (Option2::None, Option2::None) => 2, + (Option2::Other, Option2::Other) => 3, _ => 1, } } @@ -29,5 +81,6 @@ fn opt3(x: Option<u32>, y: Option<bool>) -> u32 { fn main() { opt1(None, Some(0)); opt2(None, Some(0)); - opt3(None, Some(false)); + opt3(Option2::None, Option2::Some(false)); + opt4(Option2::None, Option2::Some(0)); } diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff index f98d68e6ffc..4c3c717b522 100644 --- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff @@ -13,17 +13,15 @@ let mut _8: isize; let mut _9: isize; let mut _10: isize; - let _11: u32; - let _12: u32; + let mut _11: isize; + let mut _12: isize; let _13: u32; -+ let mut _14: isize; -+ let mut _15: bool; -+ let mut _16: isize; -+ let mut _17: bool; + let _14: u32; + let _15: u32; scope 1 { - debug a => _11; - debug b => _12; - debug c => _13; + debug a => _13; + debug b => _14; + debug c => _15; } bb0: { @@ -38,60 +36,61 @@ StorageDead(_7); StorageDead(_6); StorageDead(_5); - _10 = discriminant((_4.0: std::option::Option<u32>)); -- switchInt(move _10) -> [1: bb2, otherwise: bb1]; -+ StorageLive(_14); -+ _14 = discriminant((_4.1: std::option::Option<u32>)); -+ StorageLive(_15); -+ _15 = Ne(_10, move _14); -+ StorageDead(_14); -+ switchInt(move _15) -> [0: bb5, otherwise: bb1]; + _12 = discriminant((_4.0: std::option::Option<u32>)); + switchInt(move _12) -> [0: bb4, 1: bb2, otherwise: bb9]; } bb1: { -+ StorageDead(_17); -+ StorageDead(_15); _0 = const 1_u32; -- goto -> bb5; -+ goto -> bb4; + goto -> bb8; } bb2: { -- _9 = discriminant((_4.1: std::option::Option<u32>)); -- switchInt(move _9) -> [1: bb3, otherwise: bb1]; -- } -- -- bb3: { + _9 = discriminant((_4.1: std::option::Option<u32>)); + switchInt(move _9) -> [1: bb3, 0: bb1, otherwise: bb9]; + } + + bb3: { _8 = discriminant((_4.2: std::option::Option<u32>)); -- switchInt(move _8) -> [1: bb4, otherwise: bb1]; -+ switchInt(move _8) -> [1: bb3, otherwise: bb1]; + switchInt(move _8) -> [1: bb6, 0: bb1, otherwise: bb9]; + } + + bb4: { + _11 = discriminant((_4.1: std::option::Option<u32>)); + switchInt(move _11) -> [0: bb5, 1: bb1, otherwise: bb9]; + } + + bb5: { + _10 = discriminant((_4.2: std::option::Option<u32>)); + switchInt(move _10) -> [0: bb7, 1: bb1, otherwise: bb9]; } -- bb4: { -+ bb3: { - StorageLive(_11); - _11 = (((_4.0: std::option::Option<u32>) as Some).0: u32); - StorageLive(_12); - _12 = (((_4.1: std::option::Option<u32>) as Some).0: u32); + bb6: { StorageLive(_13); - _13 = (((_4.2: std::option::Option<u32>) as Some).0: u32); + _13 = (((_4.0: std::option::Option<u32>) as Some).0: u32); + StorageLive(_14); + _14 = (((_4.1: std::option::Option<u32>) as Some).0: u32); + StorageLive(_15); + _15 = (((_4.2: std::option::Option<u32>) as Some).0: u32); _0 = const 0_u32; + StorageDead(_15); + StorageDead(_14); StorageDead(_13); - StorageDead(_12); - StorageDead(_11); -- goto -> bb5; -+ goto -> bb4; + goto -> bb8; + } + + bb7: { + _0 = const 2_u32; + goto -> bb8; } -- bb5: { -+ bb4: { + bb8: { StorageDead(_4); return; -+ } -+ -+ bb5: { -+ StorageDead(_15); -+ switchInt(_10) -> [1: bb2, otherwise: bb1]; + } + + bb9: { + unreachable; } } diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff new file mode 100644 index 00000000000..0ea7a10baaa --- /dev/null +++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff @@ -0,0 +1,141 @@ +- // MIR for `opt2` before EarlyOtherwiseBranch ++ // MIR for `opt2` after EarlyOtherwiseBranch + + fn opt2(_1: Option2<u32>, _2: Option2<u32>, _3: Option2<u32>) -> u32 { + debug x => _1; + debug y => _2; + debug z => _3; + let mut _0: u32; + let mut _4: (Option2<u32>, Option2<u32>, Option2<u32>); + let mut _5: Option2<u32>; + let mut _6: Option2<u32>; + let mut _7: Option2<u32>; + let mut _8: isize; + let mut _9: isize; + let mut _10: isize; + let mut _11: isize; + let mut _12: isize; + let mut _13: isize; + let mut _14: isize; + let _15: u32; + let _16: u32; + let _17: u32; ++ let mut _18: isize; ++ let mut _19: bool; + scope 1 { + debug a => _15; + debug b => _16; + debug c => _17; + } + + bb0: { + StorageLive(_4); + StorageLive(_5); + _5 = move _1; + StorageLive(_6); + _6 = move _2; + StorageLive(_7); + _7 = move _3; + _4 = (move _5, move _6, move _7); + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); + _14 = discriminant((_4.0: Option2<u32>)); +- switchInt(move _14) -> [0: bb2, 1: bb4, 2: bb6, otherwise: bb12]; ++ StorageLive(_18); ++ _18 = discriminant((_4.1: Option2<u32>)); ++ StorageLive(_19); ++ _19 = Ne(_14, move _18); ++ StorageDead(_18); ++ switchInt(move _19) -> [0: bb10, otherwise: bb1]; + } + + bb1: { ++ StorageDead(_19); + _0 = const 1_u32; +- goto -> bb11; ++ goto -> bb8; + } + + bb2: { +- _9 = discriminant((_4.1: Option2<u32>)); +- switchInt(move _9) -> [0: bb3, otherwise: bb1]; +- } +- +- bb3: { + _8 = discriminant((_4.2: Option2<u32>)); +- switchInt(move _8) -> [0: bb8, otherwise: bb1]; ++ switchInt(move _8) -> [0: bb5, otherwise: bb1]; + } + +- bb4: { +- _11 = discriminant((_4.1: Option2<u32>)); +- switchInt(move _11) -> [1: bb5, otherwise: bb1]; +- } +- +- bb5: { ++ bb3: { + _10 = discriminant((_4.2: Option2<u32>)); +- switchInt(move _10) -> [1: bb9, otherwise: bb1]; ++ switchInt(move _10) -> [1: bb6, otherwise: bb1]; + } + +- bb6: { +- _13 = discriminant((_4.1: Option2<u32>)); +- switchInt(move _13) -> [2: bb7, otherwise: bb1]; +- } +- +- bb7: { ++ bb4: { + _12 = discriminant((_4.2: Option2<u32>)); +- switchInt(move _12) -> [2: bb10, otherwise: bb1]; ++ switchInt(move _12) -> [2: bb7, otherwise: bb1]; + } + +- bb8: { ++ bb5: { + StorageLive(_15); + _15 = (((_4.0: Option2<u32>) as Some).0: u32); + StorageLive(_16); + _16 = (((_4.1: Option2<u32>) as Some).0: u32); + StorageLive(_17); + _17 = (((_4.2: Option2<u32>) as Some).0: u32); + _0 = const 0_u32; + StorageDead(_17); + StorageDead(_16); + StorageDead(_15); +- goto -> bb11; ++ goto -> bb8; + } + +- bb9: { ++ bb6: { + _0 = const 2_u32; +- goto -> bb11; ++ goto -> bb8; + } + +- bb10: { ++ bb7: { + _0 = const 3_u32; +- goto -> bb11; ++ goto -> bb8; + } + +- bb11: { ++ bb8: { + StorageDead(_4); + return; + } + +- bb12: { ++ bb9: { + unreachable; ++ } ++ ++ bb10: { ++ StorageDead(_19); ++ switchInt(_14) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb9]; + } + } + diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.rs b/tests/mir-opt/early_otherwise_branch_3_element_tuple.rs index 32081347558..2d215621bbd 100644 --- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.rs +++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.rs @@ -1,14 +1,49 @@ -// skip-filecheck //@ unit-test: EarlyOtherwiseBranch +//@ compile-flags: -Zmir-enable-passes=+UnreachableEnumBranching +enum Option2<T> { + Some(T), + None, + Other, +} + +// FIXME: `switchInt` will have three targets after `UnreachableEnumBranching`, +// otherwise is unreachable. We can consume the UB fact to transform back to if else pattern. // EMIT_MIR early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff fn opt1(x: Option<u32>, y: Option<u32>, z: Option<u32>) -> u32 { + // CHECK-LABEL: fn opt1( + // CHECK: bb0: { + // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}}); + // CHECK-NOT: Ne + // CHECK-NOT: discriminant + // CHECK: switchInt(move [[LOCAL1]]) -> [ + // CHECK-NEXT: } match (x, y, z) { (Some(a), Some(b), Some(c)) => 0, + (None, None, None) => 2, + _ => 1, + } +} + +// EMIT_MIR early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff +fn opt2(x: Option2<u32>, y: Option2<u32>, z: Option2<u32>) -> u32 { + // CHECK-LABEL: fn opt2( + // CHECK: let mut [[CMP_LOCAL:_.*]]: bool; + // CHECK: bb0: { + // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}}); + // CHECK: [[LOCAL2:_.*]] = discriminant({{.*}}); + // CHECK: [[CMP_LOCAL]] = Ne([[LOCAL1]], move [[LOCAL2]]); + // CHECK: switchInt(move [[CMP_LOCAL]]) -> [ + // CHECK-NEXT: } + match (x, y, z) { + (Option2::Some(a), Option2::Some(b), Option2::Some(c)) => 0, + (Option2::None, Option2::None, Option2::None) => 2, + (Option2::Other, Option2::Other, Option2::Other) => 3, _ => 1, } } fn main() { opt1(None, Some(0), None); + opt2(Option2::None, Option2::Some(0), Option2::None); } diff --git a/tests/mir-opt/early_otherwise_branch_68867.rs b/tests/mir-opt/early_otherwise_branch_68867.rs index 805d21533c5..59bc19ceecc 100644 --- a/tests/mir-opt/early_otherwise_branch_68867.rs +++ b/tests/mir-opt/early_otherwise_branch_68867.rs @@ -1,5 +1,5 @@ -// skip-filecheck //@ unit-test: EarlyOtherwiseBranch +//@ compile-flags: -Zmir-enable-passes=+UnreachableEnumBranching // FIXME: This test was broken by the derefer change. @@ -19,6 +19,13 @@ pub extern "C" fn try_sum( x: &ViewportPercentageLength, other: &ViewportPercentageLength, ) -> Result<ViewportPercentageLength, ()> { + // CHECK-LABEL: fn try_sum( + // CHECK: bb0: { + // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}}); + // CHECK-NOT: Ne + // CHECK-NOT: discriminant + // CHECK: switchInt(move [[LOCAL1]]) -> [ + // CHECK-NEXT: } use self::ViewportPercentageLength::*; Ok(match (x, other) { (&Vw(one), &Vw(other)) => Vw(one + other), diff --git a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff index a5b5659a31a..de12fe8f120 100644 --- a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff @@ -78,7 +78,7 @@ StorageDead(_5); _34 = deref_copy (_4.0: &ViewportPercentageLength); _11 = discriminant((*_34)); - switchInt(move _11) -> [0: bb2, 1: bb3, 2: bb4, 3: bb5, otherwise: bb1]; + switchInt(move _11) -> [0: bb2, 1: bb3, 2: bb4, 3: bb5, otherwise: bb12]; } bb1: { @@ -213,5 +213,9 @@ bb11: { return; } + + bb12: { + unreachable; + } } diff --git a/tests/mir-opt/early_otherwise_branch_noopt.rs b/tests/mir-opt/early_otherwise_branch_noopt.rs index 648089e2df1..6b48393e6b9 100644 --- a/tests/mir-opt/early_otherwise_branch_noopt.rs +++ b/tests/mir-opt/early_otherwise_branch_noopt.rs @@ -1,11 +1,18 @@ -// skip-filecheck //@ unit-test: EarlyOtherwiseBranch +//@ compile-flags: -Zmir-enable-passes=+UnreachableEnumBranching // must not optimize as it does not follow the pattern of // left and right hand side being the same variant // EMIT_MIR early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff fn noopt1(x: Option<u32>, y: Option<u32>) -> u32 { + // CHECK-LABEL: fn noopt1( + // CHECK: bb0: { + // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}}); + // CHECK-NOT: Ne + // CHECK-NOT: discriminant + // CHECK: switchInt(move [[LOCAL1]]) -> [ + // CHECK-NEXT: } match (x, y) { (Some(a), Some(b)) => 0, (Some(a), None) => 1, diff --git a/tests/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff index b24ff6ec74b..8eab59823f4 100644 --- a/tests/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff @@ -14,7 +14,7 @@ bb0: { _3 = discriminant(_1); - switchInt(move _3) -> [1: bb2, otherwise: bb1]; + switchInt(move _3) -> [1: bb2, 0: bb1, otherwise: bb6]; } bb1: { @@ -24,7 +24,7 @@ bb2: { _4 = discriminant((*_2)); - switchInt(move _4) -> [1: bb4, otherwise: bb3]; + switchInt(move _4) -> [1: bb4, 0: bb3, otherwise: bb6]; } bb3: { @@ -43,5 +43,9 @@ bb5: { return; } + + bb6: { + unreachable; + } } diff --git a/tests/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff index c3ea975ce03..6a4c947b882 100644 --- a/tests/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff @@ -12,13 +12,13 @@ bb0: { _3 = discriminant((*_1)); - switchInt(move _3) -> [1: bb1, otherwise: bb3]; + switchInt(move _3) -> [1: bb1, 0: bb3, otherwise: bb5]; } bb1: { _4 = deref_copy (((*_1) as Some).0: &E<'_>); _2 = discriminant((*_4)); - switchInt(move _2) -> [1: bb2, otherwise: bb3]; + switchInt(move _2) -> [1: bb2, 0: bb3, otherwise: bb5]; } bb2: { @@ -34,5 +34,9 @@ bb4: { return; } + + bb5: { + unreachable; + } } diff --git a/tests/mir-opt/early_otherwise_branch_soundness.rs b/tests/mir-opt/early_otherwise_branch_soundness.rs index b4f5821c420..74a2af884c0 100644 --- a/tests/mir-opt/early_otherwise_branch_soundness.rs +++ b/tests/mir-opt/early_otherwise_branch_soundness.rs @@ -1,5 +1,5 @@ -// skip-filecheck //@ unit-test: EarlyOtherwiseBranch +//@ compile-flags: -Zmir-enable-passes=+UnreachableEnumBranching // Tests various cases that the `early_otherwise_branch` opt should *not* optimize @@ -11,12 +11,26 @@ enum E<'a> { // EMIT_MIR early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff fn no_downcast(e: &E) -> u32 { + // CHECK-LABEL: fn no_downcast( + // CHECK: bb0: { + // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}}); + // CHECK-NOT: Ne + // CHECK-NOT: discriminant + // CHECK: switchInt(move [[LOCAL1]]) -> [ + // CHECK-NEXT: } if let E::Some(E::Some(_)) = e { 1 } else { 2 } } // SAFETY: if `a` is `Some`, `b` must point to a valid, initialized value // EMIT_MIR early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff unsafe fn no_deref_ptr(a: Option<i32>, b: *const Option<i32>) -> i32 { + // CHECK-LABEL: fn no_deref_ptr( + // CHECK: bb0: { + // CHECK: [[LOCAL1:_.*]] = discriminant({{.*}}); + // CHECK-NOT: Ne + // CHECK-NOT: discriminant + // CHECK: switchInt(move [[LOCAL1]]) -> [ + // CHECK-NEXT: } match a { // `*b` being correct depends on `a == Some(_)` Some(_) => match *b { |
