summaryrefslogtreecommitdiffstats
path: root/tests/mir-opt/dest-prop
diff options
context:
space:
mode:
Diffstat (limited to 'tests/mir-opt/dest-prop')
-rw-r--r--tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff75
-rw-r--r--tests/mir-opt/dest-prop/branch.rs27
-rw-r--r--tests/mir-opt/dest-prop/copy_propagation_arg.arg_src.DestinationPropagation.diff26
-rw-r--r--tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff32
-rw-r--r--tests/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.diff22
-rw-r--r--tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff32
-rw-r--r--tests/mir-opt/dest-prop/copy_propagation_arg.rs40
-rw-r--r--tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff77
-rw-r--r--tests/mir-opt/dest-prop/cycle.rs15
-rw-r--r--tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir34
-rw-r--r--tests/mir-opt/dest-prop/dead_stores_79191.rs17
-rw-r--r--tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir33
-rw-r--r--tests/mir-opt/dest-prop/dead_stores_better.rs21
-rw-r--r--tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff43
-rw-r--r--tests/mir-opt/dest-prop/simple.rs14
-rw-r--r--tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff35
-rw-r--r--tests/mir-opt/dest-prop/union.rs16
-rw-r--r--tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff86
-rw-r--r--tests/mir-opt/dest-prop/unreachable.rs18
19 files changed, 663 insertions, 0 deletions
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(<ZST>) }
+ }
+
+ 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(<ZST>) }
+ }
+
+ 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(<ZST>) }
+ }
+
+ 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(<ZST>) }
+ }
+
+ 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(<ZST>) }
+ }
+
+ 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(<ZST>) }
+ }
+
+ 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::<i32>(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::<i32>}, val: Value(<ZST>) }
+ }
+
+ 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::<usize>(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::<usize>}, val: Value(<ZST>) }
+ }
+
+ 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<T>(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::<usize>(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::<usize>}, val: Value(<ZST>) }
+ }
+
+ 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<T>(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::<u32>) { // 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(<ZST>) }
+ }
+
+ 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::<T>(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::<T>}, val: Value(<ZST>) }
+- }
+-
+- 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::<T>(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::<T>(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::<T>}, val: Value(<ZST>) }
+ }
+
+- 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<T: Copy>(a: T) {
+ let b = a;
+ if false {
+ g(a, b);
+ } else {
+ g(b, b);
+ }
+}
+
+#[inline(never)]
+pub fn g<T: Copy>(_: T, _: T) {}