From 124b63acf333a6e938be5086d592657e312ea57d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 26 Oct 2020 00:00:00 +0000 Subject: [PATCH 1/6] simplify-locals: Add yet to be optimized test cases --- src/test/mir-opt/simplify-locals.rs | 74 +++++++++++++++++++ .../simplify_locals.c.SimplifyLocals.diff | 28 +++++++ .../simplify_locals.d1.SimplifyLocals.diff | 18 +++++ .../simplify_locals.d2.SimplifyLocals.diff | 42 +++++++++++ .../simplify_locals.r.SimplifyLocals.diff | 31 ++++++++ .../simplify_locals.t1.SimplifyLocals.diff | 25 +++++++ .../simplify_locals.t2.SimplifyLocals.diff | 22 ++++++ .../simplify_locals.t3.SimplifyLocals.diff | 32 ++++++++ .../simplify_locals.t4.SimplifyLocals.diff | 22 ++++++ 9 files changed, 294 insertions(+) create mode 100644 src/test/mir-opt/simplify-locals.rs create mode 100644 src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff create mode 100644 src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff create mode 100644 src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff create mode 100644 src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff create mode 100644 src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff create mode 100644 src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff create mode 100644 src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff create mode 100644 src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff diff --git a/src/test/mir-opt/simplify-locals.rs b/src/test/mir-opt/simplify-locals.rs new file mode 100644 index 0000000000000..dca8f30c89494 --- /dev/null +++ b/src/test/mir-opt/simplify-locals.rs @@ -0,0 +1,74 @@ +// compile-flags: -C overflow-checks=off + +#![feature(box_syntax)] +#![feature(thread_local)] + +#[derive(Copy, Clone)] +enum E { + A, + B, +} + +// EMIT_MIR simplify_locals.c.SimplifyLocals.diff +fn c() { + let bytes = [0u8; 10]; + // Unused cast + let _: &[u8] = &bytes; +} + +// EMIT_MIR simplify_locals.d1.SimplifyLocals.diff +fn d1() { + // Unused set discriminant + let _ = E::A; +} + +// EMIT_MIR simplify_locals.d2.SimplifyLocals.diff +fn d2() { + // Unused set discriminant + {(10, E::A)}.1 = E::B; +} + +// EMIT_MIR simplify_locals.r.SimplifyLocals.diff +fn r() { + let mut a = 1; + // Unused references + let _ = &a; + let _ = &mut a; +} + +#[thread_local] static mut X: u32 = 0; + +// EMIT_MIR simplify_locals.t1.SimplifyLocals.diff +fn t1() { + // Unused thread local + unsafe { X }; +} + +// EMIT_MIR simplify_locals.t2.SimplifyLocals.diff +fn t2() { + // Unused thread local + unsafe { &mut X }; +} + +// EMIT_MIR simplify_locals.t3.SimplifyLocals.diff +fn t3() { + // Unused thread local + unsafe { *&mut X }; +} + +// EMIT_MIR simplify_locals.t4.SimplifyLocals.diff +fn t4() -> u32 { + // Used thread local + unsafe { X + 1 } +} + +fn main() { + c(); + d1(); + d2(); + r(); + t1(); + t2(); + t3(); + t4(); +} diff --git a/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff new file mode 100644 index 0000000000000..dbf6e89469749 --- /dev/null +++ b/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff @@ -0,0 +1,28 @@ +- // MIR for `c` before SimplifyLocals ++ // MIR for `c` after SimplifyLocals + + fn c() -> () { + let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:13:8: 13:8 + let _1: [u8; 10]; // in scope 0 at $DIR/simplify-locals.rs:14:9: 14:14 + let mut _2: &[u8]; // in scope 0 at $DIR/simplify-locals.rs:16:20: 16:26 + let mut _3: &[u8; 10]; // in scope 0 at $DIR/simplify-locals.rs:16:20: 16:26 +- let _4: &[u8; 10]; // in scope 0 at $DIR/simplify-locals.rs:16:20: 16:26 + scope 1 { + debug bytes => _1; // in scope 1 at $DIR/simplify-locals.rs:14:9: 14:14 + scope 2 { + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:14:9: 14:14 + _1 = [const 0_u8; 10]; // scope 0 at $DIR/simplify-locals.rs:14:17: 14:26 + StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26 + _3 = &_1; // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26 + _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26 + StorageDead(_2); // scope 1 at $DIR/simplify-locals.rs:16:26: 16:27 + _0 = const (); // scope 0 at $DIR/simplify-locals.rs:13:8: 17:2 + StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:17:1: 17:2 + return; // scope 0 at $DIR/simplify-locals.rs:17:2: 17:2 + } + } + diff --git a/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff new file mode 100644 index 0000000000000..19811070e2a57 --- /dev/null +++ b/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff @@ -0,0 +1,18 @@ +- // MIR for `d1` before SimplifyLocals ++ // MIR for `d1` after SimplifyLocals + + fn d1() -> () { + let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:20:9: 20:9 + let mut _1: E; // in scope 0 at $DIR/simplify-locals.rs:22:13: 22:17 + scope 1 { + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:22:13: 22:17 + discriminant(_1) = 0; // scope 0 at $DIR/simplify-locals.rs:22:13: 22:17 + StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:22:17: 22:18 + _0 = const (); // scope 0 at $DIR/simplify-locals.rs:20:9: 23:2 + return; // scope 0 at $DIR/simplify-locals.rs:23:2: 23:2 + } + } + diff --git a/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff new file mode 100644 index 0000000000000..91621a102e15c --- /dev/null +++ b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff @@ -0,0 +1,42 @@ +- // MIR for `d2` before SimplifyLocals ++ // MIR for `d2` after SimplifyLocals + + fn d2() -> () { + let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:26:9: 26:9 + let mut _1: E; // in scope 0 at $DIR/simplify-locals.rs:28:22: 28:26 +- let mut _2: (i32, E); // in scope 0 at $DIR/simplify-locals.rs:28:5: 28:17 +- let mut _3: E; // in scope 0 at $DIR/simplify-locals.rs:28:11: 28:15 ++ let mut _2: E; // in scope 0 at $DIR/simplify-locals.rs:28:11: 28:15 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:28:22: 28:26 + discriminant(_1) = 1; // scope 0 at $DIR/simplify-locals.rs:28:22: 28:26 +- StorageLive(_2); // scope 0 at $DIR/simplify-locals.rs:28:5: 28:17 +- StorageLive(_3); // scope 0 at $DIR/simplify-locals.rs:28:11: 28:15 +- discriminant(_3) = 0; // scope 0 at $DIR/simplify-locals.rs:28:11: 28:15 +- (_2.0: i32) = const 10_i32; // scope 0 at $DIR/simplify-locals.rs:28:6: 28:16 +- (_2.1: E) = const E::A; // scope 0 at $DIR/simplify-locals.rs:28:6: 28:16 +- // ty::Const +- // + ty: E +- // + val: Value(Scalar(0x00)) +- // mir::Constant +- // + span: $DIR/simplify-locals.rs:28:6: 28:16 +- // + literal: Const { ty: E, val: Value(Scalar(0x00)) } +- StorageDead(_3); // scope 0 at $DIR/simplify-locals.rs:28:15: 28:16 +- (_2.1: E) = const E::B; // scope 0 at $DIR/simplify-locals.rs:28:5: 28:26 +- // ty::Const +- // + ty: E +- // + val: Value(Scalar(0x01)) +- // mir::Constant +- // + span: $DIR/simplify-locals.rs:28:5: 28:26 +- // + literal: Const { ty: E, val: Value(Scalar(0x01)) } ++ StorageLive(_2); // scope 0 at $DIR/simplify-locals.rs:28:11: 28:15 ++ discriminant(_2) = 0; // scope 0 at $DIR/simplify-locals.rs:28:11: 28:15 ++ StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:28:15: 28:16 + StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:28:25: 28:26 +- StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:28:26: 28:27 + _0 = const (); // scope 0 at $DIR/simplify-locals.rs:26:9: 29:2 + return; // scope 0 at $DIR/simplify-locals.rs:29:2: 29:2 + } + } + diff --git a/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff new file mode 100644 index 0000000000000..a5970585c831f --- /dev/null +++ b/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff @@ -0,0 +1,31 @@ +- // MIR for `r` before SimplifyLocals ++ // MIR for `r` after SimplifyLocals + + fn r() -> () { + let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:32:8: 32:8 + let mut _1: i32; // in scope 0 at $DIR/simplify-locals.rs:33:9: 33:14 + let mut _2: &i32; // in scope 0 at $DIR/simplify-locals.rs:35:13: 35:15 + let mut _3: &mut i32; // in scope 0 at $DIR/simplify-locals.rs:36:13: 36:19 + scope 1 { + debug a => _1; // in scope 1 at $DIR/simplify-locals.rs:33:9: 33:14 + scope 2 { + scope 3 { + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:33:9: 33:14 + _1 = const 1_i32; // scope 0 at $DIR/simplify-locals.rs:33:17: 33:18 + StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:35:13: 35:15 + _2 = &_1; // scope 1 at $DIR/simplify-locals.rs:35:13: 35:15 + StorageDead(_2); // scope 1 at $DIR/simplify-locals.rs:35:15: 35:16 + StorageLive(_3); // scope 2 at $DIR/simplify-locals.rs:36:13: 36:19 + _3 = &mut _1; // scope 2 at $DIR/simplify-locals.rs:36:13: 36:19 + StorageDead(_3); // scope 2 at $DIR/simplify-locals.rs:36:19: 36:20 + _0 = const (); // scope 0 at $DIR/simplify-locals.rs:32:8: 37:2 + StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:37:1: 37:2 + return; // scope 0 at $DIR/simplify-locals.rs:37:2: 37:2 + } + } + diff --git a/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff new file mode 100644 index 0000000000000..a2dc7fd68938f --- /dev/null +++ b/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff @@ -0,0 +1,25 @@ +- // MIR for `t1` before SimplifyLocals ++ // MIR for `t1` after SimplifyLocals + + fn t1() -> () { + let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:42:9: 42:9 +- let _1: u32; // in scope 0 at $DIR/simplify-locals.rs:44:14: 44:15 +- let mut _2: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:44:14: 44:15 ++ let mut _1: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:44:14: 44:15 + scope 1 { + } + + bb0: { +- StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:44:5: 44:17 +- StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:44:14: 44:15 +- _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:44:14: 44:15 +- _1 = (*_2); // scope 1 at $DIR/simplify-locals.rs:44:14: 44:15 +- StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:44:17: 44:18 ++ StorageLive(_1); // scope 1 at $DIR/simplify-locals.rs:44:14: 44:15 ++ _1 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:44:14: 44:15 + StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:44:17: 44:18 + _0 = const (); // scope 0 at $DIR/simplify-locals.rs:42:9: 45:2 + return; // scope 0 at $DIR/simplify-locals.rs:45:2: 45:2 + } + } + diff --git a/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff new file mode 100644 index 0000000000000..c119952c569ab --- /dev/null +++ b/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff @@ -0,0 +1,22 @@ +- // MIR for `t2` before SimplifyLocals ++ // MIR for `t2` after SimplifyLocals + + fn t2() -> () { + let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:48:9: 48:9 + let _1: &mut u32; // in scope 0 at $DIR/simplify-locals.rs:50:14: 50:20 + let mut _2: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:50:19: 50:20 + scope 1 { + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:50:5: 50:22 + StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:50:19: 50:20 + _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:50:19: 50:20 + _1 = &mut (*_2); // scope 1 at $DIR/simplify-locals.rs:50:14: 50:20 + StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:50:22: 50:23 + StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:50:22: 50:23 + _0 = const (); // scope 0 at $DIR/simplify-locals.rs:48:9: 51:2 + return; // scope 0 at $DIR/simplify-locals.rs:51:2: 51:2 + } + } + diff --git a/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff new file mode 100644 index 0000000000000..357b3fc9d3a97 --- /dev/null +++ b/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff @@ -0,0 +1,32 @@ +- // MIR for `t3` before SimplifyLocals ++ // MIR for `t3` after SimplifyLocals + + fn t3() -> () { + let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:54:9: 54:9 +- let _1: u32; // in scope 0 at $DIR/simplify-locals.rs:56:14: 56:21 +- let mut _2: &mut u32; // in scope 0 at $DIR/simplify-locals.rs:56:15: 56:21 +- let mut _3: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:56:20: 56:21 ++ let mut _1: &mut u32; // in scope 0 at $DIR/simplify-locals.rs:56:15: 56:21 ++ let mut _2: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:56:20: 56:21 + scope 1 { + } + + bb0: { +- StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:56:5: 56:23 +- StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:56:15: 56:21 +- StorageLive(_3); // scope 1 at $DIR/simplify-locals.rs:56:20: 56:21 +- _3 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:56:20: 56:21 +- _2 = &mut (*_3); // scope 1 at $DIR/simplify-locals.rs:56:15: 56:21 +- _1 = (*_2); // scope 1 at $DIR/simplify-locals.rs:56:14: 56:21 +- StorageDead(_3); // scope 0 at $DIR/simplify-locals.rs:56:23: 56:24 ++ StorageLive(_1); // scope 1 at $DIR/simplify-locals.rs:56:15: 56:21 ++ StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:56:20: 56:21 ++ _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:56:20: 56:21 ++ _1 = &mut (*_2); // scope 1 at $DIR/simplify-locals.rs:56:15: 56:21 + StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:56:23: 56:24 + StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:56:23: 56:24 + _0 = const (); // scope 0 at $DIR/simplify-locals.rs:54:9: 57:2 + return; // scope 0 at $DIR/simplify-locals.rs:57:2: 57:2 + } + } + diff --git a/src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff new file mode 100644 index 0000000000000..e0e9b3ef4062a --- /dev/null +++ b/src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff @@ -0,0 +1,22 @@ +- // MIR for `t4` before SimplifyLocals ++ // MIR for `t4` after SimplifyLocals + + fn t4() -> u32 { + let mut _0: u32; // return place in scope 0 at $DIR/simplify-locals.rs:60:12: 60:15 + let mut _1: u32; // in scope 0 at $DIR/simplify-locals.rs:62:14: 62:15 + let mut _2: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:62:14: 62:15 + scope 1 { + } + + bb0: { + StorageLive(_1); // scope 1 at $DIR/simplify-locals.rs:62:14: 62:15 + StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:62:14: 62:15 + _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:62:14: 62:15 + _1 = (*_2); // scope 1 at $DIR/simplify-locals.rs:62:14: 62:15 + _0 = Add(move _1, const 1_u32); // scope 1 at $DIR/simplify-locals.rs:62:14: 62:19 + StorageDead(_1); // scope 1 at $DIR/simplify-locals.rs:62:18: 62:19 + StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:63:1: 63:2 + return; // scope 0 at $DIR/simplify-locals.rs:63:2: 63:2 + } + } + From 11269536e294a497b9991382cc9afda1b6ab9de0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 12 Oct 2020 00:00:00 +0000 Subject: [PATCH 2/6] simplify-locals: Represent use counts with u32 --- compiler/rustc_mir/src/transform/simplify.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs index f0c87bcf513cd..bb5245789e001 100644 --- a/compiler/rustc_mir/src/transform/simplify.rs +++ b/compiler/rustc_mir/src/transform/simplify.rs @@ -363,7 +363,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals { /// Construct the mapping while swapping out unused stuff out from the `vec`. fn make_local_map( local_decls: &mut IndexVec, - used_locals: IndexVec, + used_locals: IndexVec, arg_count: usize, ) -> IndexVec> { let mut map: IndexVec> = IndexVec::from_elem(None, &*local_decls); @@ -385,7 +385,7 @@ fn make_local_map( } struct DeclMarker<'a, 'tcx> { - pub local_counts: IndexVec, + pub local_counts: IndexVec, pub body: &'a Body<'tcx>, } @@ -444,13 +444,13 @@ impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> { } struct StatementDeclMarker<'a, 'tcx> { - used_locals: &'a mut IndexVec, + used_locals: &'a mut IndexVec, statement: &'a Statement<'tcx>, } impl<'a, 'tcx> StatementDeclMarker<'a, 'tcx> { pub fn new( - used_locals: &'a mut IndexVec, + used_locals: &'a mut IndexVec, statement: &'a Statement<'tcx>, ) -> Self { Self { used_locals, statement } @@ -475,7 +475,7 @@ impl<'a, 'tcx> Visitor<'tcx> for StatementDeclMarker<'a, 'tcx> { } struct RemoveStatements<'a, 'tcx> { - used_locals: &'a mut IndexVec, + used_locals: &'a mut IndexVec, arg_count: usize, tcx: TyCtxt<'tcx>, modified: bool, @@ -483,7 +483,7 @@ struct RemoveStatements<'a, 'tcx> { impl<'a, 'tcx> RemoveStatements<'a, 'tcx> { fn new( - used_locals: &'a mut IndexVec, + used_locals: &'a mut IndexVec, arg_count: usize, tcx: TyCtxt<'tcx>, ) -> Self { From a6b64be8b51d680ca8185e519be81937c1a98ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 22 Oct 2020 00:00:00 +0000 Subject: [PATCH 3/6] simplify-locals: Unify use count visitors The simplify locals implementation uses two different visitors to update the locals use counts. The DeclMarker calculates the initial use counts. The StatementDeclMarker updates the use counts as statements are being removed from the block. Replace them with a single visitor that can operate in either mode, ensuring consistency of behaviour. Additionally use exhaustive match to clarify what is being optimized. No functional changes intended. --- compiler/rustc_mir/src/transform/simplify.rs | 224 +++++++++---------- 1 file changed, 111 insertions(+), 113 deletions(-) diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs index bb5245789e001..f4ba297b5702c 100644 --- a/compiler/rustc_mir/src/transform/simplify.rs +++ b/compiler/rustc_mir/src/transform/simplify.rs @@ -35,6 +35,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use smallvec::SmallVec; use std::borrow::Cow; +use std::convert::TryInto; pub struct SimplifyCfg { label: String, @@ -322,15 +323,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals { trace!("running SimplifyLocals on {:?}", body.source); // First, we're going to get a count of *actual* uses for every `Local`. - // Take a look at `DeclMarker::visit_local()` to see exactly what is ignored. - let mut used_locals = { - let mut marker = DeclMarker::new(body); - marker.visit_body(&body); - - marker.local_counts - }; - - let arg_count = body.arg_count; + let mut used_locals = UsedLocals::new(body); // Next, we're going to remove any `Local` with zero actual uses. When we remove those // `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals` @@ -338,7 +331,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals { // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a // fixedpoint where there are no more unused locals. loop { - let mut remove_statements = RemoveStatements::new(&mut used_locals, arg_count, tcx); + let mut remove_statements = RemoveStatements::new(&mut used_locals, tcx); remove_statements.visit_body(body); if !remove_statements.modified { @@ -347,7 +340,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals { } // Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the `Local`s. - let map = make_local_map(&mut body.local_decls, used_locals, arg_count); + let map = make_local_map(&mut body.local_decls, &used_locals); // Only bother running the `LocalUpdater` if we actually found locals to remove. if map.iter().any(Option::is_none) { @@ -363,14 +356,14 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals { /// Construct the mapping while swapping out unused stuff out from the `vec`. fn make_local_map( local_decls: &mut IndexVec, - used_locals: IndexVec, - arg_count: usize, + used_locals: &UsedLocals, ) -> IndexVec> { let mut map: IndexVec> = IndexVec::from_elem(None, &*local_decls); let mut used = Local::new(0); - for (alive_index, count) in used_locals.iter_enumerated() { - // The `RETURN_PLACE` and arguments are always live. - if alive_index.as_usize() > arg_count && *count == 0 { + + for alive_index in local_decls.indices() { + // `is_used` treats the `RETURN_PLACE` and arguments as used. + if !used_locals.is_used(alive_index) { continue; } @@ -384,115 +377,125 @@ fn make_local_map( map } -struct DeclMarker<'a, 'tcx> { - pub local_counts: IndexVec, - pub body: &'a Body<'tcx>, +/// Keeps track of used & unused locals. +struct UsedLocals { + increment: bool, + arg_count: u32, + use_count: IndexVec, } -impl<'a, 'tcx> DeclMarker<'a, 'tcx> { - pub fn new(body: &'a Body<'tcx>) -> Self { - Self { local_counts: IndexVec::from_elem(0, &body.local_decls), body } +impl UsedLocals { + /// Determines which locals are used & unused in the given body. + fn new(body: &Body<'_>) -> Self { + let mut this = Self { + increment: true, + arg_count: body.arg_count.try_into().unwrap(), + use_count: IndexVec::from_elem(0, &body.local_decls), + }; + this.visit_body(body); + this } -} -impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> { - fn visit_local(&mut self, local: &Local, ctx: PlaceContext, location: Location) { - // Ignore storage markers altogether, they get removed along with their otherwise unused - // decls. - // FIXME: Extend this to all non-uses. - if ctx.is_storage_marker() { - return; - } + /// Checks if local is used. + /// + /// Return place and arguments are always considered used. + fn is_used(&self, local: Local) -> bool { + trace!("is_used({:?}): use_count: {:?}", local, self.use_count[local]); + local.as_u32() <= self.arg_count || self.use_count[local] != 0 + } - // Ignore stores of constants because `ConstProp` and `CopyProp` can remove uses of many - // of these locals. However, if the local is still needed, then it will be referenced in - // another place and we'll mark it as being used there. - if ctx == PlaceContext::MutatingUse(MutatingUseContext::Store) - || ctx == PlaceContext::MutatingUse(MutatingUseContext::Projection) - { - let block = &self.body.basic_blocks()[location.block]; - if location.statement_index != block.statements.len() { - let stmt = &block.statements[location.statement_index]; - - if let StatementKind::Assign(box (dest, rvalue)) = &stmt.kind { - if !dest.is_indirect() && dest.local == *local { - let can_skip = match rvalue { - Rvalue::Use(_) - | Rvalue::Discriminant(_) - | Rvalue::BinaryOp(_, _, _) - | Rvalue::CheckedBinaryOp(_, _, _) - | Rvalue::Repeat(_, _) - | Rvalue::AddressOf(_, _) - | Rvalue::Len(_) - | Rvalue::UnaryOp(_, _) - | Rvalue::Aggregate(_, _) => true, - - _ => false, - }; - - if can_skip { - trace!("skipping store of {:?} to {:?}", rvalue, dest); - return; - } - } - } - } - } + /// Updates the use counts to reflect the removal of given statement. + fn statement_removed(&mut self, statement: &Statement<'tcx>) { + self.increment = false; - self.local_counts[*local] += 1; + // The location of the statement is irrelevant. + let location = Location { block: START_BLOCK, statement_index: 0 }; + self.visit_statement(statement, location); } -} - -struct StatementDeclMarker<'a, 'tcx> { - used_locals: &'a mut IndexVec, - statement: &'a Statement<'tcx>, -} -impl<'a, 'tcx> StatementDeclMarker<'a, 'tcx> { - pub fn new( - used_locals: &'a mut IndexVec, - statement: &'a Statement<'tcx>, - ) -> Self { - Self { used_locals, statement } + /// Visits a left-hand side of an assignment. + fn visit_lhs(&mut self, place: &Place<'tcx>, location: Location) { + if place.is_indirect() { + // A use, not a definition. + self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location); + } else { + // A definition. Although, it still might use other locals for indexing. + self.super_projection( + place.local, + &place.projection, + PlaceContext::MutatingUse(MutatingUseContext::Projection), + location, + ); + } } } -impl<'a, 'tcx> Visitor<'tcx> for StatementDeclMarker<'a, 'tcx> { - fn visit_local(&mut self, local: &Local, context: PlaceContext, _location: Location) { - // Skip the lvalue for assignments - if let StatementKind::Assign(box (p, _)) = self.statement.kind { - if p.local == *local && context.is_place_assignment() { - return; +impl Visitor<'_> for UsedLocals { + fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { + match statement.kind { + StatementKind::LlvmInlineAsm(..) + | StatementKind::SetDiscriminant { .. } // FIXME: Try to remove those as well. + | StatementKind::Retag(..) + | StatementKind::Coverage(..) + | StatementKind::FakeRead(..) + | StatementKind::AscribeUserType(..) => { + self.super_statement(statement, location); + } + + StatementKind::Nop => {} + + StatementKind::StorageLive(_local) | StatementKind::StorageDead(_local) => {} + + StatementKind::Assign(box (ref place, ref rvalue)) => { + let can_skip = match rvalue { + Rvalue::Use(_) + | Rvalue::Discriminant(_) + | Rvalue::BinaryOp(_, _, _) + | Rvalue::CheckedBinaryOp(_, _, _) + | Rvalue::Repeat(_, _) + | Rvalue::AddressOf(_, _) + | Rvalue::Len(_) + | Rvalue::UnaryOp(_, _) + | Rvalue::Aggregate(_, _) => true, + + Rvalue::Ref(..) + | Rvalue::ThreadLocalRef(..) + | Rvalue::Cast(..) + | Rvalue::NullaryOp(..) => false, + }; + if can_skip { + self.visit_lhs(place, location); + } else { + self.visit_place( + place, + PlaceContext::MutatingUse(MutatingUseContext::Store), + location, + ); + } + self.visit_rvalue(rvalue, location); } } + } - let use_count = &mut self.used_locals[*local]; - // If this is the local we're removing... - if *use_count != 0 { - *use_count -= 1; + fn visit_local(&mut self, local: &Local, _ctx: PlaceContext, _location: Location) { + if self.increment { + self.use_count[*local] += 1; + } else { + assert_ne!(self.use_count[*local], 0); + self.use_count[*local] -= 1; } } } struct RemoveStatements<'a, 'tcx> { - used_locals: &'a mut IndexVec, - arg_count: usize, + used_locals: &'a mut UsedLocals, tcx: TyCtxt<'tcx>, modified: bool, } impl<'a, 'tcx> RemoveStatements<'a, 'tcx> { - fn new( - used_locals: &'a mut IndexVec, - arg_count: usize, - tcx: TyCtxt<'tcx>, - ) -> Self { - Self { used_locals, arg_count, tcx, modified: false } - } - - fn keep_local(&self, l: Local) -> bool { - trace!("keep_local({:?}): count: {:?}", l, self.used_locals[l]); - l.as_usize() <= self.arg_count || self.used_locals[l] != 0 + fn new(used_locals: &'a mut UsedLocals, tcx: TyCtxt<'tcx>) -> Self { + Self { used_locals, tcx, modified: false } } } @@ -503,26 +506,21 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RemoveStatements<'a, 'tcx> { fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) { // Remove unnecessary StorageLive and StorageDead annotations. - let mut i = 0usize; - data.statements.retain(|stmt| { - let keep = match &stmt.kind { - StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => { - self.keep_local(*l) + data.statements.retain(|statement| { + let keep = match &statement.kind { + StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { + self.used_locals.is_used(*local) } - StatementKind::Assign(box (place, _)) => self.keep_local(place.local), + StatementKind::Assign(box (place, _)) => self.used_locals.is_used(place.local), _ => true, }; if !keep { - trace!("removing statement {:?}", stmt); + trace!("removing statement {:?}", statement); self.modified = true; - - let mut visitor = StatementDeclMarker::new(self.used_locals, stmt); - visitor.visit_statement(stmt, Location { block, statement_index: i }); + self.used_locals.statement_removed(statement); } - i += 1; - keep }); From e1e48ae29b52d214f93d816e99056aacb102a90a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 22 Oct 2020 00:00:00 +0000 Subject: [PATCH 4/6] simplify-locals: Change RemoveStatements visitor into a function No functionl changes intended. --- compiler/rustc_mir/src/transform/simplify.rs | 73 +++++++++----------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs index f4ba297b5702c..f88156588e5de 100644 --- a/compiler/rustc_mir/src/transform/simplify.rs +++ b/compiler/rustc_mir/src/transform/simplify.rs @@ -330,14 +330,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals { // count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a // fixedpoint where there are no more unused locals. - loop { - let mut remove_statements = RemoveStatements::new(&mut used_locals, tcx); - remove_statements.visit_body(body); - - if !remove_statements.modified { - break; - } - } + remove_unused_definitions(&mut used_locals, body); // Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the `Local`s. let map = make_local_map(&mut body.local_decls, &used_locals); @@ -487,44 +480,40 @@ impl Visitor<'_> for UsedLocals { } } -struct RemoveStatements<'a, 'tcx> { +/// Removes unused definitions. Updates the used locals to reflect the changes made. +fn remove_unused_definitions<'a, 'tcx>( used_locals: &'a mut UsedLocals, - tcx: TyCtxt<'tcx>, - modified: bool, -} - -impl<'a, 'tcx> RemoveStatements<'a, 'tcx> { - fn new(used_locals: &'a mut UsedLocals, tcx: TyCtxt<'tcx>) -> Self { - Self { used_locals, tcx, modified: false } - } -} - -impl<'a, 'tcx> MutVisitor<'tcx> for RemoveStatements<'a, 'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } + body: &mut Body<'tcx>, +) { + // The use counts are updated as we remove the statements. A local might become unused + // during the retain operation, leading to a temporary inconsistency (storage statements or + // definitions referencing the local might remain). For correctness it is crucial that this + // computation reaches a fixed point. + + let mut modified = true; + while modified { + modified = false; + + for data in body.basic_blocks_mut() { + // Remove unnecessary StorageLive and StorageDead annotations. + data.statements.retain(|statement| { + let keep = match &statement.kind { + StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { + used_locals.is_used(*local) + } + StatementKind::Assign(box (place, _)) => used_locals.is_used(place.local), + _ => true, + }; - fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) { - // Remove unnecessary StorageLive and StorageDead annotations. - data.statements.retain(|statement| { - let keep = match &statement.kind { - StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { - self.used_locals.is_used(*local) + if !keep { + trace!("removing statement {:?}", statement); + modified = true; + used_locals.statement_removed(statement); } - StatementKind::Assign(box (place, _)) => self.used_locals.is_used(place.local), - _ => true, - }; - - if !keep { - trace!("removing statement {:?}", statement); - self.modified = true; - self.used_locals.statement_removed(statement); - } - keep - }); - - self.super_basic_block_data(block, data); + keep + }); + } } } From 52d37826858ee4dad6b66a3060994f41df247770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 17 Oct 2020 00:00:00 +0000 Subject: [PATCH 5/6] simplify-locals: Remove unused set-discriminant statements Update affected ui & incremental tests to use a user declared variable bindings instead of temporaries. The former are preserved because of debuginfo, the latter are not. --- compiler/rustc_mir/src/transform/simplify.rs | 14 +++++++++----- src/test/incremental/hashes/enum_constructors.rs | 2 +- .../mir-opt/simplify_locals.d1.SimplifyLocals.diff | 8 ++++---- .../mir-opt/simplify_locals.d2.SimplifyLocals.diff | 12 ++++-------- ...ops.change_loop_body.PreCodegen.after.32bit.mir | 4 ---- ...ops.change_loop_body.PreCodegen.after.64bit.mir | 4 ---- .../lint/issue-69485-var-size-diffs-too-large.rs | 1 + .../issue-69485-var-size-diffs-too-large.stderr | 2 +- 8 files changed, 20 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs index f88156588e5de..183111877d1ce 100644 --- a/compiler/rustc_mir/src/transform/simplify.rs +++ b/compiler/rustc_mir/src/transform/simplify.rs @@ -427,7 +427,6 @@ impl Visitor<'_> for UsedLocals { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match statement.kind { StatementKind::LlvmInlineAsm(..) - | StatementKind::SetDiscriminant { .. } // FIXME: Try to remove those as well. | StatementKind::Retag(..) | StatementKind::Coverage(..) | StatementKind::FakeRead(..) @@ -467,6 +466,10 @@ impl Visitor<'_> for UsedLocals { } self.visit_rvalue(rvalue, location); } + + StatementKind::SetDiscriminant { ref place, variant_index: _ } => { + self.visit_lhs(place, location); + } } } @@ -481,10 +484,7 @@ impl Visitor<'_> for UsedLocals { } /// Removes unused definitions. Updates the used locals to reflect the changes made. -fn remove_unused_definitions<'a, 'tcx>( - used_locals: &'a mut UsedLocals, - body: &mut Body<'tcx>, -) { +fn remove_unused_definitions<'a, 'tcx>(used_locals: &'a mut UsedLocals, body: &mut Body<'tcx>) { // The use counts are updated as we remove the statements. A local might become unused // during the retain operation, leading to a temporary inconsistency (storage statements or // definitions referencing the local might remain). For correctness it is crucial that this @@ -502,6 +502,10 @@ fn remove_unused_definitions<'a, 'tcx>( used_locals.is_used(*local) } StatementKind::Assign(box (place, _)) => used_locals.is_used(place.local), + + StatementKind::SetDiscriminant { ref place, .. } => { + used_locals.is_used(place.local) + } _ => true, }; diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs index 4161c6a6bfcde..26ff6b109dc32 100644 --- a/src/test/incremental/hashes/enum_constructors.rs +++ b/src/test/incremental/hashes/enum_constructors.rs @@ -7,7 +7,7 @@ // build-pass (FIXME(62277): could be check-pass?) // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans -Zmir-opt-level=0 #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff index 19811070e2a57..76bf175d073d7 100644 --- a/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff @@ -3,14 +3,14 @@ fn d1() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:20:9: 20:9 - let mut _1: E; // in scope 0 at $DIR/simplify-locals.rs:22:13: 22:17 +- let mut _1: E; // in scope 0 at $DIR/simplify-locals.rs:22:13: 22:17 scope 1 { } bb0: { - StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:22:13: 22:17 - discriminant(_1) = 0; // scope 0 at $DIR/simplify-locals.rs:22:13: 22:17 - StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:22:17: 22:18 +- StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:22:13: 22:17 +- discriminant(_1) = 0; // scope 0 at $DIR/simplify-locals.rs:22:13: 22:17 +- StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:22:17: 22:18 _0 = const (); // scope 0 at $DIR/simplify-locals.rs:20:9: 23:2 return; // scope 0 at $DIR/simplify-locals.rs:23:2: 23:2 } diff --git a/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff index 91621a102e15c..c06fa09053ce8 100644 --- a/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff @@ -3,14 +3,13 @@ fn d2() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:26:9: 26:9 - let mut _1: E; // in scope 0 at $DIR/simplify-locals.rs:28:22: 28:26 +- let mut _1: E; // in scope 0 at $DIR/simplify-locals.rs:28:22: 28:26 - let mut _2: (i32, E); // in scope 0 at $DIR/simplify-locals.rs:28:5: 28:17 - let mut _3: E; // in scope 0 at $DIR/simplify-locals.rs:28:11: 28:15 -+ let mut _2: E; // in scope 0 at $DIR/simplify-locals.rs:28:11: 28:15 bb0: { - StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:28:22: 28:26 - discriminant(_1) = 1; // scope 0 at $DIR/simplify-locals.rs:28:22: 28:26 +- StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:28:22: 28:26 +- discriminant(_1) = 1; // scope 0 at $DIR/simplify-locals.rs:28:22: 28:26 - StorageLive(_2); // scope 0 at $DIR/simplify-locals.rs:28:5: 28:17 - StorageLive(_3); // scope 0 at $DIR/simplify-locals.rs:28:11: 28:15 - discriminant(_3) = 0; // scope 0 at $DIR/simplify-locals.rs:28:11: 28:15 @@ -30,10 +29,7 @@ - // mir::Constant - // + span: $DIR/simplify-locals.rs:28:5: 28:26 - // + literal: Const { ty: E, val: Value(Scalar(0x01)) } -+ StorageLive(_2); // scope 0 at $DIR/simplify-locals.rs:28:11: 28:15 -+ discriminant(_2) = 0; // scope 0 at $DIR/simplify-locals.rs:28:11: 28:15 -+ StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:28:15: 28:16 - StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:28:25: 28:26 +- StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:28:25: 28:26 - StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:28:26: 28:27 _0 = const (); // scope 0 at $DIR/simplify-locals.rs:26:9: 29:2 return; // scope 0 at $DIR/simplify-locals.rs:29:2: 29:2 diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.32bit.mir b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.32bit.mir index 523ecb5ec1a3d..dae0cbb65a4b3 100644 --- a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.32bit.mir +++ b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.32bit.mir @@ -3,7 +3,6 @@ fn change_loop_body() -> () { let mut _0: (); // return place in scope 0 at $DIR/while_let_loops.rs:5:27: 5:27 let mut _1: i32; // in scope 0 at $DIR/while_let_loops.rs:6:9: 6:15 - let mut _2: std::option::Option; // in scope 0 at $DIR/while_let_loops.rs:7:28: 7:32 scope 1 { debug _x => _1; // in scope 1 at $DIR/while_let_loops.rs:6:9: 6:15 } @@ -11,10 +10,7 @@ fn change_loop_body() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/while_let_loops.rs:6:9: 6:15 _1 = const 0_i32; // scope 0 at $DIR/while_let_loops.rs:6:18: 6:19 - StorageLive(_2); // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32 - discriminant(_2) = 0; // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32 _0 = const (); // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 - StorageDead(_2); // scope 1 at $DIR/while_let_loops.rs:10:5: 10:6 StorageDead(_1); // scope 0 at $DIR/while_let_loops.rs:11:1: 11:2 return; // scope 0 at $DIR/while_let_loops.rs:11:2: 11:2 } diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.64bit.mir b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.64bit.mir index 523ecb5ec1a3d..dae0cbb65a4b3 100644 --- a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.64bit.mir +++ b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.64bit.mir @@ -3,7 +3,6 @@ fn change_loop_body() -> () { let mut _0: (); // return place in scope 0 at $DIR/while_let_loops.rs:5:27: 5:27 let mut _1: i32; // in scope 0 at $DIR/while_let_loops.rs:6:9: 6:15 - let mut _2: std::option::Option; // in scope 0 at $DIR/while_let_loops.rs:7:28: 7:32 scope 1 { debug _x => _1; // in scope 1 at $DIR/while_let_loops.rs:6:9: 6:15 } @@ -11,10 +10,7 @@ fn change_loop_body() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/while_let_loops.rs:6:9: 6:15 _1 = const 0_i32; // scope 0 at $DIR/while_let_loops.rs:6:18: 6:19 - StorageLive(_2); // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32 - discriminant(_2) = 0; // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32 _0 = const (); // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 - StorageDead(_2); // scope 1 at $DIR/while_let_loops.rs:10:5: 10:6 StorageDead(_1); // scope 0 at $DIR/while_let_loops.rs:11:1: 11:2 return; // scope 0 at $DIR/while_let_loops.rs:11:2: 11:2 } diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs index 49d489d916837..0895f4c18e387 100644 --- a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs +++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs @@ -1,5 +1,6 @@ // build-fail // only-x86_64 +// compile-flags: -Zmir-opt-level=0 fn main() { Bug::V([0; !0]); //~ ERROR is too big for the current diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr index d31ce9cfe0c2b..51eac95afb9ce 100644 --- a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr +++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr @@ -1,5 +1,5 @@ error: the type `[u8; 18446744073709551615]` is too big for the current architecture - --> $DIR/issue-69485-var-size-diffs-too-large.rs:5:12 + --> $DIR/issue-69485-var-size-diffs-too-large.rs:6:12 | LL | Bug::V([0; !0]); | ^^^^^^^ From 4c3e06a0ba557c5915d8c00f23455461549f07f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 17 Oct 2020 00:00:00 +0000 Subject: [PATCH 6/6] simplify-locals: Remove unused assignments regardless of rvalue kind --- compiler/rustc_mir/src/transform/simplify.rs | 26 +------------------ .../instantiation-through-vtable.rs | 3 +-- src/test/codegen/lifetime_start_end.rs | 6 ++--- src/test/codegen/loads.rs | 2 +- src/test/codegen/naked-functions.rs | 2 +- src/test/codegen/refs.rs | 2 +- .../incremental/hashes/closure_expressions.rs | 4 +-- .../simplify_locals.c.SimplifyLocals.diff | 12 ++++----- .../simplify_locals.r.SimplifyLocals.diff | 16 ++++++------ .../simplify_locals.t1.SimplifyLocals.diff | 5 +--- .../simplify_locals.t2.SimplifyLocals.diff | 16 ++++++------ .../simplify_locals.t3.SimplifyLocals.diff | 10 ++----- ...ssue-38591-non-regular-dropck-recursion.rs | 1 + 13 files changed, 36 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs index 183111877d1ce..b7c9a3a8688ec 100644 --- a/compiler/rustc_mir/src/transform/simplify.rs +++ b/compiler/rustc_mir/src/transform/simplify.rs @@ -439,31 +439,7 @@ impl Visitor<'_> for UsedLocals { StatementKind::StorageLive(_local) | StatementKind::StorageDead(_local) => {} StatementKind::Assign(box (ref place, ref rvalue)) => { - let can_skip = match rvalue { - Rvalue::Use(_) - | Rvalue::Discriminant(_) - | Rvalue::BinaryOp(_, _, _) - | Rvalue::CheckedBinaryOp(_, _, _) - | Rvalue::Repeat(_, _) - | Rvalue::AddressOf(_, _) - | Rvalue::Len(_) - | Rvalue::UnaryOp(_, _) - | Rvalue::Aggregate(_, _) => true, - - Rvalue::Ref(..) - | Rvalue::ThreadLocalRef(..) - | Rvalue::Cast(..) - | Rvalue::NullaryOp(..) => false, - }; - if can_skip { - self.visit_lhs(place, location); - } else { - self.visit_place( - place, - PlaceContext::MutatingUse(MutatingUseContext::Store), - location, - ); - } + self.visit_lhs(place, location); self.visit_rvalue(rvalue, location); } diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs index 63966a7ec97b3..ce6757a047cb3 100644 --- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs @@ -1,6 +1,5 @@ // ignore-tidy-linelength -// compile-flags:-Zprint-mono-items=eager -// compile-flags:-Zinline-in-all-cgus +// compile-flags:-Zprint-mono-items=eager -Zinline-in-all-cgus -Zmir-opt-level=0 #![deny(dead_code)] #![feature(start)] diff --git a/src/test/codegen/lifetime_start_end.rs b/src/test/codegen/lifetime_start_end.rs index 9df46bb3dd1b5..da35789ce8de7 100644 --- a/src/test/codegen/lifetime_start_end.rs +++ b/src/test/codegen/lifetime_start_end.rs @@ -1,4 +1,4 @@ -// compile-flags: -O -C no-prepopulate-passes +// compile-flags: -O -C no-prepopulate-passes -Zmir-opt-level=0 #![crate_type = "lib"] @@ -18,10 +18,10 @@ pub fn test() { // CHECK: [[S_b:%[0-9]+]] = bitcast { i32, i32 }** %b to i8* // CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, i8* [[S_b]]) -// CHECK: [[S__4:%[0-9]+]] = bitcast { i32, i32 }* %_4 to i8* +// CHECK: [[S__4:%[0-9]+]] = bitcast { i32, i32 }* %_5 to i8* // CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, i8* [[S__4]]) -// CHECK: [[E__4:%[0-9]+]] = bitcast { i32, i32 }* %_4 to i8* +// CHECK: [[E__4:%[0-9]+]] = bitcast { i32, i32 }* %_5 to i8* // CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, i8* [[E__4]]) // CHECK: [[E_b:%[0-9]+]] = bitcast { i32, i32 }** %b to i8* diff --git a/src/test/codegen/loads.rs b/src/test/codegen/loads.rs index e164f5115fffd..3c9ecec2cbf58 100644 --- a/src/test/codegen/loads.rs +++ b/src/test/codegen/loads.rs @@ -1,4 +1,4 @@ -// compile-flags: -C no-prepopulate-passes +// compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0 #![crate_type = "lib"] diff --git a/src/test/codegen/naked-functions.rs b/src/test/codegen/naked-functions.rs index 493c1b9f0ba6b..5e76f1d67e6f7 100644 --- a/src/test/codegen/naked-functions.rs +++ b/src/test/codegen/naked-functions.rs @@ -1,4 +1,4 @@ -// compile-flags: -C no-prepopulate-passes +// compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0 #![crate_type = "lib"] #![feature(naked_functions)] diff --git a/src/test/codegen/refs.rs b/src/test/codegen/refs.rs index 15f99fd0c22a0..b4cc26f3f9d79 100644 --- a/src/test/codegen/refs.rs +++ b/src/test/codegen/refs.rs @@ -1,4 +1,4 @@ -// compile-flags: -C no-prepopulate-passes +// compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0 #![crate_type = "lib"] diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index 7372cbc915608..4a00a6c72f79e 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -7,7 +7,7 @@ // build-pass (FIXME(62277): could be check-pass?) // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans -Zmir-opt-level=0 #![allow(warnings)] #![feature(rustc_attrs)] @@ -53,7 +53,7 @@ pub fn change_parameter_pattern() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_parameter_pattern() { let _ = |(x,): (u32,)| x; diff --git a/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff index dbf6e89469749..dbac7dff9e2bb 100644 --- a/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff @@ -4,8 +4,8 @@ fn c() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:13:8: 13:8 let _1: [u8; 10]; // in scope 0 at $DIR/simplify-locals.rs:14:9: 14:14 - let mut _2: &[u8]; // in scope 0 at $DIR/simplify-locals.rs:16:20: 16:26 - let mut _3: &[u8; 10]; // in scope 0 at $DIR/simplify-locals.rs:16:20: 16:26 +- let mut _2: &[u8]; // in scope 0 at $DIR/simplify-locals.rs:16:20: 16:26 +- let mut _3: &[u8; 10]; // in scope 0 at $DIR/simplify-locals.rs:16:20: 16:26 - let _4: &[u8; 10]; // in scope 0 at $DIR/simplify-locals.rs:16:20: 16:26 scope 1 { debug bytes => _1; // in scope 1 at $DIR/simplify-locals.rs:14:9: 14:14 @@ -16,10 +16,10 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:14:9: 14:14 _1 = [const 0_u8; 10]; // scope 0 at $DIR/simplify-locals.rs:14:17: 14:26 - StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26 - _3 = &_1; // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26 - _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26 - StorageDead(_2); // scope 1 at $DIR/simplify-locals.rs:16:26: 16:27 +- StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26 +- _3 = &_1; // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26 +- _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26 +- StorageDead(_2); // scope 1 at $DIR/simplify-locals.rs:16:26: 16:27 _0 = const (); // scope 0 at $DIR/simplify-locals.rs:13:8: 17:2 StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:17:1: 17:2 return; // scope 0 at $DIR/simplify-locals.rs:17:2: 17:2 diff --git a/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff index a5970585c831f..85cf398d31693 100644 --- a/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff @@ -4,8 +4,8 @@ fn r() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:32:8: 32:8 let mut _1: i32; // in scope 0 at $DIR/simplify-locals.rs:33:9: 33:14 - let mut _2: &i32; // in scope 0 at $DIR/simplify-locals.rs:35:13: 35:15 - let mut _3: &mut i32; // in scope 0 at $DIR/simplify-locals.rs:36:13: 36:19 +- let mut _2: &i32; // in scope 0 at $DIR/simplify-locals.rs:35:13: 35:15 +- let mut _3: &mut i32; // in scope 0 at $DIR/simplify-locals.rs:36:13: 36:19 scope 1 { debug a => _1; // in scope 1 at $DIR/simplify-locals.rs:33:9: 33:14 scope 2 { @@ -17,12 +17,12 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:33:9: 33:14 _1 = const 1_i32; // scope 0 at $DIR/simplify-locals.rs:33:17: 33:18 - StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:35:13: 35:15 - _2 = &_1; // scope 1 at $DIR/simplify-locals.rs:35:13: 35:15 - StorageDead(_2); // scope 1 at $DIR/simplify-locals.rs:35:15: 35:16 - StorageLive(_3); // scope 2 at $DIR/simplify-locals.rs:36:13: 36:19 - _3 = &mut _1; // scope 2 at $DIR/simplify-locals.rs:36:13: 36:19 - StorageDead(_3); // scope 2 at $DIR/simplify-locals.rs:36:19: 36:20 +- StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:35:13: 35:15 +- _2 = &_1; // scope 1 at $DIR/simplify-locals.rs:35:13: 35:15 +- StorageDead(_2); // scope 1 at $DIR/simplify-locals.rs:35:15: 35:16 +- StorageLive(_3); // scope 2 at $DIR/simplify-locals.rs:36:13: 36:19 +- _3 = &mut _1; // scope 2 at $DIR/simplify-locals.rs:36:13: 36:19 +- StorageDead(_3); // scope 2 at $DIR/simplify-locals.rs:36:19: 36:20 _0 = const (); // scope 0 at $DIR/simplify-locals.rs:32:8: 37:2 StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:37:1: 37:2 return; // scope 0 at $DIR/simplify-locals.rs:37:2: 37:2 diff --git a/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff index a2dc7fd68938f..991a0721cca30 100644 --- a/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff @@ -5,7 +5,6 @@ let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:42:9: 42:9 - let _1: u32; // in scope 0 at $DIR/simplify-locals.rs:44:14: 44:15 - let mut _2: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:44:14: 44:15 -+ let mut _1: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:44:14: 44:15 scope 1 { } @@ -15,9 +14,7 @@ - _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:44:14: 44:15 - _1 = (*_2); // scope 1 at $DIR/simplify-locals.rs:44:14: 44:15 - StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:44:17: 44:18 -+ StorageLive(_1); // scope 1 at $DIR/simplify-locals.rs:44:14: 44:15 -+ _1 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:44:14: 44:15 - StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:44:17: 44:18 +- StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:44:17: 44:18 _0 = const (); // scope 0 at $DIR/simplify-locals.rs:42:9: 45:2 return; // scope 0 at $DIR/simplify-locals.rs:45:2: 45:2 } diff --git a/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff index c119952c569ab..6c9ed96e78ffe 100644 --- a/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff @@ -3,18 +3,18 @@ fn t2() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:48:9: 48:9 - let _1: &mut u32; // in scope 0 at $DIR/simplify-locals.rs:50:14: 50:20 - let mut _2: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:50:19: 50:20 +- let _1: &mut u32; // in scope 0 at $DIR/simplify-locals.rs:50:14: 50:20 +- let mut _2: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:50:19: 50:20 scope 1 { } bb0: { - StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:50:5: 50:22 - StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:50:19: 50:20 - _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:50:19: 50:20 - _1 = &mut (*_2); // scope 1 at $DIR/simplify-locals.rs:50:14: 50:20 - StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:50:22: 50:23 - StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:50:22: 50:23 +- StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:50:5: 50:22 +- StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:50:19: 50:20 +- _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:50:19: 50:20 +- _1 = &mut (*_2); // scope 1 at $DIR/simplify-locals.rs:50:14: 50:20 +- StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:50:22: 50:23 +- StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:50:22: 50:23 _0 = const (); // scope 0 at $DIR/simplify-locals.rs:48:9: 51:2 return; // scope 0 at $DIR/simplify-locals.rs:51:2: 51:2 } diff --git a/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff index 357b3fc9d3a97..2d5fb352f8be3 100644 --- a/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff @@ -6,8 +6,6 @@ - let _1: u32; // in scope 0 at $DIR/simplify-locals.rs:56:14: 56:21 - let mut _2: &mut u32; // in scope 0 at $DIR/simplify-locals.rs:56:15: 56:21 - let mut _3: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:56:20: 56:21 -+ let mut _1: &mut u32; // in scope 0 at $DIR/simplify-locals.rs:56:15: 56:21 -+ let mut _2: *mut u32; // in scope 0 at $DIR/simplify-locals.rs:56:20: 56:21 scope 1 { } @@ -19,12 +17,8 @@ - _2 = &mut (*_3); // scope 1 at $DIR/simplify-locals.rs:56:15: 56:21 - _1 = (*_2); // scope 1 at $DIR/simplify-locals.rs:56:14: 56:21 - StorageDead(_3); // scope 0 at $DIR/simplify-locals.rs:56:23: 56:24 -+ StorageLive(_1); // scope 1 at $DIR/simplify-locals.rs:56:15: 56:21 -+ StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:56:20: 56:21 -+ _2 = &/*tls*/ mut X; // scope 1 at $DIR/simplify-locals.rs:56:20: 56:21 -+ _1 = &mut (*_2); // scope 1 at $DIR/simplify-locals.rs:56:15: 56:21 - StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:56:23: 56:24 - StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:56:23: 56:24 +- StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:56:23: 56:24 +- StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:56:23: 56:24 _0 = const (); // scope 0 at $DIR/simplify-locals.rs:54:9: 57:2 return; // scope 0 at $DIR/simplify-locals.rs:57:2: 57:2 } diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs index 658def0ad5a72..c857eb459b8de 100644 --- a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs +++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs @@ -5,6 +5,7 @@ // build-fail // normalize-stderr-test: ".nll/" -> "/" +// compile-flags: -Zmir-opt-level=0 struct S { t: T,