about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs49
-rw-r--r--tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff41
-rw-r--r--tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff37
-rw-r--r--tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff35
-rw-r--r--tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff35
-rw-r--r--tests/mir-opt/copy-prop/reborrow.rs39
6 files changed, 222 insertions, 14 deletions
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index c1e7f62dea5..0bb97c4fc09 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -179,6 +179,25 @@ struct SsaVisitor {
     assignment_order: Vec<Local>,
 }
 
+impl SsaVisitor {
+    fn check_assignment_dominates(&mut self, local: Local, loc: Location) {
+        let set = &mut self.assignments[local];
+        let assign_dominates = match *set {
+            Set1::Empty | Set1::Many => false,
+            Set1::One(LocationExtended::Arg) => true,
+            Set1::One(LocationExtended::Plain(assign)) => {
+                assign.successor_within_block().dominates(loc, &self.dominators)
+            }
+        };
+        // We are visiting a use that is not dominated by an assignment.
+        // Either there is a cycle involved, or we are reading for uninitialized local.
+        // Bail out.
+        if !assign_dominates {
+            *set = Set1::Many;
+        }
+    }
+}
+
 impl<'tcx> Visitor<'tcx> for SsaVisitor {
     fn visit_local(&mut self, local: Local, ctxt: PlaceContext, loc: Location) {
         match ctxt {
@@ -192,24 +211,26 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor {
             // Immutable borrows are taken into account in `SsaLocals::new` by
             // removing non-freeze locals.
             PlaceContext::NonMutatingUse(_) => {
-                let set = &mut self.assignments[local];
-                let assign_dominates = match *set {
-                    Set1::Empty | Set1::Many => false,
-                    Set1::One(LocationExtended::Arg) => true,
-                    Set1::One(LocationExtended::Plain(assign)) => {
-                        assign.successor_within_block().dominates(loc, &self.dominators)
-                    }
-                };
-                // We are visiting a use that is not dominated by an assignment.
-                // Either there is a cycle involved, or we are reading for uninitialized local.
-                // Bail out.
-                if !assign_dominates {
-                    *set = Set1::Many;
-                }
+                self.check_assignment_dominates(local, loc);
             }
             PlaceContext::NonUse(_) => {}
         }
     }
+
+    fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, loc: Location) {
+        if place.projection.first() == Some(&PlaceElem::Deref) {
+            // Do not do anything for storage statements and debuginfo.
+            if ctxt.is_use() {
+                // A use through a `deref` only reads from the local, and cannot write to it.
+                let new_ctxt = PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection);
+
+                self.visit_projection(place.as_ref(), new_ctxt, loc);
+                self.check_assignment_dominates(place.local, loc);
+            }
+            return;
+        }
+        self.super_place(place, ctxt, loc);
+    }
 }
 
 #[instrument(level = "trace", skip(ssa, body))]
diff --git a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff
new file mode 100644
index 00000000000..62ef6ca86c6
--- /dev/null
+++ b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff
@@ -0,0 +1,41 @@
+- // MIR for `demiraw` before CopyProp
++ // MIR for `demiraw` after CopyProp
+  
+  fn demiraw(_1: u8) -> () {
+      debug x => _1;                       // in scope 0 at $DIR/reborrow.rs:+0:12: +0:17
+      let mut _0: ();                      // return place in scope 0 at $DIR/reborrow.rs:+0:23: +0:23
+      let _2: *mut u8;                     // in scope 0 at $DIR/reborrow.rs:+1:9: +1:10
+      let mut _4: &mut u8;                 // in scope 0 at $DIR/reborrow.rs:+2:22: +2:29
+      scope 1 {
+          debug a => _2;                   // in scope 1 at $DIR/reborrow.rs:+1:9: +1:10
+          let _3: &mut u8;                 // in scope 1 at $DIR/reborrow.rs:+2:9: +2:10
+          scope 2 {
+              debug b => _3;               // in scope 2 at $DIR/reborrow.rs:+2:9: +2:10
+              let _5: *mut u8;             // in scope 2 at $DIR/reborrow.rs:+3:9: +3:10
+              scope 4 {
+-                 debug c => _5;           // in scope 4 at $DIR/reborrow.rs:+3:9: +3:10
++                 debug c => _2;           // in scope 4 at $DIR/reborrow.rs:+3:9: +3:10
+              }
+          }
+          scope 3 {
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);                 // scope 0 at $DIR/reborrow.rs:+1:9: +1:10
+          _2 = &raw mut _1;                // scope 0 at $DIR/reborrow.rs:+1:13: +1:23
+          StorageLive(_3);                 // scope 1 at $DIR/reborrow.rs:+2:9: +2:10
+          StorageLive(_4);                 // scope 1 at $DIR/reborrow.rs:+2:22: +2:29
+          _4 = &mut (*_2);                 // scope 3 at $DIR/reborrow.rs:+2:22: +2:29
+          _3 = &mut (*_4);                 // scope 1 at $DIR/reborrow.rs:+2:22: +2:29
+          StorageDead(_4);                 // scope 1 at $DIR/reborrow.rs:+2:31: +2:32
+-         StorageLive(_5);                 // scope 2 at $DIR/reborrow.rs:+3:9: +3:10
+-         _5 = _2;                         // scope 2 at $DIR/reborrow.rs:+3:13: +3:14
+          _0 = const ();                   // scope 0 at $DIR/reborrow.rs:+0:23: +4:2
+-         StorageDead(_5);                 // scope 2 at $DIR/reborrow.rs:+4:1: +4:2
+          StorageDead(_3);                 // scope 1 at $DIR/reborrow.rs:+4:1: +4:2
+-         StorageDead(_2);                 // scope 0 at $DIR/reborrow.rs:+4:1: +4:2
+          return;                          // scope 0 at $DIR/reborrow.rs:+4:2: +4:2
+      }
+  }
+  
diff --git a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff
new file mode 100644
index 00000000000..5d620402eaa
--- /dev/null
+++ b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff
@@ -0,0 +1,37 @@
+- // MIR for `miraw` before CopyProp
++ // MIR for `miraw` after CopyProp
+  
+  fn miraw(_1: u8) -> () {
+      debug x => _1;                       // in scope 0 at $DIR/reborrow.rs:+0:10: +0:15
+      let mut _0: ();                      // return place in scope 0 at $DIR/reborrow.rs:+0:21: +0:21
+      let _2: *mut u8;                     // in scope 0 at $DIR/reborrow.rs:+1:9: +1:10
+      scope 1 {
+          debug a => _2;                   // in scope 1 at $DIR/reborrow.rs:+1:9: +1:10
+          let _3: *mut u8;                 // in scope 1 at $DIR/reborrow.rs:+2:9: +2:10
+          scope 2 {
+              debug b => _3;               // in scope 2 at $DIR/reborrow.rs:+2:9: +2:10
+              let _4: *mut u8;             // in scope 2 at $DIR/reborrow.rs:+3:9: +3:10
+              scope 4 {
+-                 debug c => _4;           // in scope 4 at $DIR/reborrow.rs:+3:9: +3:10
++                 debug c => _2;           // in scope 4 at $DIR/reborrow.rs:+3:9: +3:10
+              }
+          }
+          scope 3 {
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);                 // scope 0 at $DIR/reborrow.rs:+1:9: +1:10
+          _2 = &raw mut _1;                // scope 0 at $DIR/reborrow.rs:+1:13: +1:23
+          StorageLive(_3);                 // scope 1 at $DIR/reborrow.rs:+2:9: +2:10
+          _3 = &raw mut (*_2);             // scope 3 at $DIR/reborrow.rs:+2:22: +2:33
+-         StorageLive(_4);                 // scope 2 at $DIR/reborrow.rs:+3:9: +3:10
+-         _4 = _2;                         // scope 2 at $DIR/reborrow.rs:+3:13: +3:14
+          _0 = const ();                   // scope 0 at $DIR/reborrow.rs:+0:21: +4:2
+-         StorageDead(_4);                 // scope 2 at $DIR/reborrow.rs:+4:1: +4:2
+          StorageDead(_3);                 // scope 1 at $DIR/reborrow.rs:+4:1: +4:2
+-         StorageDead(_2);                 // scope 0 at $DIR/reborrow.rs:+4:1: +4:2
+          return;                          // scope 0 at $DIR/reborrow.rs:+4:2: +4:2
+      }
+  }
+  
diff --git a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff
new file mode 100644
index 00000000000..2c00c06ffea
--- /dev/null
+++ b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff
@@ -0,0 +1,35 @@
+- // MIR for `remut` before CopyProp
++ // MIR for `remut` after CopyProp
+  
+  fn remut(_1: u8) -> () {
+      debug x => _1;                       // in scope 0 at $DIR/reborrow.rs:+0:10: +0:15
+      let mut _0: ();                      // return place in scope 0 at $DIR/reborrow.rs:+0:21: +0:21
+      let _2: &mut u8;                     // in scope 0 at $DIR/reborrow.rs:+1:9: +1:10
+      scope 1 {
+          debug a => _2;                   // in scope 1 at $DIR/reborrow.rs:+1:9: +1:10
+          let _3: &mut u8;                 // in scope 1 at $DIR/reborrow.rs:+2:9: +2:10
+          scope 2 {
+              debug b => _3;               // in scope 2 at $DIR/reborrow.rs:+2:9: +2:10
+              let _4: &mut u8;             // in scope 2 at $DIR/reborrow.rs:+3:9: +3:10
+              scope 3 {
+-                 debug c => _4;           // in scope 3 at $DIR/reborrow.rs:+3:9: +3:10
++                 debug c => _2;           // in scope 3 at $DIR/reborrow.rs:+3:9: +3:10
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);                 // scope 0 at $DIR/reborrow.rs:+1:9: +1:10
+          _2 = &mut _1;                    // scope 0 at $DIR/reborrow.rs:+1:13: +1:19
+          StorageLive(_3);                 // scope 1 at $DIR/reborrow.rs:+2:9: +2:10
+          _3 = &mut (*_2);                 // scope 1 at $DIR/reborrow.rs:+2:13: +2:20
+-         StorageLive(_4);                 // scope 2 at $DIR/reborrow.rs:+3:9: +3:10
+-         _4 = move _2;                    // scope 2 at $DIR/reborrow.rs:+3:13: +3:14
+          _0 = const ();                   // scope 0 at $DIR/reborrow.rs:+0:21: +4:2
+-         StorageDead(_4);                 // scope 2 at $DIR/reborrow.rs:+4:1: +4:2
+          StorageDead(_3);                 // scope 1 at $DIR/reborrow.rs:+4:1: +4:2
+-         StorageDead(_2);                 // scope 0 at $DIR/reborrow.rs:+4:1: +4:2
+          return;                          // scope 0 at $DIR/reborrow.rs:+4:2: +4:2
+      }
+  }
+  
diff --git a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff
new file mode 100644
index 00000000000..bc74ae05ce2
--- /dev/null
+++ b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff
@@ -0,0 +1,35 @@
+- // MIR for `reraw` before CopyProp
++ // MIR for `reraw` after CopyProp
+  
+  fn reraw(_1: u8) -> () {
+      debug x => _1;                       // in scope 0 at $DIR/reborrow.rs:+0:10: +0:15
+      let mut _0: ();                      // return place in scope 0 at $DIR/reborrow.rs:+0:21: +0:21
+      let _2: &mut u8;                     // in scope 0 at $DIR/reborrow.rs:+1:9: +1:10
+      scope 1 {
+          debug a => _2;                   // in scope 1 at $DIR/reborrow.rs:+1:9: +1:10
+          let _3: *mut u8;                 // in scope 1 at $DIR/reborrow.rs:+2:9: +2:10
+          scope 2 {
+              debug b => _3;               // in scope 2 at $DIR/reborrow.rs:+2:9: +2:10
+              let _4: &mut u8;             // in scope 2 at $DIR/reborrow.rs:+3:9: +3:10
+              scope 3 {
+-                 debug c => _4;           // in scope 3 at $DIR/reborrow.rs:+3:9: +3:10
++                 debug c => _2;           // in scope 3 at $DIR/reborrow.rs:+3:9: +3:10
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);                 // scope 0 at $DIR/reborrow.rs:+1:9: +1:10
+          _2 = &mut _1;                    // scope 0 at $DIR/reborrow.rs:+1:13: +1:19
+          StorageLive(_3);                 // scope 1 at $DIR/reborrow.rs:+2:9: +2:10
+          _3 = &raw mut (*_2);             // scope 1 at $DIR/reborrow.rs:+2:13: +2:24
+-         StorageLive(_4);                 // scope 2 at $DIR/reborrow.rs:+3:9: +3:10
+-         _4 = move _2;                    // scope 2 at $DIR/reborrow.rs:+3:13: +3:14
+          _0 = const ();                   // scope 0 at $DIR/reborrow.rs:+0:21: +4:2
+-         StorageDead(_4);                 // scope 2 at $DIR/reborrow.rs:+4:1: +4:2
+          StorageDead(_3);                 // scope 1 at $DIR/reborrow.rs:+4:1: +4:2
+-         StorageDead(_2);                 // scope 0 at $DIR/reborrow.rs:+4:1: +4:2
+          return;                          // scope 0 at $DIR/reborrow.rs:+4:2: +4:2
+      }
+  }
+  
diff --git a/tests/mir-opt/copy-prop/reborrow.rs b/tests/mir-opt/copy-prop/reborrow.rs
new file mode 100644
index 00000000000..a1624215feb
--- /dev/null
+++ b/tests/mir-opt/copy-prop/reborrow.rs
@@ -0,0 +1,39 @@
+// Check that CopyProp considers reborrows as not mutating the pointer.
+// unit-test: CopyProp
+
+#![feature(raw_ref_op)]
+
+// EMIT_MIR reborrow.remut.CopyProp.diff
+fn remut(mut x: u8) {
+    let a = &mut x;
+    let b = &mut *a; //< this cannot mutate a.
+    let c = a; //< so `c` and `a` can be merged.
+}
+
+// EMIT_MIR reborrow.reraw.CopyProp.diff
+fn reraw(mut x: u8) {
+    let a = &mut x;
+    let b = &raw mut *a; //< this cannot mutate a.
+    let c = a; //< so `c` and `a` can be merged.
+}
+
+// EMIT_MIR reborrow.miraw.CopyProp.diff
+fn miraw(mut x: u8) {
+    let a = &raw mut x;
+    let b = unsafe { &raw mut *a }; //< this cannot mutate a.
+    let c = a; //< so `c` and `a` can be merged.
+}
+
+// EMIT_MIR reborrow.demiraw.CopyProp.diff
+fn demiraw(mut x: u8) {
+    let a = &raw mut x;
+    let b = unsafe { &mut *a }; //< this cannot mutate a.
+    let c = a; //< so `c` and `a` can be merged.
+}
+
+fn main() {
+    remut(0);
+    reraw(0);
+    miraw(0);
+    demiraw(0);
+}