From 75e2e8c71b4988324ebed0696d0177030d26be1d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 30 Mar 2020 09:56:52 -0400 Subject: [PATCH] Remove unused discriminant reads from MIR bodies Allow the `SimplifyLocals` pass to remove reads of discriminants if the read is never used. --- src/librustc_mir/transform/simplify.rs | 26 +++++++------ ...ocals-removes-unused-discriminant-reads.rs | 12 ++++++ .../rustc.map.SimplifyLocals.diff | 37 +++++++++++++++++++ src/test/mir-opt/simplify_try.rs | 16 ++++---- 4 files changed, 71 insertions(+), 20 deletions(-) create mode 100644 src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs create mode 100644 src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/rustc.map.SimplifyLocals.diff diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index faee077f51e1a..c2029a223b941 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 0000000000000..067fa879b4038 --- /dev/null +++ b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs @@ -0,0 +1,12 @@ +fn map(x: Option>) -> Option> { + 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 0000000000000..bba8bc82fe7d9 --- /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::option::Option> { + 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>; // 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 abac66d95c548..78a7f722538ed 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) -> std::result::Result { // debug x => _1; // let mut _0: std::result::Result; -// 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; // }