about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWesley Wiser <wwiser@gmail.com>2020-03-30 09:56:52 -0400
committerWesley Wiser <wwiser@gmail.com>2020-04-02 08:14:34 -0400
commit75e2e8c71b4988324ebed0696d0177030d26be1d (patch)
tree2f3c97f10b64facede2587dbe70ecf7f1fa54679
parent99009bf31992fb9257b84550dbf7cb509f987952 (diff)
downloadrust-75e2e8c71b4988324ebed0696d0177030d26be1d.tar.gz
rust-75e2e8c71b4988324ebed0696d0177030d26be1d.zip
Remove unused discriminant reads from MIR bodies
Allow the `SimplifyLocals` pass to remove reads of discriminants if the
read is never used.
-rw-r--r--src/librustc_mir/transform/simplify.rs26
-rw-r--r--src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs12
-rw-r--r--src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/rustc.map.SimplifyLocals.diff37
-rw-r--r--src/test/mir-opt/simplify_try.rs16
4 files changed, 71 insertions, 20 deletions
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index faee077f51e..c2029a223b9 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -368,18 +368,22 @@ impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> {
             if location.statement_index != block.statements.len() {
                 let stmt = &block.statements[location.statement_index];
 
-                if let StatementKind::Assign(box (p, Rvalue::Use(Operand::Constant(c)))) =
-                    &stmt.kind
-                {
-                    match c.literal.val {
-                        // Keep assignments from unevaluated constants around, since the evaluation
-                        // may report errors, even if the use of the constant is dead code.
-                        ty::ConstKind::Unevaluated(..) => {}
-                        _ => {
-                            if !p.is_indirect() {
-                                trace!("skipping store of const value {:?} to {:?}", c, p);
-                                return;
+                if let StatementKind::Assign(box (dest, rvalue)) = &stmt.kind {
+                    if !dest.is_indirect() && dest.local == *local {
+                        if let Rvalue::Use(Operand::Constant(c)) = rvalue {
+                            match c.literal.val {
+                                // Keep assignments from unevaluated constants around, since the
+                                // evaluation may report errors, even if the use of the constant
+                                // is dead code.
+                                ty::ConstKind::Unevaluated(..) => {}
+                                _ => {
+                                    trace!("skipping store of const value {:?} to {:?}", c, dest);
+                                    return;
+                                }
                             }
+                        } else if let Rvalue::Discriminant(d) = rvalue {
+                            trace!("skipping store of discriminant value {:?} to {:?}", d, dest);
+                            return;
                         }
                     }
                 }
diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs
new file mode 100644
index 00000000000..067fa879b40
--- /dev/null
+++ b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs
@@ -0,0 +1,12 @@
+fn map(x: Option<Box<()>>) -> Option<Box<()>> {
+    match x {
+        None => None,
+        Some(x) => Some(x),
+    }
+}
+
+fn main() {
+    map(None);
+}
+
+// EMIT_MIR rustc.map.SimplifyLocals.diff
diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/rustc.map.SimplifyLocals.diff b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/rustc.map.SimplifyLocals.diff
new file mode 100644
index 00000000000..bba8bc82fe7
--- /dev/null
+++ b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/rustc.map.SimplifyLocals.diff
@@ -0,0 +1,37 @@
+- // MIR for `map` before SimplifyLocals
++ // MIR for `map` after SimplifyLocals
+  
+  fn map(_1: std::option::Option<std::boxed::Box<()>>) -> std::option::Option<std::boxed::Box<()>> {
+      debug x => _1;                       // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:1:8: 1:9
+      let mut _0: std::option::Option<std::boxed::Box<()>>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:1:31: 1:46
+      let mut _2: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
+      let _3: std::boxed::Box<()>;         // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15
+-     let mut _4: std::boxed::Box<()>;     // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:25: 4:26
+-     let mut _5: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
+-     let mut _6: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
+      scope 1 {
+          debug x => _3;                   // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15
+      }
+  
+      bb0: {
+          _2 = discriminant(_1);           // bb0[0]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
+          switchInt(move _2) -> [0isize: bb2, otherwise: bb1]; // bb0[1]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
+      }
+  
+      bb1: {
+          _0 = move _1;                    // bb1[0]: scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:20: 4:27
+          goto -> bb3;                     // bb1[1]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6
+      }
+  
+      bb2: {
+          discriminant(_0) = 0;            // bb2[0]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21
+          goto -> bb3;                     // bb2[1]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6
+      }
+  
+      bb3: {
+-         _5 = discriminant(_1);           // bb3[0]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
+-         return;                          // bb3[1]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:2: 6:2
++         return;                          // bb3[0]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:2: 6:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs
index abac66d95c5..78a7f722538 100644
--- a/src/test/mir-opt/simplify_try.rs
+++ b/src/test/mir-opt/simplify_try.rs
@@ -183,25 +183,24 @@ fn main() {
 // fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
 //     debug x => _1;
 //     let mut _0: std::result::Result<u32, i32>;
-//     let mut _2: isize;
-//     let _3: i32;
-//     let _4: u32;
+//     let _2: i32;
+//     let _3: u32;
 //     scope 1 {
-//         debug y => _4;
+//         debug y => _3;
 //     }
 //     scope 2 {
-//         debug err => _3;
+//         debug err => _2;
 //         scope 3 {
 //             scope 7 {
-//                 debug t => _3;
+//                 debug t => _2;
 //             }
 //             scope 8 {
-//                 debug v => _3;
+//                 debug v => _2;
 //             }
 //         }
 //     }
 //     scope 4 {
-//         debug val => _4;
+//         debug val => _3;
 //         scope 5 {
 //         }
 //     }
@@ -209,7 +208,6 @@ fn main() {
 //         debug self => _1;
 //     }
 //     bb0: {
-//         _2 = discriminant(_1);
 //         _0 = move _1;
 //         return;
 //     }