Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebase and fixup #80493: Remove MIR assignments to ZST types #83118

Merged
merged 6 commits into from
Mar 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion compiler/rustc_codegen_ssa/src/mir/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,18 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
Some(assignment_location) => {
assignment_location.dominates(location, &self.dominators)
}
None => false,
None => {
debug!("No first assignment found for {:?}", local);
// We have not seen any assignment to the local yet,
// but before marking not_ssa, check if it is a ZST,
// in which case we don't need to initialize the local.
let ty = self.fx.mir.local_decls[local].ty;
let ty = self.fx.monomorphize(ty);

let is_zst = self.fx.cx.layout_of(ty).is_zst();
debug!("is_zst: {}", is_zst);
is_zst
}
};
if !ssa_read {
self.not_ssa(local);
Expand Down
79 changes: 52 additions & 27 deletions compiler/rustc_mir/src/transform/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ use crate::transform::MirPass;
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::ParamEnv;
use rustc_middle::ty::TyCtxt;
use smallvec::SmallVec;
use std::borrow::Cow;
use std::convert::TryInto;
use std::{borrow::Cow, convert::TryInto};

pub struct SimplifyCfg {
label: String,
Expand Down Expand Up @@ -326,7 +326,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals {

pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
// First, we're going to get a count of *actual* uses for every `Local`.
let mut used_locals = UsedLocals::new(body);
let mut used_locals = UsedLocals::new(body, tcx);

// 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`
Expand All @@ -336,7 +336,8 @@ pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
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);
let arg_count = body.arg_count.try_into().unwrap();
let map = make_local_map(&mut body.local_decls, &used_locals, arg_count);

// Only bother running the `LocalUpdater` if we actually found locals to remove.
if map.iter().any(Option::is_none) {
Expand All @@ -349,54 +350,61 @@ pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
}

/// Construct the mapping while swapping out unused stuff out from the `vec`.
fn make_local_map<V>(
fn make_local_map<'tcx, V>(
local_decls: &mut IndexVec<Local, V>,
used_locals: &UsedLocals,
used_locals: &UsedLocals<'tcx>,
arg_count: u32,
) -> IndexVec<Local, Option<Local>> {
let mut map: IndexVec<Local, Option<Local>> = IndexVec::from_elem(None, &*local_decls);
let mut map: IndexVec<Local, Option<Local>> = IndexVec::from_elem(None, local_decls);
let mut used = Local::new(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;
}

map[alive_index] = Some(used);
if alive_index != used {
local_decls.swap(alive_index, used);
// When creating the local map treat the `RETURN_PLACE` and arguments as used.
if alive_index.as_u32() <= arg_count || used_locals.is_used(alive_index) {
map[alive_index] = Some(used);
if alive_index != used {
local_decls.swap(alive_index, used);
}
used.increment_by(1);
}
used.increment_by(1);
}
local_decls.truncate(used.index());
map
}

/// Keeps track of used & unused locals.
struct UsedLocals {
struct UsedLocals<'tcx> {
increment: bool,
arg_count: u32,
use_count: IndexVec<Local, u32>,
is_static: bool,
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
param_env: ParamEnv<'tcx>,
tcx: TyCtxt<'tcx>,
}

impl UsedLocals {
impl UsedLocals<'tcx> {
/// Determines which locals are used & unused in the given body.
fn new(body: &Body<'_>) -> Self {
fn new(body: &Body<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
let def_id = body.source.def_id();
let is_static = tcx.is_static(def_id);
let param_env = tcx.param_env(def_id);
let local_decls = body.local_decls.clone();
let mut this = Self {
increment: true,
arg_count: body.arg_count.try_into().unwrap(),
use_count: IndexVec::from_elem(0, &body.local_decls),
is_static,
local_decls,
param_env,
tcx,
};
this.visit_body(body);
this
}

/// 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
self.use_count[local] != 0
}

/// Updates the use counts to reflect the removal of given statement.
Expand Down Expand Up @@ -424,7 +432,7 @@ impl UsedLocals {
}
}

impl Visitor<'_> for UsedLocals {
impl Visitor<'tcx> for UsedLocals<'tcx> {
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
match statement.kind {
StatementKind::LlvmInlineAsm(..)
Expand All @@ -451,7 +459,21 @@ impl Visitor<'_> for UsedLocals {
}
}

fn visit_local(&mut self, local: &Local, _ctx: PlaceContext, _location: Location) {
fn visit_local(&mut self, local: &Local, ctx: PlaceContext, _location: Location) {
debug!("local: {:?} is_static: {:?}, ctx: {:?}", local, self.is_static, ctx);
// Do not count _0 as a used in `return;` if it is a ZST.
let return_place = *local == RETURN_PLACE
&& matches!(ctx, PlaceContext::NonMutatingUse(visit::NonMutatingUseContext::Move));
if !self.is_static && return_place {
let ty = self.local_decls[*local].ty;
let param_env_and = self.param_env.and(ty);
if let Ok(layout) = self.tcx.layout_of(param_env_and) {
debug!("layout.is_zst: {:?}", layout.is_zst());
if layout.is_zst() {
return;
}
}
}
if self.increment {
self.use_count[*local] += 1;
} else {
Expand All @@ -462,7 +484,10 @@ 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<'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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ fn hello() -> () {
let mut _0: (); // return place in scope 0 at $DIR/control-flow-simplification.rs:11:14: 11:14

bb0: {
_0 = const (); // scope 0 at $DIR/control-flow-simplification.rs:14:6: 14:6
return; // scope 0 at $DIR/control-flow-simplification.rs:15:2: 15:2
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ fn main() -> () {
_2 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:14:9: 14:10
_3 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:38
_0 = const (); // scope 0 at $DIR/optimizes_into_variable.rs:11:11: 15:2
StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:15:1: 15:2
StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:15:1: 15:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:15:1: 15:2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ fn main() -> () {
_2 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:14:9: 14:10
_3 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:38
_0 = const (); // scope 0 at $DIR/optimizes_into_variable.rs:11:11: 15:2
StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:15:1: 15:2
StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:15:1: 15:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:15:1: 15:2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
StorageLive(_6); // scope 3 at $DIR/cycle.rs:14:10: 14:11
- _6 = _1; // scope 3 at $DIR/cycle.rs:14:10: 14:11
+ _6 = _4; // scope 3 at $DIR/cycle.rs:14:10: 14:11
_5 = const (); // scope 4 at $DIR/cycle.rs:14:5: 14:12
StorageDead(_6); // scope 3 at $DIR/cycle.rs:14:11: 14:12
StorageDead(_5); // scope 3 at $DIR/cycle.rs:14:12: 14:13
_0 = const (); // scope 0 at $DIR/cycle.rs:8:11: 15:2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
StorageLive(_3); // scope 1 at $DIR/union.rs:15:5: 15:27
StorageLive(_4); // scope 1 at $DIR/union.rs:15:10: 15:26
_4 = (_1.0: u32); // scope 2 at $DIR/union.rs:15:19: 15:24
_3 = const (); // scope 3 at $DIR/union.rs:15:5: 15:27
StorageDead(_4); // scope 1 at $DIR/union.rs:15:26: 15:27
StorageDead(_3); // scope 1 at $DIR/union.rs:15:27: 15:28
_0 = const (); // scope 0 at $DIR/union.rs:8:11: 16:2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
- }
-
- bb1: {
+ _1 = const (); // scope 1 at $DIR/inline-compatibility.rs:24:5: 24:18
StorageDead(_1); // scope 0 at $DIR/inline-compatibility.rs:24:18: 24:19
_0 = const (); // scope 0 at $DIR/inline-compatibility.rs:23:37: 25:2
return; // scope 0 at $DIR/inline-compatibility.rs:25:2: 25:2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
- }
-
- bb1: {
+ _1 = const (); // scope 1 at $DIR/inline-compatibility.rs:13:5: 13:21
StorageDead(_1); // scope 0 at $DIR/inline-compatibility.rs:13:21: 13:22
_0 = const (); // scope 0 at $DIR/inline-compatibility.rs:12:40: 14:2
return; // scope 0 at $DIR/inline-compatibility.rs:14:2: 14:2
Expand Down
1 change: 0 additions & 1 deletion src/test/mir-opt/inline/inline_cycle.two.Inline.diff
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
+ StorageDead(_5); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ StorageDead(_4); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ StorageDead(_3); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ _1 = const (); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ StorageDead(_2); // scope 0 at $DIR/inline-cycle.rs:49:5: 49:12
StorageDead(_1); // scope 0 at $DIR/inline-cycle.rs:49:12: 49:13
_0 = const (); // scope 0 at $DIR/inline-cycle.rs:48:10: 50:2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
- }
-
- bb3: {
+ _3 = const (); // scope 1 at $DIR/inline-instruction-set.rs:53:5: 53:30
StorageDead(_3); // scope 0 at $DIR/inline-instruction-set.rs:53:30: 53:31
_0 = const (); // scope 0 at $DIR/inline-instruction-set.rs:50:18: 54:2
return; // scope 0 at $DIR/inline-instruction-set.rs:54:2: 54:2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
- }
-
- bb2: {
+ _2 = const (); // scope 1 at $DIR/inline-instruction-set.rs:43:5: 43:26
StorageDead(_2); // scope 0 at $DIR/inline-instruction-set.rs:43:26: 43:27
StorageLive(_3); // scope 0 at $DIR/inline-instruction-set.rs:46:5: 46:30
- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline-instruction-set.rs:46:5: 46:30
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ fn main() -> () {

bb4: {
StorageDead(_5); // scope 1 at $DIR/inline-options.rs:10:5: 10:21
_2 = const (); // scope 1 at $DIR/inline-options.rs:10:5: 10:21
StorageDead(_2); // scope 0 at $DIR/inline-options.rs:10:21: 10:22
_0 = const (); // scope 0 at $DIR/inline-options.rs:8:11: 11:2
return; // scope 0 at $DIR/inline-options.rs:11:2: 11:2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ fn main() -> () {
_5 = move (_3.0: ()); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
StorageLive(_6); // scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
_6 = const (); // scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
_0 = const (); // scope 3 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
StorageDead(_6); // scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
StorageDead(_5); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
StorageDead(_4); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:9: 6:10
Expand Down
1 change: 0 additions & 1 deletion src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@
StorageDead(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
StorageDead(_4); // scope 1 at $DIR/issue-73223.rs:9:1: 9:2
StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
Expand Down
1 change: 0 additions & 1 deletion src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@
StorageDead(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
StorageDead(_4); // scope 1 at $DIR/issue-73223.rs:9:1: 9:2
StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ fn f_u64() -> () {
StorageDead(_3); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
_0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:34:16: 36:2
return; // scope 0 at $DIR/lower_intrinsics.rs:36:2: 36:2
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ fn f_unit() -> () {
bb1: {
StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:29:18: 29:19
_0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:28:17: 30:2
return; // scope 0 at $DIR/lower_intrinsics.rs:30:2: 30:2
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,25 @@
debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:7:8: 7:11
let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:7:25: 7:25
let mut _2: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
+ let mut _3: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26

bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
}

bb1: {
_0 = const (); // scope 0 at $DIR/matches_reduce_branches.rs:10:6: 10:6
goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:8:5: 10:6
}

bb2: {
goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
}

bb3: {
- switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
- }
-
- bb1: {
- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:8:5: 10:6
- }
-
- bb2: {
- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
-
- bb3: {
+ StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
+ _3 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
+ StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
return; // scope 0 at $DIR/matches_reduce_branches.rs:11:2: 11:2
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,25 @@
debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:7:8: 7:11
let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:7:25: 7:25
let mut _2: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
+ let mut _3: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26

bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
}

bb1: {
_0 = const (); // scope 0 at $DIR/matches_reduce_branches.rs:10:6: 10:6
goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:8:5: 10:6
}

bb2: {
goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
}

bb3: {
- switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
- }
-
- bb1: {
- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:8:5: 10:6
- }
-
- bb2: {
- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
-
- bb3: {
+ StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
+ _3 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
+ StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
return; // scope 0 at $DIR/matches_reduce_branches.rs:11:2: 11:2
}
}
Expand Down
Loading