about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2023-01-15 15:30:09 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-01-27 18:22:45 +0000
commit38b55dc68459bf68cd5489b8c5d808b6902c83d1 (patch)
tree0ce29f0d21c7deea2f66eca3e681f92f92552df8
parent6ed9f8f62ebe52f388f9098fb4c05791f588729b (diff)
downloadrust-38b55dc68459bf68cd5489b8c5d808b6902c83d1.tar.gz
rust-38b55dc68459bf68cd5489b8c5d808b6902c83d1.zip
Add tests.
-rw-r--r--tests/mir-opt/copy-prop/branch.foo.CopyProp.diff65
-rw-r--r--tests/mir-opt/copy-prop/branch.rs27
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff21
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff28
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.diff18
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff28
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.rs40
-rw-r--r--tests/mir-opt/copy-prop/cycle.main.CopyProp.diff60
-rw-r--r--tests/mir-opt/copy-prop/cycle.rs15
-rw-r--r--tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir29
-rw-r--r--tests/mir-opt/copy-prop/dead_stores_79191.rs17
-rw-r--r--tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir29
-rw-r--r--tests/mir-opt/copy-prop/dead_stores_better.rs21
-rw-r--r--tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff40
-rw-r--r--tests/mir-opt/copy-prop/move_arg.rs15
15 files changed, 453 insertions, 0 deletions
diff --git a/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff b/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff
new file mode 100644
index 00000000000..8b116532d9f
--- /dev/null
+++ b/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff
@@ -0,0 +1,65 @@
+- // MIR for `foo` before CopyProp
++ // MIR for `foo` after CopyProp
+  
+  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
+          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
+          }
+      }
+  
+      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
+                                           // 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
+          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
+          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
+          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
+          return;                          // scope 0 at $DIR/branch.rs:+11:2: +11:2
+      }
+  }
+  
diff --git a/tests/mir-opt/copy-prop/branch.rs b/tests/mir-opt/copy-prop/branch.rs
new file mode 100644
index 00000000000..50b1e00fad4
--- /dev/null
+++ b/tests/mir-opt/copy-prop/branch.rs
@@ -0,0 +1,27 @@
+//! Tests that we bail out when there are multiple assignments to the same local.
+// unit-test: CopyProp
+fn val() -> i32 {
+    1
+}
+
+fn cond() -> bool {
+    true
+}
+
+// EMIT_MIR branch.foo.CopyProp.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/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff
new file mode 100644
index 00000000000..69acebf7642
--- /dev/null
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff
@@ -0,0 +1,21 @@
+- // MIR for `arg_src` before CopyProp
++ // MIR for `arg_src` after CopyProp
+  
+  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
+      }
+  
+      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
+          _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
+          return;                          // scope 0 at $DIR/copy_propagation_arg.rs:+4:2: +4:2
+      }
+  }
+  
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff
new file mode 100644
index 00000000000..ac4e9a2bfa7
--- /dev/null
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff
@@ -0,0 +1,28 @@
+- // MIR for `bar` before CopyProp
++ // MIR for `bar` after CopyProp
+  
+  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
+                                           // 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
+          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/copy-prop/copy_propagation_arg.baz.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.diff
new file mode 100644
index 00000000000..7ab6ebb7d53
--- /dev/null
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.diff
@@ -0,0 +1,18 @@
+- // MIR for `baz` before CopyProp
++ // MIR for `baz` after CopyProp
+  
+  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
+          _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/copy-prop/copy_propagation_arg.foo.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff
new file mode 100644
index 00000000000..0a3e985e7c2
--- /dev/null
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff
@@ -0,0 +1,28 @@
+- // MIR for `foo` before CopyProp
++ // MIR for `foo` after CopyProp
+  
+  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
+          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
+                                           // 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
+          _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/copy-prop/copy_propagation_arg.rs b/tests/mir-opt/copy-prop/copy_propagation_arg.rs
new file mode 100644
index 00000000000..cc98985f1fd
--- /dev/null
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.rs
@@ -0,0 +1,40 @@
+// Check that CopyProp does not propagate an assignment to a function argument
+// (doing so can break usages of the original argument value)
+// unit-test: CopyProp
+fn dummy(x: u8) -> u8 {
+    x
+}
+
+// EMIT_MIR copy_propagation_arg.foo.CopyProp.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.CopyProp.diff
+fn bar(mut x: u8) {
+    dummy(x);
+    x = 5;
+}
+
+// EMIT_MIR copy_propagation_arg.baz.CopyProp.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.CopyProp.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/copy-prop/cycle.main.CopyProp.diff b/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff
new file mode 100644
index 00000000000..3e61869e82f
--- /dev/null
+++ b/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff
@@ -0,0 +1,60 @@
+- // MIR for `main` before CopyProp
++ // MIR for `main` after CopyProp
+  
+  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
+          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
+              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 => _2;           // 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
+                                           // 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
++         _1 = _2;                         // scope 3 at $DIR/cycle.rs:+4:5: +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
+          _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
+          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
+          return;                          // scope 0 at $DIR/cycle.rs:+7:2: +7:2
+      }
+  }
+  
diff --git a/tests/mir-opt/copy-prop/cycle.rs b/tests/mir-opt/copy-prop/cycle.rs
new file mode 100644
index 00000000000..b74c397269d
--- /dev/null
+++ b/tests/mir-opt/copy-prop/cycle.rs
@@ -0,0 +1,15 @@
+//! Tests that cyclic assignments don't hang CopyProp, and result in reasonable code.
+// unit-test: CopyProp
+fn val() -> i32 {
+    1
+}
+
+// EMIT_MIR cycle.main.CopyProp.diff
+fn main() {
+    let mut x = val();
+    let y = x;
+    let z = y;
+    x = z;
+
+    drop(x);
+}
diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir
new file mode 100644
index 00000000000..d48b04e2de2
--- /dev/null
+++ b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir
@@ -0,0 +1,29 @@
+// MIR for `f` after CopyProp
+
+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 => _2;                   // in scope 1 at $DIR/dead_stores_79191.rs:+1:9: +1:10
+    }
+
+    bb0: {
+        _2 = _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
+        _1 = _2;                         // scope 1 at $DIR/dead_stores_79191.rs:+3:5: +3:10
+        StorageLive(_4);                 // scope 1 at $DIR/dead_stores_79191.rs:+4:8: +4:9
+        _4 = _1;                         // scope 1 at $DIR/dead_stores_79191.rs:+4:8: +4:9
+        _0 = id::<usize>(move _4) -> 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: {
+        StorageDead(_4);                 // scope 1 at $DIR/dead_stores_79191.rs:+4:9: +4:10
+        return;                          // scope 0 at $DIR/dead_stores_79191.rs:+5:2: +5:2
+    }
+}
diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.rs b/tests/mir-opt/copy-prop/dead_stores_79191.rs
new file mode 100644
index 00000000000..e3493b8b7a1
--- /dev/null
+++ b/tests/mir-opt/copy-prop/dead_stores_79191.rs
@@ -0,0 +1,17 @@
+// unit-test: CopyProp
+
+fn id<T>(x: T) -> T {
+    x
+}
+
+// EMIT_MIR dead_stores_79191.f.CopyProp.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/copy-prop/dead_stores_better.f.CopyProp.after.mir b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir
new file mode 100644
index 00000000000..727791f50a4
--- /dev/null
+++ b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir
@@ -0,0 +1,29 @@
+// MIR for `f` after CopyProp
+
+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 => _2;                   // in scope 1 at $DIR/dead_stores_better.rs:+1:9: +1:10
+    }
+
+    bb0: {
+        _2 = _1;                         // scope 0 at $DIR/dead_stores_better.rs:+1:13: +1:14
+        _1 = const 5_usize;              // scope 1 at $DIR/dead_stores_better.rs:+2:5: +2:10
+        _1 = _2;                         // scope 1 at $DIR/dead_stores_better.rs:+3:5: +3:10
+        StorageLive(_4);                 // scope 1 at $DIR/dead_stores_better.rs:+4:8: +4:9
+        _4 = _1;                         // scope 1 at $DIR/dead_stores_better.rs:+4:8: +4:9
+        _0 = id::<usize>(move _4) -> 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: {
+        StorageDead(_4);                 // scope 1 at $DIR/dead_stores_better.rs:+4:9: +4:10
+        return;                          // scope 0 at $DIR/dead_stores_better.rs:+5:2: +5:2
+    }
+}
diff --git a/tests/mir-opt/copy-prop/dead_stores_better.rs b/tests/mir-opt/copy-prop/dead_stores_better.rs
new file mode 100644
index 00000000000..8465b3c9853
--- /dev/null
+++ b/tests/mir-opt/copy-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: CopyProp
+// compile-flags: -Zmir-enable-passes=+DeadStoreElimination
+
+fn id<T>(x: T) -> T {
+    x
+}
+
+// EMIT_MIR dead_stores_better.f.CopyProp.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/copy-prop/move_arg.f.CopyProp.diff b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff
new file mode 100644
index 00000000000..d76bf1cfe7e
--- /dev/null
+++ b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff
@@ -0,0 +1,40 @@
+- // MIR for `f` before CopyProp
++ // MIR for `f` after CopyProp
+  
+  fn f(_1: T) -> () {
+      debug a => _1;                       // in scope 0 at $DIR/move_arg.rs:+0:19: +0:20
+      let mut _0: ();                      // return place in scope 0 at $DIR/move_arg.rs:+0:25: +0:25
+      let _2: T;                           // in scope 0 at $DIR/move_arg.rs:+1:9: +1:10
+      let _3: ();                          // in scope 0 at $DIR/move_arg.rs:+2:5: +2:12
+      let mut _4: T;                       // in scope 0 at $DIR/move_arg.rs:+2:7: +2:8
+      let mut _5: T;                       // in scope 0 at $DIR/move_arg.rs:+2:10: +2:11
+      scope 1 {
+-         debug b => _2;                   // in scope 1 at $DIR/move_arg.rs:+1:9: +1:10
++         debug b => _1;                   // in scope 1 at $DIR/move_arg.rs:+1:9: +1:10
+      }
+  
+      bb0: {
+-         StorageLive(_2);                 // scope 0 at $DIR/move_arg.rs:+1:9: +1:10
+-         _2 = _1;                         // scope 0 at $DIR/move_arg.rs:+1:13: +1:14
+          StorageLive(_3);                 // scope 1 at $DIR/move_arg.rs:+2:5: +2:12
+-         StorageLive(_4);                 // scope 1 at $DIR/move_arg.rs:+2:7: +2:8
+-         _4 = _1;                         // scope 1 at $DIR/move_arg.rs:+2:7: +2:8
+-         StorageLive(_5);                 // scope 1 at $DIR/move_arg.rs:+2:10: +2:11
+-         _5 = _2;                         // scope 1 at $DIR/move_arg.rs:+2:10: +2:11
+-         _3 = g::<T>(move _4, move _5) -> bb1; // scope 1 at $DIR/move_arg.rs:+2:5: +2:12
++         _3 = g::<T>(_1, _1) -> bb1;      // scope 1 at $DIR/move_arg.rs:+2:5: +2:12
+                                           // mir::Constant
+                                           // + span: $DIR/move_arg.rs:7:5: 7:6
+                                           // + literal: Const { ty: fn(T, T) {g::<T>}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+-         StorageDead(_5);                 // scope 1 at $DIR/move_arg.rs:+2:11: +2:12
+-         StorageDead(_4);                 // scope 1 at $DIR/move_arg.rs:+2:11: +2:12
+          StorageDead(_3);                 // scope 1 at $DIR/move_arg.rs:+2:12: +2:13
+          _0 = const ();                   // scope 0 at $DIR/move_arg.rs:+0:25: +3:2
+-         StorageDead(_2);                 // scope 0 at $DIR/move_arg.rs:+3:1: +3:2
+          return;                          // scope 0 at $DIR/move_arg.rs:+3:2: +3:2
+      }
+  }
+  
diff --git a/tests/mir-opt/copy-prop/move_arg.rs b/tests/mir-opt/copy-prop/move_arg.rs
new file mode 100644
index 00000000000..40ae1d8f466
--- /dev/null
+++ b/tests/mir-opt/copy-prop/move_arg.rs
@@ -0,0 +1,15 @@
+// Test that we do not move multiple times from the same local.
+// unit-test: CopyProp
+
+// EMIT_MIR move_arg.f.CopyProp.diff
+pub fn f<T: Copy>(a: T) {
+    let b = a;
+    g(a, b);
+}
+
+#[inline(never)]
+pub fn g<T: Copy>(_: T, _: T) {}
+
+fn main() {
+    f(5)
+}