Separately eliminate self-assignments
This commit is contained in:
parent
ae5553d7b0
commit
114252410d
3 changed files with 62 additions and 6 deletions
|
|
@ -69,10 +69,14 @@ impl MirPass for CopyPropagation {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut def_use_analysis = DefUseAnalysis::new(mir);
|
||||
loop {
|
||||
let mut def_use_analysis = DefUseAnalysis::new(mir);
|
||||
def_use_analysis.analyze(mir);
|
||||
|
||||
if eliminate_self_assignments(mir, &def_use_analysis) {
|
||||
def_use_analysis.analyze(mir);
|
||||
}
|
||||
|
||||
let mut changed = false;
|
||||
for dest_local in mir.local_decls.indices() {
|
||||
debug!("Considering destination local: {:?}", dest_local);
|
||||
|
|
@ -106,9 +110,7 @@ impl MirPass for CopyPropagation {
|
|||
dest_local);
|
||||
continue;
|
||||
}
|
||||
let dest_lvalue_def = dest_use_info.defs_and_uses.iter().filter(|lvalue_def| {
|
||||
lvalue_def.context.is_mutating_use() && !lvalue_def.context.is_drop()
|
||||
}).next().unwrap();
|
||||
let dest_lvalue_def = dest_use_info.defs_not_including_drop().next().unwrap();
|
||||
location = dest_lvalue_def.location;
|
||||
|
||||
let basic_block = &mir[location.block];
|
||||
|
|
@ -158,6 +160,39 @@ impl MirPass for CopyPropagation {
|
|||
}
|
||||
}
|
||||
|
||||
fn eliminate_self_assignments<'tcx>(
|
||||
mir: &mut Mir<'tcx>,
|
||||
def_use_analysis: &DefUseAnalysis<'tcx>,
|
||||
) -> bool {
|
||||
let mut changed = false;
|
||||
|
||||
for dest_local in mir.local_decls.indices() {
|
||||
let dest_use_info = def_use_analysis.local_info(dest_local);
|
||||
|
||||
for def in dest_use_info.defs_not_including_drop() {
|
||||
let location = def.location;
|
||||
if let Some(stmt) = mir[location.block].statements.get(location.statement_index) {
|
||||
match stmt.kind {
|
||||
StatementKind::Assign(
|
||||
Lvalue::Local(local),
|
||||
Rvalue::Use(Operand::Consume(Lvalue::Local(src_local))),
|
||||
) if local == dest_local && dest_local == src_local => {}
|
||||
_ => {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
debug!("Deleting a self-assignment for {:?}", dest_local);
|
||||
mir.make_statement_nop(location);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
changed
|
||||
}
|
||||
|
||||
enum Action<'tcx> {
|
||||
PropagateLocalCopy(Local),
|
||||
PropagateConstant(Constant<'tcx>),
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ use rustc::mir::visit::{LvalueContext, MutVisitor, Visitor};
|
|||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::slice;
|
||||
use std::iter;
|
||||
|
||||
pub struct DefUseAnalysis<'tcx> {
|
||||
info: IndexVec<Local, Info<'tcx>>,
|
||||
|
|
@ -39,6 +41,8 @@ impl<'tcx> DefUseAnalysis<'tcx> {
|
|||
}
|
||||
|
||||
pub fn analyze(&mut self, mir: &Mir<'tcx>) {
|
||||
self.clear();
|
||||
|
||||
let mut finder = DefUseFinder {
|
||||
info: mem::replace(&mut self.info, IndexVec::new()),
|
||||
};
|
||||
|
|
@ -46,6 +50,12 @@ impl<'tcx> DefUseAnalysis<'tcx> {
|
|||
self.info = finder.info
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
for info in &mut self.info {
|
||||
info.clear();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_info(&self, local: Local) -> &Info<'tcx> {
|
||||
&self.info[local]
|
||||
}
|
||||
|
|
@ -93,14 +103,24 @@ impl<'tcx> Info<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.defs_and_uses.clear();
|
||||
}
|
||||
|
||||
pub fn def_count(&self) -> usize {
|
||||
self.defs_and_uses.iter().filter(|lvalue_use| lvalue_use.context.is_mutating_use()).count()
|
||||
}
|
||||
|
||||
pub fn def_count_not_including_drop(&self) -> usize {
|
||||
self.defs_not_including_drop().count()
|
||||
}
|
||||
|
||||
pub fn defs_not_including_drop(
|
||||
&self,
|
||||
) -> iter::Filter<slice::Iter<Use<'tcx>>, fn(&&Use<'tcx>) -> bool> {
|
||||
self.defs_and_uses.iter().filter(|lvalue_use| {
|
||||
lvalue_use.context.is_mutating_use() && !lvalue_use.context.is_drop()
|
||||
}).count()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn use_count(&self) -> usize {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ fn main() {
|
|||
// Make sure the function actually gets instantiated.
|
||||
foo(0);
|
||||
bar(0);
|
||||
baz(0);
|
||||
}
|
||||
|
||||
// END RUST SOURCE
|
||||
|
|
@ -112,4 +113,4 @@ fn main() {
|
|||
// _0 = ();
|
||||
// return;
|
||||
// }
|
||||
// END rustc.baz.CopyPropagation.after.mir
|
||||
// END rustc.baz.CopyPropagation.after.mir
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue