-
Notifications
You must be signed in to change notification settings - Fork 12.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[mir-opt] Allow debuginfo to be generated for a constant or a Place
Prior to this commit, debuginfo was always generated by mapping a name to a Place. This has the side-effect that `SimplifyLocals` cannot remove locals that are only used for debuginfo because their other uses have been const-propagated. To allow these locals to be removed, we now allow debuginfo to point to a constant value. The `ConstProp` pass detects when debuginfo points to a local with a known constant value and replaces it with the value. This allows the later `SimplifyLocals` pass to remove the local.
- Loading branch information
1 parent
31530e5
commit 52640f2
Showing
22 changed files
with
410 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
//! Finds locals which are assigned once to a const and unused except for debuginfo and converts | ||
//! their debuginfo to use the const directly, allowing the local to be removed. | ||
|
||
use rustc_middle::{ | ||
mir::{ | ||
visit::{PlaceContext, Visitor}, | ||
Body, Constant, Local, Location, Operand, Rvalue, StatementKind, VarDebugInfoContents, | ||
}, | ||
ty::TyCtxt, | ||
}; | ||
|
||
use crate::transform::MirPass; | ||
use rustc_index::{bit_set::BitSet, vec::IndexVec}; | ||
|
||
pub struct ConstDebugInfo; | ||
|
||
impl<'tcx> MirPass<'tcx> for ConstDebugInfo { | ||
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { | ||
trace!("running ConstDebugInfo on {:?}", body.source); | ||
|
||
for (local, constant) in find_optimization_oportunities(body) { | ||
for debuginfo in &mut body.var_debug_info { | ||
if let VarDebugInfoContents::Place(p) = debuginfo.value { | ||
if p.local == local && p.projection.is_empty() { | ||
trace!( | ||
"changing debug info for {:?} from place {:?} to constant {:?}", | ||
debuginfo.name, | ||
p, | ||
constant | ||
); | ||
debuginfo.value = VarDebugInfoContents::Const(constant); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
struct LocalUseVisitor { | ||
local_mutating_uses: IndexVec<Local, u8>, | ||
local_assignment_locations: IndexVec<Local, Option<Location>>, | ||
} | ||
|
||
fn find_optimization_oportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Constant<'tcx>)> { | ||
let mut visitor = LocalUseVisitor { | ||
local_mutating_uses: IndexVec::from_elem(0, &body.local_decls), | ||
local_assignment_locations: IndexVec::from_elem(None, &body.local_decls), | ||
}; | ||
|
||
visitor.visit_body(body); | ||
|
||
let mut locals_to_debuginfo = BitSet::new_empty(body.local_decls.len()); | ||
for debuginfo in &body.var_debug_info { | ||
if let VarDebugInfoContents::Place(p) = debuginfo.value { | ||
if let Some(l) = p.as_local() { | ||
locals_to_debuginfo.insert(l); | ||
} | ||
} | ||
} | ||
|
||
let mut eligable_locals = Vec::new(); | ||
for (local, mutating_uses) in visitor.local_mutating_uses.drain_enumerated(..) { | ||
if mutating_uses != 1 || !locals_to_debuginfo.contains(local) { | ||
continue; | ||
} | ||
|
||
if let Some(location) = visitor.local_assignment_locations[local] { | ||
let bb = &body[location.block]; | ||
|
||
// The value is assigned as the result of a call, not a constant | ||
if bb.statements.len() == location.statement_index { | ||
continue; | ||
} | ||
|
||
if let StatementKind::Assign(box (p, Rvalue::Use(Operand::Constant(box c)))) = | ||
&bb.statements[location.statement_index].kind | ||
{ | ||
if let Some(local) = p.as_local() { | ||
eligable_locals.push((local, *c)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
eligable_locals | ||
} | ||
|
||
impl<'tcx> Visitor<'tcx> for LocalUseVisitor { | ||
fn visit_local(&mut self, local: &Local, context: PlaceContext, location: Location) { | ||
if context.is_mutating_use() { | ||
self.local_mutating_uses[*local] += 1; | ||
|
||
if context.is_place_assignment() { | ||
self.local_assignment_locations[*local] = Some(location); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.