1
Fork 0

Auto merge of #99946 - tmiasko:elide-storage-makers, r=oli-obk

Elide superfluous storage markers

Follow the existing strategy of omitting the storage markers for temporaries
introduced for internal usage when elaborating derefs and deref projections.

Those temporaries are simple scalars which are used immediately after being
defined and never have their address taken. There is no benefit from storage
markers from either liveness analysis or code generation perspective.
This commit is contained in:
bors 2022-08-24 23:51:06 +00:00
commit 5462da52ba
22 changed files with 48 additions and 198 deletions

View file

@ -68,7 +68,7 @@ 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,
@ -76,14 +76,17 @@ impl<'tcx> MirPatch<'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 {
@ -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;
@ -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 {

View file

@ -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;
@ -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)
@ -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));
}
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));
}
}
}
}

View file

@ -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,
@ -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);

View file

@ -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
&& 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,
@ -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,