From cb918904fe693e93c679d4c3417cfe7776f8ebe2 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 24 Sep 2023 08:27:42 +0000 Subject: [PATCH] Only emit `!=` assumptions if the otherwise target is reachable. --- .../src/unreachable_prop.rs | 13 +++--- ...d.unwrap_unchecked.Inline.panic-abort.diff | 7 +-- ....unwrap_unchecked.Inline.panic-unwind.diff | 7 +-- ...unchecked.PreCodegen.after.panic-abort.mir | 15 +++---- ...nchecked.PreCodegen.after.panic-unwind.mir | 15 +++---- ...witch_targets.ub_if_b.PreCodegen.after.mir | 5 +-- ...ch.UnreachablePropagation.panic-abort.diff | 45 +++++++++++++++++++ ...h.UnreachablePropagation.panic-unwind.diff | 45 +++++++++++++++++++ ...t.UnreachablePropagation.panic-abort.diff} | 11 +++-- ....UnreachablePropagation.panic-unwind.diff} | 11 +++-- tests/mir-opt/unreachable.rs | 32 +++++++++++-- 11 files changed, 148 insertions(+), 58 deletions(-) create mode 100644 tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff create mode 100644 tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff rename tests/mir-opt/{unreachable.main.UnreachablePropagation.panic-abort.diff => unreachable.if_let.UnreachablePropagation.panic-abort.diff} (86%) rename tests/mir-opt/{unreachable.main.UnreachablePropagation.panic-unwind.diff => unreachable.if_let.UnreachablePropagation.panic-unwind.diff} (86%) diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index d25c6d471cd2a..919e8d6a2340f 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -116,22 +116,21 @@ fn remove_successors_from_switch<'tcx>( patch.add_statement(location, StatementKind::Intrinsic(Box::new(assume))); }; + let otherwise = targets.otherwise(); + let otherwise_unreachable = is_unreachable(otherwise); + let reachable_iter = targets.iter().filter(|&(value, bb)| { let is_unreachable = is_unreachable(bb); - if is_unreachable { - // We remove this target from the switch, so record the inequality using `Assume`. + // We remove this target from the switch, so record the inequality using `Assume`. + if is_unreachable && !otherwise_unreachable { add_assumption(BinOp::Ne, value); - false - } else { - true } + !is_unreachable }); - let otherwise = targets.otherwise(); let new_targets = SwitchTargets::new(reachable_iter, otherwise); let num_targets = new_targets.all_targets().len(); - let otherwise_unreachable = is_unreachable(otherwise); let fully_unreachable = num_targets == 1 && otherwise_unreachable; let terminator = match (num_targets, otherwise_unreachable) { diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff index 4ca7a2c4294ff..2a36ad9230e4b 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff @@ -10,7 +10,6 @@ + let mut _3: &std::option::Option; + let mut _4: isize; + let mut _5: bool; -+ let mut _6: bool; + scope 2 { + debug val => _0; + } @@ -37,14 +36,10 @@ + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); -+ StorageLive(_6); + _4 = discriminant(_2); -+ _5 = Ne(_4, const 0_isize); ++ _5 = Eq(_4, const 1_isize); + assume(move _5); -+ _6 = Eq(_4, const 1_isize); -+ assume(move _6); + _0 = move ((_2 as Some).0: T); -+ StorageDead(_6); + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff index caabb7ea46358..14c8c671d3fe2 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff @@ -10,7 +10,6 @@ + let mut _3: &std::option::Option; + let mut _4: isize; + let mut _5: bool; -+ let mut _6: bool; + scope 2 { + debug val => _0; + } @@ -37,14 +36,10 @@ + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); -+ StorageLive(_6); + _4 = discriminant(_2); -+ _5 = Ne(_4, const 0_isize); ++ _5 = Eq(_4, const 1_isize); + assume(move _5); -+ _6 = Eq(_4, const 1_isize); -+ assume(move _6); + _0 = move ((_2 as Some).0: T); -+ StorageDead(_6); + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir index 521266925e0d4..aeb93bd334fe6 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir @@ -7,8 +7,7 @@ fn unwrap_unchecked(_1: Option) -> T { debug self => _1; let mut _2: isize; let mut _3: bool; - let mut _4: bool; - let mut _5: &std::option::Option; + let mut _4: &std::option::Option; scope 2 { debug val => _0; } @@ -21,25 +20,21 @@ fn unwrap_unchecked(_1: Option) -> T { } } scope 4 (inlined Option::::is_some) { - debug self => _5; + debug self => _4; } } bb0: { - StorageLive(_5); + StorageLive(_4); StorageLive(_2); StorageLive(_3); - StorageLive(_4); _2 = discriminant(_1); - _3 = Ne(_2, const 0_isize); + _3 = Eq(_2, const 1_isize); assume(move _3); - _4 = Eq(_2, const 1_isize); - assume(move _4); _0 = move ((_1 as Some).0: T); - StorageDead(_4); StorageDead(_3); StorageDead(_2); - StorageDead(_5); + StorageDead(_4); return; } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir index 521266925e0d4..aeb93bd334fe6 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir @@ -7,8 +7,7 @@ fn unwrap_unchecked(_1: Option) -> T { debug self => _1; let mut _2: isize; let mut _3: bool; - let mut _4: bool; - let mut _5: &std::option::Option; + let mut _4: &std::option::Option; scope 2 { debug val => _0; } @@ -21,25 +20,21 @@ fn unwrap_unchecked(_1: Option) -> T { } } scope 4 (inlined Option::::is_some) { - debug self => _5; + debug self => _4; } } bb0: { - StorageLive(_5); + StorageLive(_4); StorageLive(_2); StorageLive(_3); - StorageLive(_4); _2 = discriminant(_1); - _3 = Ne(_2, const 0_isize); + _3 = Eq(_2, const 1_isize); assume(move _3); - _4 = Eq(_2, const 1_isize); - assume(move _4); _0 = move ((_1 as Some).0: T); - StorageDead(_4); StorageDead(_3); StorageDead(_2); - StorageDead(_5); + StorageDead(_4); return; } } diff --git a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir index fe7beadc8188c..0114309dbb58e 100644 --- a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir @@ -5,7 +5,6 @@ fn ub_if_b(_1: Thing) -> Thing { let mut _0: Thing; let mut _2: isize; let mut _3: bool; - let mut _4: bool; scope 1 (inlined unreachable_unchecked) { scope 2 { scope 3 (inlined unreachable_unchecked::runtime) { @@ -15,10 +14,8 @@ fn ub_if_b(_1: Thing) -> Thing { bb0: { _2 = discriminant(_1); - _3 = Ne(_2, const 1_isize); + _3 = Eq(_2, const 0_isize); assume(move _3); - _4 = Eq(_2, const 0_isize); - assume(move _4); _0 = move _1; return; } diff --git a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff new file mode 100644 index 0000000000000..f6e594ffac765 --- /dev/null +++ b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff @@ -0,0 +1,45 @@ +- // MIR for `as_match` before UnreachablePropagation ++ // MIR for `as_match` after UnreachablePropagation + + fn as_match() -> () { + let mut _0: (); + let mut _1: std::option::Option; + let mut _2: isize; + let _3: Empty; + let mut _4: !; ++ let mut _5: bool; + scope 1 { + debug _x => _3; + } + + bb0: { + StorageLive(_1); + _1 = empty() -> [return: bb1, unwind unreachable]; + } + + bb1: { + _2 = discriminant(_1); +- switchInt(move _2) -> [0: bb4, 1: bb2, otherwise: bb3]; ++ _5 = Eq(_2, const 0_isize); ++ assume(move _5); ++ goto -> bb4; + } + + bb2: { +- StorageLive(_3); +- _3 = move ((_1 as Some).0: Empty); +- StorageLive(_4); + unreachable; + } + + bb3: { + unreachable; + } + + bb4: { + _0 = const (); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff new file mode 100644 index 0000000000000..2813d64672e6a --- /dev/null +++ b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff @@ -0,0 +1,45 @@ +- // MIR for `as_match` before UnreachablePropagation ++ // MIR for `as_match` after UnreachablePropagation + + fn as_match() -> () { + let mut _0: (); + let mut _1: std::option::Option; + let mut _2: isize; + let _3: Empty; + let mut _4: !; ++ let mut _5: bool; + scope 1 { + debug _x => _3; + } + + bb0: { + StorageLive(_1); + _1 = empty() -> [return: bb1, unwind continue]; + } + + bb1: { + _2 = discriminant(_1); +- switchInt(move _2) -> [0: bb4, 1: bb2, otherwise: bb3]; ++ _5 = Eq(_2, const 0_isize); ++ assume(move _5); ++ goto -> bb4; + } + + bb2: { +- StorageLive(_3); +- _3 = move ((_1 as Some).0: Empty); +- StorageLive(_4); + unreachable; + } + + bb3: { + unreachable; + } + + bb4: { + _0 = const (); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/unreachable.main.UnreachablePropagation.panic-abort.diff b/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-abort.diff similarity index 86% rename from tests/mir-opt/unreachable.main.UnreachablePropagation.panic-abort.diff rename to tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-abort.diff index 6f4faefce145e..61959732720e0 100644 --- a/tests/mir-opt/unreachable.main.UnreachablePropagation.panic-abort.diff +++ b/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-abort.diff @@ -1,7 +1,7 @@ -- // MIR for `main` before UnreachablePropagation -+ // MIR for `main` after UnreachablePropagation +- // MIR for `if_let` before UnreachablePropagation ++ // MIR for `if_let` after UnreachablePropagation - fn main() -> () { + fn if_let() -> () { let mut _0: (); let mut _1: std::option::Option; let mut _2: isize; @@ -9,7 +9,6 @@ let mut _6: bool; let mut _7: !; + let mut _8: bool; -+ let mut _9: bool; scope 1 { debug _x => _3; let _3: Empty; @@ -27,8 +26,8 @@ bb1: { _2 = discriminant(_1); - switchInt(move _2) -> [1: bb2, otherwise: bb6]; -+ _9 = Ne(_2, const 1_isize); -+ assume(move _9); ++ _8 = Ne(_2, const 1_isize); ++ assume(move _8); + goto -> bb6; } diff --git a/tests/mir-opt/unreachable.main.UnreachablePropagation.panic-unwind.diff b/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-unwind.diff similarity index 86% rename from tests/mir-opt/unreachable.main.UnreachablePropagation.panic-unwind.diff rename to tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-unwind.diff index 5bacb42bed3f2..476e2f5599449 100644 --- a/tests/mir-opt/unreachable.main.UnreachablePropagation.panic-unwind.diff +++ b/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-unwind.diff @@ -1,7 +1,7 @@ -- // MIR for `main` before UnreachablePropagation -+ // MIR for `main` after UnreachablePropagation +- // MIR for `if_let` before UnreachablePropagation ++ // MIR for `if_let` after UnreachablePropagation - fn main() -> () { + fn if_let() -> () { let mut _0: (); let mut _1: std::option::Option; let mut _2: isize; @@ -9,7 +9,6 @@ let mut _6: bool; let mut _7: !; + let mut _8: bool; -+ let mut _9: bool; scope 1 { debug _x => _3; let _3: Empty; @@ -27,8 +26,8 @@ bb1: { _2 = discriminant(_1); - switchInt(move _2) -> [1: bb2, otherwise: bb6]; -+ _9 = Ne(_2, const 1_isize); -+ assume(move _9); ++ _8 = Ne(_2, const 1_isize); ++ assume(move _8); + goto -> bb6; } diff --git a/tests/mir-opt/unreachable.rs b/tests/mir-opt/unreachable.rs index 3d934ace261e7..5b96681d9df58 100644 --- a/tests/mir-opt/unreachable.rs +++ b/tests/mir-opt/unreachable.rs @@ -7,9 +7,9 @@ fn empty() -> Option { None } -// EMIT_MIR unreachable.main.UnreachablePropagation.diff -fn main() { - // CHECK-LABEL: fn main( +// EMIT_MIR unreachable.if_let.UnreachablePropagation.diff +fn if_let() { + // CHECK-LABEL: fn if_let( // CHECK: bb0: { // CHECK: {{_.*}} = empty() // CHECK: bb1: { @@ -38,3 +38,29 @@ fn main() { match _x { } } } + +// EMIT_MIR unreachable.as_match.UnreachablePropagation.diff +fn as_match() { + // CHECK-LABEL: fn as_match( + // CHECK: bb0: { + // CHECK: {{_.*}} = empty() + // CHECK: bb1: { + // CHECK: [[eq:_.*]] = Eq({{.*}}, const 0_isize); + // CHECK-NEXT: assume(move [[eq]]); + // CHECK-NEXT: goto -> bb4; + // CHECK: bb2: { + // CHECK-NEXT: unreachable; + // CHECK: bb3: { + // CHECK-NEXT: unreachable; + // CHECK: bb4: { + // CHECK: return; + match empty() { + None => {} + Some(_x) => match _x {} + } +} + +fn main() { + if_let(); + as_match(); +}