From 218caa410aa38c29984be31a5229b9fa717560ee Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:13 +0200 Subject: Merging upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- .../branch.foo.DestinationPropagation.diff | 75 +++++++++++++++++++ tests/mir-opt/dest-prop/branch.rs | 27 +++++++ ...agation_arg.arg_src.DestinationPropagation.diff | 26 +++++++ ...propagation_arg.bar.DestinationPropagation.diff | 32 ++++++++ ...propagation_arg.baz.DestinationPropagation.diff | 22 ++++++ ...propagation_arg.foo.DestinationPropagation.diff | 32 ++++++++ tests/mir-opt/dest-prop/copy_propagation_arg.rs | 40 ++++++++++ .../cycle.main.DestinationPropagation.diff | 77 +++++++++++++++++++ tests/mir-opt/dest-prop/cycle.rs | 15 ++++ ...stores_79191.f.DestinationPropagation.after.mir | 34 +++++++++ tests/mir-opt/dest-prop/dead_stores_79191.rs | 17 +++++ ...tores_better.f.DestinationPropagation.after.mir | 33 +++++++++ tests/mir-opt/dest-prop/dead_stores_better.rs | 21 ++++++ .../simple.nrvo.DestinationPropagation.diff | 43 +++++++++++ tests/mir-opt/dest-prop/simple.rs | 14 ++++ .../union.main.DestinationPropagation.diff | 35 +++++++++ tests/mir-opt/dest-prop/union.rs | 16 ++++ .../unreachable.f.DestinationPropagation.diff | 86 ++++++++++++++++++++++ tests/mir-opt/dest-prop/unreachable.rs | 18 +++++ 19 files changed, 663 insertions(+) create mode 100644 tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff create mode 100644 tests/mir-opt/dest-prop/branch.rs create mode 100644 tests/mir-opt/dest-prop/copy_propagation_arg.arg_src.DestinationPropagation.diff create mode 100644 tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff create mode 100644 tests/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.diff create mode 100644 tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff create mode 100644 tests/mir-opt/dest-prop/copy_propagation_arg.rs create mode 100644 tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff create mode 100644 tests/mir-opt/dest-prop/cycle.rs create mode 100644 tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir create mode 100644 tests/mir-opt/dest-prop/dead_stores_79191.rs create mode 100644 tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir create mode 100644 tests/mir-opt/dest-prop/dead_stores_better.rs create mode 100644 tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff create mode 100644 tests/mir-opt/dest-prop/simple.rs create mode 100644 tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff create mode 100644 tests/mir-opt/dest-prop/union.rs create mode 100644 tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff create mode 100644 tests/mir-opt/dest-prop/unreachable.rs (limited to 'tests/mir-opt/dest-prop') diff --git a/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff new file mode 100644 index 000000000..9c7296632 --- /dev/null +++ b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff @@ -0,0 +1,75 @@ +- // MIR for `foo` before DestinationPropagation ++ // MIR for `foo` after DestinationPropagation + + fn foo() -> i32 { + let mut _0: i32; // return place in scope 0 at $DIR/branch.rs:+0:13: +0:16 + let _1: i32; // in scope 0 at $DIR/branch.rs:+1:9: +1:10 + let mut _3: bool; // in scope 0 at $DIR/branch.rs:+3:16: +3:22 + let _4: i32; // in scope 0 at $DIR/branch.rs:+6:9: +6:14 + scope 1 { +- debug x => _1; // in scope 1 at $DIR/branch.rs:+1:9: +1:10 ++ debug x => _0; // in scope 1 at $DIR/branch.rs:+1:9: +1:10 + let _2: i32; // in scope 1 at $DIR/branch.rs:+3:9: +3:10 + scope 2 { +- debug y => _2; // in scope 2 at $DIR/branch.rs:+3:9: +3:10 ++ debug y => _0; // in scope 2 at $DIR/branch.rs:+3:9: +3:10 + } + } + + bb0: { +- StorageLive(_1); // scope 0 at $DIR/branch.rs:+1:9: +1:10 +- _1 = val() -> bb1; // scope 0 at $DIR/branch.rs:+1:13: +1:18 ++ nop; // scope 0 at $DIR/branch.rs:+1:9: +1:10 ++ _0 = val() -> bb1; // scope 0 at $DIR/branch.rs:+1:13: +1:18 + // mir::Constant + // + span: $DIR/branch.rs:13:13: 13:16 + // + literal: Const { ty: fn() -> i32 {val}, val: Value() } + } + + bb1: { +- StorageLive(_2); // scope 1 at $DIR/branch.rs:+3:9: +3:10 ++ nop; // scope 1 at $DIR/branch.rs:+3:9: +3:10 + StorageLive(_3); // scope 1 at $DIR/branch.rs:+3:16: +3:22 + _3 = cond() -> bb2; // scope 1 at $DIR/branch.rs:+3:16: +3:22 + // mir::Constant + // + span: $DIR/branch.rs:15:16: 15:20 + // + literal: Const { ty: fn() -> bool {cond}, val: Value() } + } + + bb2: { + switchInt(move _3) -> [0: bb4, otherwise: bb3]; // scope 1 at $DIR/branch.rs:+3:16: +3:22 + } + + bb3: { +- _2 = _1; // scope 1 at $DIR/branch.rs:+4:9: +4:10 ++ nop; // scope 1 at $DIR/branch.rs:+4:9: +4:10 + goto -> bb6; // scope 1 at $DIR/branch.rs:+3:13: +8:6 + } + + bb4: { + StorageLive(_4); // scope 1 at $DIR/branch.rs:+6:9: +6:14 + _4 = val() -> bb5; // scope 1 at $DIR/branch.rs:+6:9: +6:14 + // mir::Constant + // + span: $DIR/branch.rs:18:9: 18:12 + // + literal: Const { ty: fn() -> i32 {val}, val: Value() } + } + + bb5: { + StorageDead(_4); // scope 1 at $DIR/branch.rs:+6:14: +6:15 +- _2 = _1; // scope 1 at $DIR/branch.rs:+7:9: +7:10 ++ nop; // scope 1 at $DIR/branch.rs:+7:9: +7:10 + goto -> bb6; // scope 1 at $DIR/branch.rs:+3:13: +8:6 + } + + bb6: { + StorageDead(_3); // scope 1 at $DIR/branch.rs:+8:5: +8:6 +- _0 = _2; // scope 2 at $DIR/branch.rs:+10:5: +10:6 +- StorageDead(_2); // scope 1 at $DIR/branch.rs:+11:1: +11:2 +- StorageDead(_1); // scope 0 at $DIR/branch.rs:+11:1: +11:2 ++ nop; // scope 2 at $DIR/branch.rs:+10:5: +10:6 ++ nop; // scope 1 at $DIR/branch.rs:+11:1: +11:2 ++ nop; // scope 0 at $DIR/branch.rs:+11:1: +11:2 + return; // scope 0 at $DIR/branch.rs:+11:2: +11:2 + } + } + diff --git a/tests/mir-opt/dest-prop/branch.rs b/tests/mir-opt/dest-prop/branch.rs new file mode 100644 index 000000000..898c908b1 --- /dev/null +++ b/tests/mir-opt/dest-prop/branch.rs @@ -0,0 +1,27 @@ +//! Tests that assignment in both branches of an `if` are eliminated. +// unit-test: DestinationPropagation +fn val() -> i32 { + 1 +} + +fn cond() -> bool { + true +} + +// EMIT_MIR branch.foo.DestinationPropagation.diff +fn foo() -> i32 { + let x = val(); + + let y = if cond() { + x + } else { + val(); + x + }; + + y +} + +fn main() { + foo(); +} diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.arg_src.DestinationPropagation.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.arg_src.DestinationPropagation.diff new file mode 100644 index 000000000..4343a5935 --- /dev/null +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.arg_src.DestinationPropagation.diff @@ -0,0 +1,26 @@ +- // MIR for `arg_src` before DestinationPropagation ++ // MIR for `arg_src` after DestinationPropagation + + fn arg_src(_1: i32) -> i32 { + debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:+0:12: +0:17 + let mut _0: i32; // return place in scope 0 at $DIR/copy_propagation_arg.rs:+0:27: +0:30 + let _2: i32; // in scope 0 at $DIR/copy_propagation_arg.rs:+1:9: +1:10 + scope 1 { +- debug y => _2; // in scope 1 at $DIR/copy_propagation_arg.rs:+1:9: +1:10 ++ debug y => _0; // in scope 1 at $DIR/copy_propagation_arg.rs:+1:9: +1:10 + } + + bb0: { +- StorageLive(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+1:9: +1:10 +- _2 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:+1:13: +1:14 ++ nop; // scope 0 at $DIR/copy_propagation_arg.rs:+1:9: +1:10 ++ _0 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:+1:13: +1:14 + _1 = const 123_i32; // scope 1 at $DIR/copy_propagation_arg.rs:+2:5: +2:12 +- _0 = _2; // scope 1 at $DIR/copy_propagation_arg.rs:+3:5: +3:6 +- StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+4:1: +4:2 ++ nop; // scope 1 at $DIR/copy_propagation_arg.rs:+3:5: +3:6 ++ nop; // scope 0 at $DIR/copy_propagation_arg.rs:+4:1: +4:2 + return; // scope 0 at $DIR/copy_propagation_arg.rs:+4:2: +4:2 + } + } + diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff new file mode 100644 index 000000000..298991b5a --- /dev/null +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff @@ -0,0 +1,32 @@ +- // MIR for `bar` before DestinationPropagation ++ // MIR for `bar` after DestinationPropagation + + fn bar(_1: u8) -> () { + debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:+0:8: +0:13 + let mut _0: (); // return place in scope 0 at $DIR/copy_propagation_arg.rs:+0:19: +0:19 + let _2: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:+1:5: +1:13 + let mut _3: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+1:5: +1:13 +- StorageLive(_3); // scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12 +- _3 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12 +- _2 = dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:+1:5: +1:13 ++ nop; // scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12 ++ nop; // scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12 ++ _2 = dummy(move _1) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:+1:5: +1:13 + // mir::Constant + // + span: $DIR/copy_propagation_arg.rs:16:5: 16:10 + // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value() } + } + + bb1: { +- StorageDead(_3); // scope 0 at $DIR/copy_propagation_arg.rs:+1:12: +1:13 ++ nop; // scope 0 at $DIR/copy_propagation_arg.rs:+1:12: +1:13 + StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+1:13: +1:14 + _1 = const 5_u8; // scope 0 at $DIR/copy_propagation_arg.rs:+2:5: +2:10 + _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:+0:19: +3:2 + return; // scope 0 at $DIR/copy_propagation_arg.rs:+3:2: +3:2 + } + } + diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.diff new file mode 100644 index 000000000..bc88787e6 --- /dev/null +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.diff @@ -0,0 +1,22 @@ +- // MIR for `baz` before DestinationPropagation ++ // MIR for `baz` after DestinationPropagation + + fn baz(_1: i32) -> i32 { + debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:+0:8: +0:13 + let mut _0: i32; // return place in scope 0 at $DIR/copy_propagation_arg.rs:+0:23: +0:26 + let mut _2: i32; // in scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:10 + + bb0: { +- StorageLive(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:10 +- _2 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:10 +- _1 = move _2; // scope 0 at $DIR/copy_propagation_arg.rs:+2:5: +2:10 +- StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:10 ++ nop; // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:10 ++ nop; // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:10 ++ nop; // scope 0 at $DIR/copy_propagation_arg.rs:+2:5: +2:10 ++ nop; // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:10 + _0 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:+3:5: +3:6 + return; // scope 0 at $DIR/copy_propagation_arg.rs:+4:2: +4:2 + } + } + diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff new file mode 100644 index 000000000..d37a9f71d --- /dev/null +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff @@ -0,0 +1,32 @@ +- // MIR for `foo` before DestinationPropagation ++ // MIR for `foo` after DestinationPropagation + + fn foo(_1: u8) -> () { + debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:+0:8: +0:13 + let mut _0: (); // return place in scope 0 at $DIR/copy_propagation_arg.rs:+0:19: +0:19 + let mut _2: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17 + let mut _3: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:+2:15: +2:16 + + bb0: { +- StorageLive(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17 ++ nop; // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17 + StorageLive(_3); // scope 0 at $DIR/copy_propagation_arg.rs:+2:15: +2:16 + _3 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:+2:15: +2:16 +- _2 = dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17 ++ _1 = dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17 + // mir::Constant + // + span: $DIR/copy_propagation_arg.rs:11:9: 11:14 + // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value() } + } + + bb1: { + StorageDead(_3); // scope 0 at $DIR/copy_propagation_arg.rs:+2:16: +2:17 +- _1 = move _2; // scope 0 at $DIR/copy_propagation_arg.rs:+2:5: +2:17 +- StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+2:16: +2:17 ++ nop; // scope 0 at $DIR/copy_propagation_arg.rs:+2:5: +2:17 ++ nop; // scope 0 at $DIR/copy_propagation_arg.rs:+2:16: +2:17 + _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:+0:19: +3:2 + return; // scope 0 at $DIR/copy_propagation_arg.rs:+3:2: +3:2 + } + } + diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.rs b/tests/mir-opt/dest-prop/copy_propagation_arg.rs new file mode 100644 index 000000000..31be6c931 --- /dev/null +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.rs @@ -0,0 +1,40 @@ +// Check that DestinationPropagation does not propagate an assignment to a function argument +// (doing so can break usages of the original argument value) +// unit-test: DestinationPropagation +fn dummy(x: u8) -> u8 { + x +} + +// EMIT_MIR copy_propagation_arg.foo.DestinationPropagation.diff +fn foo(mut x: u8) { + // calling `dummy` to make a use of `x` that copyprop cannot eliminate + x = dummy(x); // this will assign a local to `x` +} + +// EMIT_MIR copy_propagation_arg.bar.DestinationPropagation.diff +fn bar(mut x: u8) { + dummy(x); + x = 5; +} + +// EMIT_MIR copy_propagation_arg.baz.DestinationPropagation.diff +fn baz(mut x: i32) -> i32 { + // self-assignment to a function argument should be eliminated + x = x; + x +} + +// EMIT_MIR copy_propagation_arg.arg_src.DestinationPropagation.diff +fn arg_src(mut x: i32) -> i32 { + let y = x; + x = 123; // Don't propagate this assignment to `y` + y +} + +fn main() { + // Make sure the function actually gets instantiated. + foo(0); + bar(0); + baz(0); + arg_src(0); +} diff --git a/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff new file mode 100644 index 000000000..cfc203c5f --- /dev/null +++ b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff @@ -0,0 +1,77 @@ +- // MIR for `main` before DestinationPropagation ++ // MIR for `main` after DestinationPropagation + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/cycle.rs:+0:11: +0:11 + let mut _1: i32; // in scope 0 at $DIR/cycle.rs:+1:9: +1:14 + let mut _4: i32; // in scope 0 at $DIR/cycle.rs:+4:9: +4:10 + let _5: (); // in scope 0 at $DIR/cycle.rs:+6:5: +6:12 + let mut _6: i32; // in scope 0 at $DIR/cycle.rs:+6:10: +6:11 + scope 1 { +- debug x => _1; // in scope 1 at $DIR/cycle.rs:+1:9: +1:14 ++ debug x => _6; // in scope 1 at $DIR/cycle.rs:+1:9: +1:14 + let _2: i32; // in scope 1 at $DIR/cycle.rs:+2:9: +2:10 + scope 2 { +- debug y => _2; // in scope 2 at $DIR/cycle.rs:+2:9: +2:10 ++ debug y => _6; // in scope 2 at $DIR/cycle.rs:+2:9: +2:10 + let _3: i32; // in scope 2 at $DIR/cycle.rs:+3:9: +3:10 + scope 3 { +- debug z => _3; // in scope 3 at $DIR/cycle.rs:+3:9: +3:10 ++ debug z => _6; // in scope 3 at $DIR/cycle.rs:+3:9: +3:10 + } + } + } + + bb0: { +- StorageLive(_1); // scope 0 at $DIR/cycle.rs:+1:9: +1:14 +- _1 = val() -> bb1; // scope 0 at $DIR/cycle.rs:+1:17: +1:22 ++ nop; // scope 0 at $DIR/cycle.rs:+1:9: +1:14 ++ _6 = val() -> bb1; // scope 0 at $DIR/cycle.rs:+1:17: +1:22 + // mir::Constant + // + span: $DIR/cycle.rs:9:17: 9:20 + // + literal: Const { ty: fn() -> i32 {val}, val: Value() } + } + + bb1: { +- StorageLive(_2); // scope 1 at $DIR/cycle.rs:+2:9: +2:10 +- _2 = _1; // scope 1 at $DIR/cycle.rs:+2:13: +2:14 +- StorageLive(_3); // scope 2 at $DIR/cycle.rs:+3:9: +3:10 +- _3 = _2; // scope 2 at $DIR/cycle.rs:+3:13: +3:14 +- StorageLive(_4); // scope 3 at $DIR/cycle.rs:+4:9: +4:10 +- _4 = _3; // scope 3 at $DIR/cycle.rs:+4:9: +4:10 +- _1 = move _4; // scope 3 at $DIR/cycle.rs:+4:5: +4:10 +- StorageDead(_4); // scope 3 at $DIR/cycle.rs:+4:9: +4:10 ++ nop; // scope 1 at $DIR/cycle.rs:+2:9: +2:10 ++ nop; // scope 1 at $DIR/cycle.rs:+2:13: +2:14 ++ nop; // scope 2 at $DIR/cycle.rs:+3:9: +3:10 ++ nop; // scope 2 at $DIR/cycle.rs:+3:13: +3:14 ++ nop; // scope 3 at $DIR/cycle.rs:+4:9: +4:10 ++ nop; // scope 3 at $DIR/cycle.rs:+4:9: +4:10 ++ nop; // scope 3 at $DIR/cycle.rs:+4:5: +4:10 ++ nop; // scope 3 at $DIR/cycle.rs:+4:9: +4:10 + StorageLive(_5); // scope 3 at $DIR/cycle.rs:+6:5: +6:12 +- StorageLive(_6); // scope 3 at $DIR/cycle.rs:+6:10: +6:11 +- _6 = _1; // scope 3 at $DIR/cycle.rs:+6:10: +6:11 ++ nop; // scope 3 at $DIR/cycle.rs:+6:10: +6:11 ++ nop; // scope 3 at $DIR/cycle.rs:+6:10: +6:11 + _5 = std::mem::drop::(move _6) -> bb2; // scope 3 at $DIR/cycle.rs:+6:5: +6:12 + // mir::Constant + // + span: $DIR/cycle.rs:14:5: 14:9 + // + literal: Const { ty: fn(i32) {std::mem::drop::}, val: Value() } + } + + bb2: { +- StorageDead(_6); // scope 3 at $DIR/cycle.rs:+6:11: +6:12 ++ nop; // scope 3 at $DIR/cycle.rs:+6:11: +6:12 + StorageDead(_5); // scope 3 at $DIR/cycle.rs:+6:12: +6:13 + _0 = const (); // scope 0 at $DIR/cycle.rs:+0:11: +7:2 +- StorageDead(_3); // scope 2 at $DIR/cycle.rs:+7:1: +7:2 +- StorageDead(_2); // scope 1 at $DIR/cycle.rs:+7:1: +7:2 +- StorageDead(_1); // scope 0 at $DIR/cycle.rs:+7:1: +7:2 ++ nop; // scope 2 at $DIR/cycle.rs:+7:1: +7:2 ++ nop; // scope 1 at $DIR/cycle.rs:+7:1: +7:2 ++ nop; // scope 0 at $DIR/cycle.rs:+7:1: +7:2 + return; // scope 0 at $DIR/cycle.rs:+7:2: +7:2 + } + } + diff --git a/tests/mir-opt/dest-prop/cycle.rs b/tests/mir-opt/dest-prop/cycle.rs new file mode 100644 index 000000000..6182878f3 --- /dev/null +++ b/tests/mir-opt/dest-prop/cycle.rs @@ -0,0 +1,15 @@ +//! Tests that cyclic assignments don't hang DestinationPropagation, and result in reasonable code. +// unit-test: DestinationPropagation +fn val() -> i32 { + 1 +} + +// EMIT_MIR cycle.main.DestinationPropagation.diff +fn main() { + let mut x = val(); + let y = x; + let z = y; + x = z; + + drop(x); +} diff --git a/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir new file mode 100644 index 000000000..63cac133b --- /dev/null +++ b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir @@ -0,0 +1,34 @@ +// MIR for `f` after DestinationPropagation + +fn f(_1: usize) -> usize { + debug a => _1; // in scope 0 at $DIR/dead_stores_79191.rs:+0:6: +0:11 + let mut _0: usize; // return place in scope 0 at $DIR/dead_stores_79191.rs:+0:23: +0:28 + let _2: usize; // in scope 0 at $DIR/dead_stores_79191.rs:+1:9: +1:10 + let mut _3: usize; // in scope 0 at $DIR/dead_stores_79191.rs:+3:9: +3:10 + let mut _4: usize; // in scope 0 at $DIR/dead_stores_79191.rs:+4:8: +4:9 + scope 1 { + debug b => _3; // in scope 1 at $DIR/dead_stores_79191.rs:+1:9: +1:10 + } + + bb0: { + nop; // scope 0 at $DIR/dead_stores_79191.rs:+1:9: +1:10 + _3 = _1; // scope 0 at $DIR/dead_stores_79191.rs:+1:13: +1:14 + _1 = const 5_usize; // scope 1 at $DIR/dead_stores_79191.rs:+2:5: +2:10 + nop; // scope 1 at $DIR/dead_stores_79191.rs:+3:9: +3:10 + nop; // scope 1 at $DIR/dead_stores_79191.rs:+3:9: +3:10 + _1 = move _3; // scope 1 at $DIR/dead_stores_79191.rs:+3:5: +3:10 + nop; // scope 1 at $DIR/dead_stores_79191.rs:+3:9: +3:10 + nop; // scope 1 at $DIR/dead_stores_79191.rs:+4:8: +4:9 + nop; // scope 1 at $DIR/dead_stores_79191.rs:+4:8: +4:9 + _0 = id::(move _1) -> bb1; // scope 1 at $DIR/dead_stores_79191.rs:+4:5: +4:10 + // mir::Constant + // + span: $DIR/dead_stores_79191.rs:12:5: 12:7 + // + literal: Const { ty: fn(usize) -> usize {id::}, val: Value() } + } + + bb1: { + nop; // scope 1 at $DIR/dead_stores_79191.rs:+4:9: +4:10 + nop; // scope 0 at $DIR/dead_stores_79191.rs:+5:1: +5:2 + return; // scope 0 at $DIR/dead_stores_79191.rs:+5:2: +5:2 + } +} diff --git a/tests/mir-opt/dest-prop/dead_stores_79191.rs b/tests/mir-opt/dest-prop/dead_stores_79191.rs new file mode 100644 index 000000000..43e0bf664 --- /dev/null +++ b/tests/mir-opt/dest-prop/dead_stores_79191.rs @@ -0,0 +1,17 @@ +// unit-test: DestinationPropagation + +fn id(x: T) -> T { + x +} + +// EMIT_MIR dead_stores_79191.f.DestinationPropagation.after.mir +fn f(mut a: usize) -> usize { + let b = a; + a = 5; + a = b; + id(a) +} + +fn main() { + f(0); +} diff --git a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir new file mode 100644 index 000000000..26068931a --- /dev/null +++ b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir @@ -0,0 +1,33 @@ +// MIR for `f` after DestinationPropagation + +fn f(_1: usize) -> usize { + debug a => _1; // in scope 0 at $DIR/dead_stores_better.rs:+0:10: +0:15 + let mut _0: usize; // return place in scope 0 at $DIR/dead_stores_better.rs:+0:27: +0:32 + let _2: usize; // in scope 0 at $DIR/dead_stores_better.rs:+1:9: +1:10 + let mut _3: usize; // in scope 0 at $DIR/dead_stores_better.rs:+3:9: +3:10 + let mut _4: usize; // in scope 0 at $DIR/dead_stores_better.rs:+4:8: +4:9 + scope 1 { + debug b => _1; // in scope 1 at $DIR/dead_stores_better.rs:+1:9: +1:10 + } + + bb0: { + nop; // scope 0 at $DIR/dead_stores_better.rs:+1:9: +1:10 + nop; // scope 0 at $DIR/dead_stores_better.rs:+1:13: +1:14 + nop; // scope 1 at $DIR/dead_stores_better.rs:+3:9: +3:10 + nop; // scope 1 at $DIR/dead_stores_better.rs:+3:9: +3:10 + nop; // scope 1 at $DIR/dead_stores_better.rs:+3:5: +3:10 + nop; // scope 1 at $DIR/dead_stores_better.rs:+3:9: +3:10 + nop; // scope 1 at $DIR/dead_stores_better.rs:+4:8: +4:9 + nop; // scope 1 at $DIR/dead_stores_better.rs:+4:8: +4:9 + _0 = id::(move _1) -> bb1; // scope 1 at $DIR/dead_stores_better.rs:+4:5: +4:10 + // mir::Constant + // + span: $DIR/dead_stores_better.rs:16:5: 16:7 + // + literal: Const { ty: fn(usize) -> usize {id::}, val: Value() } + } + + bb1: { + nop; // scope 1 at $DIR/dead_stores_better.rs:+4:9: +4:10 + nop; // scope 0 at $DIR/dead_stores_better.rs:+5:1: +5:2 + return; // scope 0 at $DIR/dead_stores_better.rs:+5:2: +5:2 + } +} diff --git a/tests/mir-opt/dest-prop/dead_stores_better.rs b/tests/mir-opt/dest-prop/dead_stores_better.rs new file mode 100644 index 000000000..003ad57d8 --- /dev/null +++ b/tests/mir-opt/dest-prop/dead_stores_better.rs @@ -0,0 +1,21 @@ +// This is a copy of the `dead_stores_79191` test, except that we turn on DSE. This demonstrates +// that that pass enables this one to do more optimizations. + +// unit-test: DestinationPropagation +// compile-flags: -Zmir-enable-passes=+DeadStoreElimination + +fn id(x: T) -> T { + x +} + +// EMIT_MIR dead_stores_better.f.DestinationPropagation.after.mir +pub fn f(mut a: usize) -> usize { + let b = a; + a = 5; + a = b; + id(a) +} + +fn main() { + f(0); +} diff --git a/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff b/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff new file mode 100644 index 000000000..c2a3a0025 --- /dev/null +++ b/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff @@ -0,0 +1,43 @@ +- // MIR for `nrvo` before DestinationPropagation ++ // MIR for `nrvo` after DestinationPropagation + + fn nrvo(_1: for<'a> fn(&'a mut [u8; 1024])) -> [u8; 1024] { + debug init => _1; // in scope 0 at $DIR/simple.rs:+0:9: +0:13 + let mut _0: [u8; 1024]; // return place in scope 0 at $DIR/simple.rs:+0:39: +0:49 + let mut _2: [u8; 1024]; // in scope 0 at $DIR/simple.rs:+1:9: +1:16 + let _3: (); // in scope 0 at $DIR/simple.rs:+2:5: +2:19 + let mut _4: for<'a> fn(&'a mut [u8; 1024]); // in scope 0 at $DIR/simple.rs:+2:5: +2:9 + let mut _5: &mut [u8; 1024]; // in scope 0 at $DIR/simple.rs:+2:10: +2:18 + let mut _6: &mut [u8; 1024]; // in scope 0 at $DIR/simple.rs:+2:10: +2:18 + scope 1 { + debug buf => _2; // in scope 1 at $DIR/simple.rs:+1:9: +1:16 + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/simple.rs:+1:9: +1:16 + _2 = [const 0_u8; 1024]; // scope 0 at $DIR/simple.rs:+1:19: +1:28 + StorageLive(_3); // scope 1 at $DIR/simple.rs:+2:5: +2:19 +- StorageLive(_4); // scope 1 at $DIR/simple.rs:+2:5: +2:9 +- _4 = _1; // scope 1 at $DIR/simple.rs:+2:5: +2:9 ++ nop; // scope 1 at $DIR/simple.rs:+2:5: +2:9 ++ nop; // scope 1 at $DIR/simple.rs:+2:5: +2:9 + StorageLive(_5); // scope 1 at $DIR/simple.rs:+2:10: +2:18 + StorageLive(_6); // scope 1 at $DIR/simple.rs:+2:10: +2:18 + _6 = &mut _2; // scope 1 at $DIR/simple.rs:+2:10: +2:18 + _5 = &mut (*_6); // scope 1 at $DIR/simple.rs:+2:10: +2:18 +- _3 = move _4(move _5) -> bb1; // scope 1 at $DIR/simple.rs:+2:5: +2:19 ++ _3 = move _1(move _5) -> bb1; // scope 1 at $DIR/simple.rs:+2:5: +2:19 + } + + bb1: { + StorageDead(_5); // scope 1 at $DIR/simple.rs:+2:18: +2:19 +- StorageDead(_4); // scope 1 at $DIR/simple.rs:+2:18: +2:19 ++ nop; // scope 1 at $DIR/simple.rs:+2:18: +2:19 + StorageDead(_6); // scope 1 at $DIR/simple.rs:+2:19: +2:20 + StorageDead(_3); // scope 1 at $DIR/simple.rs:+2:19: +2:20 + _0 = _2; // scope 1 at $DIR/simple.rs:+3:5: +3:8 + StorageDead(_2); // scope 0 at $DIR/simple.rs:+4:1: +4:2 + return; // scope 0 at $DIR/simple.rs:+4:2: +4:2 + } + } + diff --git a/tests/mir-opt/dest-prop/simple.rs b/tests/mir-opt/dest-prop/simple.rs new file mode 100644 index 000000000..d4c27228f --- /dev/null +++ b/tests/mir-opt/dest-prop/simple.rs @@ -0,0 +1,14 @@ +//! Copy of `nrvo-simple.rs`, to ensure that full dest-prop handles it too. +// unit-test: DestinationPropagation +// EMIT_MIR simple.nrvo.DestinationPropagation.diff +fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] { + let mut buf = [0; 1024]; + init(&mut buf); + buf +} + +fn main() { + let _ = nrvo(|buf| { + buf[4] = 4; + }); +} diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff new file mode 100644 index 000000000..fbed31788 --- /dev/null +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff @@ -0,0 +1,35 @@ +- // MIR for `main` before DestinationPropagation ++ // MIR for `main` after DestinationPropagation + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/union.rs:+0:11: +0:11 + let _1: main::Un; // in scope 0 at $DIR/union.rs:+5:9: +5:11 + let mut _2: u32; // in scope 0 at $DIR/union.rs:+5:23: +5:28 + let mut _3: u32; // in scope 0 at $DIR/union.rs:+7:10: +7:26 + scope 1 { + debug un => _1; // in scope 1 at $DIR/union.rs:+5:9: +5:11 + scope 2 { + } + scope 3 (inlined std::mem::drop::) { // at $DIR/union.rs:15:5: 15:27 + debug _x => _3; // in scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/union.rs:+5:9: +5:11 + StorageLive(_2); // scope 0 at $DIR/union.rs:+5:23: +5:28 + _2 = val() -> bb1; // scope 0 at $DIR/union.rs:+5:23: +5:28 + // mir::Constant + // + span: $DIR/union.rs:13:23: 13:26 + // + literal: Const { ty: fn() -> u32 {val}, val: Value() } + } + + bb1: { + StorageDead(_2); // scope 0 at $DIR/union.rs:+5:29: +5:30 + StorageLive(_3); // scope 1 at $DIR/union.rs:+7:10: +7:26 + StorageDead(_3); // scope 1 at $DIR/union.rs:+7:26: +7:27 + StorageDead(_1); // scope 0 at $DIR/union.rs:+8:1: +8:2 + return; // scope 0 at $DIR/union.rs:+8:2: +8:2 + } + } + diff --git a/tests/mir-opt/dest-prop/union.rs b/tests/mir-opt/dest-prop/union.rs new file mode 100644 index 000000000..eb6cb09fc --- /dev/null +++ b/tests/mir-opt/dest-prop/union.rs @@ -0,0 +1,16 @@ +//! Tests that we can propagate into places that are projections into unions +// compile-flags: -Zunsound-mir-opts +fn val() -> u32 { + 1 +} + +// EMIT_MIR union.main.DestinationPropagation.diff +fn main() { + union Un { + us: u32, + } + + let un = Un { us: val() }; + + drop(unsafe { un.us }); +} diff --git a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff new file mode 100644 index 000000000..9ea756c27 --- /dev/null +++ b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff @@ -0,0 +1,86 @@ +- // MIR for `f` before DestinationPropagation ++ // MIR for `f` after DestinationPropagation + + fn f(_1: T) -> () { + debug a => _1; // in scope 0 at $DIR/unreachable.rs:+0:19: +0:20 + let mut _0: (); // return place in scope 0 at $DIR/unreachable.rs:+0:25: +0:25 + let _2: T; // in scope 0 at $DIR/unreachable.rs:+1:9: +1:10 + let mut _3: bool; // in scope 0 at $DIR/unreachable.rs:+2:8: +2:13 + let _4: (); // in scope 0 at $DIR/unreachable.rs:+3:9: +3:16 + let mut _5: T; // in scope 0 at $DIR/unreachable.rs:+3:11: +3:12 + let mut _6: T; // in scope 0 at $DIR/unreachable.rs:+3:14: +3:15 + let _7: (); // in scope 0 at $DIR/unreachable.rs:+5:9: +5:16 + let mut _8: T; // in scope 0 at $DIR/unreachable.rs:+5:11: +5:12 + let mut _9: T; // in scope 0 at $DIR/unreachable.rs:+5:14: +5:15 + scope 1 { +- debug b => _2; // in scope 1 at $DIR/unreachable.rs:+1:9: +1:10 ++ debug b => _1; // in scope 1 at $DIR/unreachable.rs:+1:9: +1:10 + } + + bb0: { +- StorageLive(_2); // scope 0 at $DIR/unreachable.rs:+1:9: +1:10 +- _2 = _1; // scope 0 at $DIR/unreachable.rs:+1:13: +1:14 ++ nop; // scope 0 at $DIR/unreachable.rs:+1:9: +1:10 ++ nop; // scope 0 at $DIR/unreachable.rs:+1:13: +1:14 + StorageLive(_3); // scope 1 at $DIR/unreachable.rs:+2:8: +2:13 + _3 = const false; // scope 1 at $DIR/unreachable.rs:+2:8: +2:13 +- goto -> bb3; // scope 1 at $DIR/unreachable.rs:+2:8: +2:13 ++ goto -> bb1; // scope 1 at $DIR/unreachable.rs:+2:8: +2:13 + } + + bb1: { +- StorageLive(_4); // scope 1 at $DIR/unreachable.rs:+3:9: +3:16 +- StorageLive(_5); // scope 1 at $DIR/unreachable.rs:+3:11: +3:12 +- _5 = _1; // scope 1 at $DIR/unreachable.rs:+3:11: +3:12 +- StorageLive(_6); // scope 1 at $DIR/unreachable.rs:+3:14: +3:15 +- _6 = _2; // scope 1 at $DIR/unreachable.rs:+3:14: +3:15 +- _4 = g::(move _5, move _6) -> bb2; // scope 1 at $DIR/unreachable.rs:+3:9: +3:16 +- // mir::Constant +- // + span: $DIR/unreachable.rs:11:9: 11:10 +- // + literal: Const { ty: fn(T, T) {g::}, val: Value() } +- } +- +- bb2: { +- StorageDead(_6); // scope 1 at $DIR/unreachable.rs:+3:15: +3:16 +- StorageDead(_5); // scope 1 at $DIR/unreachable.rs:+3:15: +3:16 +- StorageDead(_4); // scope 1 at $DIR/unreachable.rs:+3:16: +3:17 +- _0 = const (); // scope 1 at $DIR/unreachable.rs:+2:14: +4:6 +- goto -> bb5; // scope 1 at $DIR/unreachable.rs:+2:5: +6:6 +- } +- +- bb3: { + StorageLive(_7); // scope 1 at $DIR/unreachable.rs:+5:9: +5:16 +- StorageLive(_8); // scope 1 at $DIR/unreachable.rs:+5:11: +5:12 +- _8 = _2; // scope 1 at $DIR/unreachable.rs:+5:11: +5:12 ++ nop; // scope 1 at $DIR/unreachable.rs:+5:11: +5:12 ++ nop; // scope 1 at $DIR/unreachable.rs:+5:11: +5:12 + StorageLive(_9); // scope 1 at $DIR/unreachable.rs:+5:14: +5:15 +- _9 = _2; // scope 1 at $DIR/unreachable.rs:+5:14: +5:15 +- _7 = g::(move _8, move _9) -> bb4; // scope 1 at $DIR/unreachable.rs:+5:9: +5:16 ++ _9 = _1; // scope 1 at $DIR/unreachable.rs:+5:14: +5:15 ++ _7 = g::(move _1, move _9) -> bb2; // scope 1 at $DIR/unreachable.rs:+5:9: +5:16 + // mir::Constant + // + span: $DIR/unreachable.rs:13:9: 13:10 + // + literal: Const { ty: fn(T, T) {g::}, val: Value() } + } + +- bb4: { ++ bb2: { + StorageDead(_9); // scope 1 at $DIR/unreachable.rs:+5:15: +5:16 +- StorageDead(_8); // scope 1 at $DIR/unreachable.rs:+5:15: +5:16 ++ nop; // scope 1 at $DIR/unreachable.rs:+5:15: +5:16 + StorageDead(_7); // scope 1 at $DIR/unreachable.rs:+5:16: +5:17 + _0 = const (); // scope 1 at $DIR/unreachable.rs:+4:12: +6:6 +- goto -> bb5; // scope 1 at $DIR/unreachable.rs:+2:5: +6:6 ++ goto -> bb3; // scope 1 at $DIR/unreachable.rs:+2:5: +6:6 + } + +- bb5: { ++ bb3: { + StorageDead(_3); // scope 1 at $DIR/unreachable.rs:+6:5: +6:6 +- StorageDead(_2); // scope 0 at $DIR/unreachable.rs:+7:1: +7:2 ++ nop; // scope 0 at $DIR/unreachable.rs:+7:1: +7:2 + return; // scope 0 at $DIR/unreachable.rs:+7:2: +7:2 + } + } + diff --git a/tests/mir-opt/dest-prop/unreachable.rs b/tests/mir-opt/dest-prop/unreachable.rs new file mode 100644 index 000000000..32b5def98 --- /dev/null +++ b/tests/mir-opt/dest-prop/unreachable.rs @@ -0,0 +1,18 @@ +// Check that unreachable code is removed after the destination propagation. +// Regression test for issue #105428. +// +// compile-flags: --crate-type=lib -Zmir-opt-level=0 +// compile-flags: -Zmir-enable-passes=+ConstProp,+SimplifyConstCondition-after-const-prop,+DestinationPropagation + +// EMIT_MIR unreachable.f.DestinationPropagation.diff +pub fn f(a: T) { + let b = a; + if false { + g(a, b); + } else { + g(b, b); + } +} + +#[inline(never)] +pub fn g(_: T, _: T) {} -- cgit v1.2.3