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

Elide superfluous storage markers #99946

Merged
merged 5 commits into from
Aug 25, 2022
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
26 changes: 6 additions & 20 deletions compiler/rustc_middle/src/mir/patch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,22 +68,25 @@ impl<'tcx> MirPatch<'tcx> {
Location { block: bb, statement_index: offset }
}

pub fn new_local_with_info(
pub fn new_internal_with_info(
&mut self,
ty: Ty<'tcx>,
span: Span,
local_info: Option<Box<LocalInfo<'tcx>>>,
) -> Local {
let index = self.next_local;
self.next_local += 1;
let mut new_decl = LocalDecl::new(ty, span);
let mut new_decl = LocalDecl::new(ty, span).internal();
new_decl.local_info = local_info;
self.new_locals.push(new_decl);
Local::new(index as usize)
}

pub fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
self.new_local_with_info(ty, span, None)
let index = self.next_local;
self.next_local += 1;
self.new_locals.push(LocalDecl::new(ty, span));
Local::new(index as usize)
}

pub fn new_internal(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
Expand Down Expand Up @@ -147,7 +150,6 @@ impl<'tcx> MirPatch<'tcx> {

let mut delta = 0;
let mut last_bb = START_BLOCK;
let mut stmts_and_targets: Vec<(Statement<'_>, BasicBlock)> = Vec::new();
for (mut loc, stmt) in new_statements {
if loc.block != last_bb {
delta = 0;
Expand All @@ -156,27 +158,11 @@ impl<'tcx> MirPatch<'tcx> {
debug!("MirPatch: adding statement {:?} at loc {:?}+{}", stmt, loc, delta);
loc.statement_index += delta;
let source_info = Self::source_info_for_index(&body[loc.block], loc);

// For mir-opt `Derefer` to work in all cases we need to
// get terminator's targets and apply the statement to all of them.
if loc.statement_index > body[loc.block].statements.len() {
let term = body[loc.block].terminator();
for i in term.successors() {
stmts_and_targets.push((Statement { source_info, kind: stmt.clone() }, i));
}
delta += 1;
continue;
}

body[loc.block]
.statements
.insert(loc.statement_index, Statement { source_info, kind: stmt });
delta += 1;
}

for (stmt, target) in stmts_and_targets.into_iter().rev() {
body[target].statements.insert(0, stmt);
}
}

pub fn source_info_for_index(data: &BasicBlockData<'_>, loc: Location) -> SourceInfo {
Expand Down
20 changes: 1 addition & 19 deletions compiler/rustc_mir_transform/src/deref_separator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ impl<'tcx> MutVisitor<'tcx> for DerefChecker<'tcx> {
let mut last_len = 0;
let mut last_deref_idx = 0;

let mut prev_temp: Option<Local> = None;

for (idx, elem) in place.projection[0..].iter().enumerate() {
if *elem == ProjectionElem::Deref {
last_deref_idx = idx;
Expand All @@ -39,14 +37,12 @@ impl<'tcx> MutVisitor<'tcx> for DerefChecker<'tcx> {
for (idx, (p_ref, p_elem)) in place.iter_projections().enumerate() {
if !p_ref.projection.is_empty() && p_elem == ProjectionElem::Deref {
let ty = p_ref.ty(&self.local_decls, self.tcx).ty;
let temp = self.patcher.new_local_with_info(
let temp = self.patcher.new_internal_with_info(
ty,
self.local_decls[p_ref.local].source_info.span,
Some(Box::new(LocalInfo::DerefTemp)),
);

self.patcher.add_statement(loc, StatementKind::StorageLive(temp));

// We are adding current p_ref's projections to our
// temp value, excluding projections we already covered.
let deref_place = Place::from(place_local)
Expand All @@ -66,22 +62,8 @@ impl<'tcx> MutVisitor<'tcx> for DerefChecker<'tcx> {
Place::from(temp).project_deeper(&place.projection[idx..], self.tcx);
*place = temp_place;
}

// We are destroying the previous temp since it's no longer used.
if let Some(prev_temp) = prev_temp {
self.patcher.add_statement(loc, StatementKind::StorageDead(prev_temp));
}
tmiasko marked this conversation as resolved.
Show resolved Hide resolved

prev_temp = Some(temp);
}
}

// Since we won't be able to reach final temp, we destroy it outside the loop.
if let Some(prev_temp) = prev_temp {
let last_loc =
Location { block: loc.block, statement_index: loc.statement_index + 1 };
self.patcher.add_statement(last_loc, StatementKind::StorageDead(prev_temp));
}
}
}
}
Expand Down
9 changes: 1 addition & 8 deletions compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,7 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> {
let (unique_ty, nonnull_ty, ptr_ty) =
build_ptr_tys(tcx, base_ty.boxed_ty(), self.unique_did, self.nonnull_did);

let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);

self.patch.add_statement(location, StatementKind::StorageLive(ptr_local));
let ptr_local = self.patch.new_internal(ptr_ty, source_info.span);

self.patch.add_assign(
location,
Expand All @@ -83,11 +81,6 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> {
);

place.local = ptr_local;

self.patch.add_statement(
Location { block: location.block, statement_index: location.statement_index + 1 },
StatementKind::StorageDead(ptr_local),
);
}

self.super_place(place, context, location);
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_mir_transform/src/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,9 @@ impl<'tcx> Inliner<'tcx> {
// If there are any locals without storage markers, give them storage only for the
// duration of the call.
for local in callee_body.vars_and_temps_iter() {
if integrator.always_live_locals.contains(local) {
if !callee_body.local_decls[local].internal
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @rust-lang/wg-const-eval I think we could do something similar for internal locals without storage markers in const eval. Basically not eagerly initialize them and also not error when writing to them without marking them as live first.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like you are suggesting a change to the operational semantics of MIR? I don't quite understand what change you are suggesting, though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somewhat. We'd need to change MIR validation to make sure that internal locals are only referenced after being assigned to first. If that is guaranteed, then it's just an evaluator optimization to lazily initialize internal locals

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd also have to make sure that syntactically they are never accessed after the StorageDead, and that they never have their address taken. Otherwise we could miss UB.

&& integrator.always_live_locals.contains(local)
{
let new_local = integrator.map_local(local);
caller_body[callsite.block].statements.push(Statement {
source_info: callsite.source_info,
Expand All @@ -629,7 +631,9 @@ impl<'tcx> Inliner<'tcx> {
// the slice once.
let mut n = 0;
for local in callee_body.vars_and_temps_iter().rev() {
if integrator.always_live_locals.contains(local) {
if !callee_body.local_decls[local].internal
&& integrator.always_live_locals.contains(local)
{
let new_local = integrator.map_local(local);
caller_body[block].statements.push(Statement {
source_info: callsite.source_info,
Expand Down
4 changes: 0 additions & 4 deletions src/test/mir-opt/const_prop/boxes.main.ConstProp.diff
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,12 @@
bb1: {
StorageLive(_7); // scope 0 at $DIR/boxes.rs:+1:14: +1:22
_7 = ShallowInitBox(move _6, i32); // scope 0 at $DIR/boxes.rs:+1:14: +1:22
StorageLive(_8); // scope 0 at $DIR/boxes.rs:+1:19: +1:21
_8 = (((_7.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>).0: *const i32); // scope 0 at $DIR/boxes.rs:+1:19: +1:21
(*_8) = const 42_i32; // scope 0 at $DIR/boxes.rs:+1:19: +1:21
StorageDead(_8); // scope 0 at $DIR/boxes.rs:+1:14: +1:22
_3 = move _7; // scope 0 at $DIR/boxes.rs:+1:14: +1:22
StorageDead(_7); // scope 0 at $DIR/boxes.rs:+1:21: +1:22
StorageLive(_9); // scope 0 at $DIR/boxes.rs:+1:13: +1:22
_9 = (((_3.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>).0: *const i32); // scope 0 at $DIR/boxes.rs:+1:13: +1:22
_2 = (*_9); // scope 0 at $DIR/boxes.rs:+1:13: +1:22
StorageDead(_9); // scope 0 at $DIR/boxes.rs:+1:13: +1:26
_1 = Add(move _2, const 0_i32); // scope 0 at $DIR/boxes.rs:+1:13: +1:26
StorageDead(_2); // scope 0 at $DIR/boxes.rs:+1:25: +1:26
drop(_3) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/boxes.rs:+1:26: +1:27
Expand Down
2 changes: 0 additions & 2 deletions src/test/mir-opt/derefer_complex_case.main.Derefer.diff
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,8 @@
bb4: {
StorageLive(_12); // scope 1 at $DIR/derefer_complex_case.rs:+1:10: +1:13
- _12 = (*((_7 as Some).0: &i32)); // scope 1 at $DIR/derefer_complex_case.rs:+1:10: +1:13
+ StorageLive(_15); // scope 1 at $DIR/derefer_complex_case.rs:+1:10: +1:13
+ _15 = deref_copy ((_7 as Some).0: &i32); // scope 1 at $DIR/derefer_complex_case.rs:+1:10: +1:13
+ _12 = (*_15); // scope 1 at $DIR/derefer_complex_case.rs:+1:10: +1:13
+ StorageDead(_15); // scope 2 at $DIR/derefer_complex_case.rs:+1:34: +1:37
StorageLive(_13); // scope 2 at $DIR/derefer_complex_case.rs:+1:34: +1:37
_13 = _12; // scope 2 at $DIR/derefer_complex_case.rs:+1:34: +1:37
_6 = std::mem::drop::<i32>(move _13) -> bb7; // scope 2 at $DIR/derefer_complex_case.rs:+1:29: +1:38
Expand Down
7 changes: 0 additions & 7 deletions src/test/mir-opt/derefer_terminator_test.main.Derefer.diff
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,18 @@
_5 = &_6; // scope 2 at $DIR/derefer_terminator_test.rs:+3:17: +3:21
_4 = &_5; // scope 2 at $DIR/derefer_terminator_test.rs:+3:15: +3:22
- switchInt((*(*(*(*_4))))) -> [false: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+ StorageLive(_10); // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+ _10 = deref_copy (*_4); // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+ StorageLive(_11); // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+ _11 = deref_copy (*_10); // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+ StorageDead(_10); // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+ StorageLive(_12); // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+ _12 = deref_copy (*_11); // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+ StorageDead(_11); // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+ switchInt((*_12)) -> [false: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
}

bb3: {
+ StorageDead(_12); // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
_3 = const (); // scope 2 at $DIR/derefer_terminator_test.rs:+5:18: +5:20
goto -> bb5; // scope 2 at $DIR/derefer_terminator_test.rs:+5:18: +5:20
}

bb4: {
+ StorageDead(_12); // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
StorageLive(_8); // scope 2 at $DIR/derefer_terminator_test.rs:+4:22: +4:23
_8 = const 5_i32; // scope 2 at $DIR/derefer_terminator_test.rs:+4:26: +4:27
_3 = const (); // scope 2 at $DIR/derefer_terminator_test.rs:+4:17: +4:29
Expand Down
4 changes: 0 additions & 4 deletions src/test/mir-opt/derefer_test.main.Derefer.diff
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,12 @@
StorageDead(_3); // scope 1 at $DIR/derefer_test.rs:+2:28: +2:29
StorageLive(_4); // scope 2 at $DIR/derefer_test.rs:+3:9: +3:10
- _4 = &mut ((*(_2.1: &mut (i32, i32))).0: i32); // scope 2 at $DIR/derefer_test.rs:+3:13: +3:26
+ StorageLive(_6); // scope 2 at $DIR/derefer_test.rs:+3:13: +3:26
+ _6 = deref_copy (_2.1: &mut (i32, i32)); // scope 2 at $DIR/derefer_test.rs:+3:13: +3:26
+ _4 = &mut ((*_6).0: i32); // scope 2 at $DIR/derefer_test.rs:+3:13: +3:26
+ StorageDead(_6); // scope 3 at $DIR/derefer_test.rs:+4:9: +4:10
StorageLive(_5); // scope 3 at $DIR/derefer_test.rs:+4:9: +4:10
- _5 = &mut ((*(_2.1: &mut (i32, i32))).1: i32); // scope 3 at $DIR/derefer_test.rs:+4:13: +4:26
+ StorageLive(_7); // scope 3 at $DIR/derefer_test.rs:+4:13: +4:26
+ _7 = deref_copy (_2.1: &mut (i32, i32)); // scope 3 at $DIR/derefer_test.rs:+4:13: +4:26
+ _5 = &mut ((*_7).1: i32); // scope 3 at $DIR/derefer_test.rs:+4:13: +4:26
+ StorageDead(_7); // scope 0 at $DIR/derefer_test.rs:+0:11: +5:2
_0 = const (); // scope 0 at $DIR/derefer_test.rs:+0:11: +5:2
StorageDead(_5); // scope 3 at $DIR/derefer_test.rs:+5:1: +5:2
StorageDead(_4); // scope 2 at $DIR/derefer_test.rs:+5:1: +5:2
Expand Down
12 changes: 0 additions & 12 deletions src/test/mir-opt/derefer_test_multiple.main.Derefer.diff
Original file line number Diff line number Diff line change
Expand Up @@ -57,28 +57,16 @@
StorageDead(_7); // scope 3 at $DIR/derefer_test_multiple.rs:+4:28: +4:29
StorageLive(_8); // scope 4 at $DIR/derefer_test_multiple.rs:+5:9: +5:10
- _8 = &mut ((*((*((*(_6.1: &mut (i32, &mut (i32, &mut (i32, i32))))).1: &mut (i32, &mut (i32, i32)))).1: &mut (i32, i32))).1: i32); // scope 4 at $DIR/derefer_test_multiple.rs:+5:13: +5:30
+ StorageLive(_10); // scope 4 at $DIR/derefer_test_multiple.rs:+5:13: +5:30
+ _10 = deref_copy (_6.1: &mut (i32, &mut (i32, &mut (i32, i32)))); // scope 4 at $DIR/derefer_test_multiple.rs:+5:13: +5:30
+ StorageLive(_11); // scope 4 at $DIR/derefer_test_multiple.rs:+5:13: +5:30
+ _11 = deref_copy ((*_10).1: &mut (i32, &mut (i32, i32))); // scope 4 at $DIR/derefer_test_multiple.rs:+5:13: +5:30
+ StorageDead(_10); // scope 4 at $DIR/derefer_test_multiple.rs:+5:13: +5:30
+ StorageLive(_12); // scope 4 at $DIR/derefer_test_multiple.rs:+5:13: +5:30
+ _12 = deref_copy ((*_11).1: &mut (i32, i32)); // scope 4 at $DIR/derefer_test_multiple.rs:+5:13: +5:30
+ StorageDead(_11); // scope 4 at $DIR/derefer_test_multiple.rs:+5:13: +5:30
+ _8 = &mut ((*_12).1: i32); // scope 4 at $DIR/derefer_test_multiple.rs:+5:13: +5:30
+ StorageDead(_12); // scope 5 at $DIR/derefer_test_multiple.rs:+6:9: +6:10
StorageLive(_9); // scope 5 at $DIR/derefer_test_multiple.rs:+6:9: +6:10
- _9 = &mut ((*((*((*(_6.1: &mut (i32, &mut (i32, &mut (i32, i32))))).1: &mut (i32, &mut (i32, i32)))).1: &mut (i32, i32))).1: i32); // scope 5 at $DIR/derefer_test_multiple.rs:+6:13: +6:30
+ StorageLive(_13); // scope 5 at $DIR/derefer_test_multiple.rs:+6:13: +6:30
+ _13 = deref_copy (_6.1: &mut (i32, &mut (i32, &mut (i32, i32)))); // scope 5 at $DIR/derefer_test_multiple.rs:+6:13: +6:30
+ StorageLive(_14); // scope 5 at $DIR/derefer_test_multiple.rs:+6:13: +6:30
+ _14 = deref_copy ((*_13).1: &mut (i32, &mut (i32, i32))); // scope 5 at $DIR/derefer_test_multiple.rs:+6:13: +6:30
+ StorageDead(_13); // scope 5 at $DIR/derefer_test_multiple.rs:+6:13: +6:30
+ StorageLive(_15); // scope 5 at $DIR/derefer_test_multiple.rs:+6:13: +6:30
+ _15 = deref_copy ((*_14).1: &mut (i32, i32)); // scope 5 at $DIR/derefer_test_multiple.rs:+6:13: +6:30
+ StorageDead(_14); // scope 5 at $DIR/derefer_test_multiple.rs:+6:13: +6:30
+ _9 = &mut ((*_15).1: i32); // scope 5 at $DIR/derefer_test_multiple.rs:+6:13: +6:30
+ StorageDead(_15); // scope 0 at $DIR/derefer_test_multiple.rs:+0:12: +7:2
_0 = const (); // scope 0 at $DIR/derefer_test_multiple.rs:+0:12: +7:2
StorageDead(_9); // scope 5 at $DIR/derefer_test_multiple.rs:+7:1: +7:2
StorageDead(_8); // scope 4 at $DIR/derefer_test_multiple.rs:+7:1: +7:2
Expand Down
Loading