Skip to content

Commit 1142524

Browse files
committed
Separately eliminate self-assignments
1 parent ae5553d commit 1142524

File tree

3 files changed

+62
-6
lines changed

3 files changed

+62
-6
lines changed

src/librustc_mir/transform/copy_prop.rs

+39-4
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,14 @@ impl MirPass for CopyPropagation {
6969
return;
7070
}
7171

72+
let mut def_use_analysis = DefUseAnalysis::new(mir);
7273
loop {
73-
let mut def_use_analysis = DefUseAnalysis::new(mir);
7474
def_use_analysis.analyze(mir);
7575

76+
if eliminate_self_assignments(mir, &def_use_analysis) {
77+
def_use_analysis.analyze(mir);
78+
}
79+
7680
let mut changed = false;
7781
for dest_local in mir.local_decls.indices() {
7882
debug!("Considering destination local: {:?}", dest_local);
@@ -106,9 +110,7 @@ impl MirPass for CopyPropagation {
106110
dest_local);
107111
continue;
108112
}
109-
let dest_lvalue_def = dest_use_info.defs_and_uses.iter().filter(|lvalue_def| {
110-
lvalue_def.context.is_mutating_use() && !lvalue_def.context.is_drop()
111-
}).next().unwrap();
113+
let dest_lvalue_def = dest_use_info.defs_not_including_drop().next().unwrap();
112114
location = dest_lvalue_def.location;
113115

114116
let basic_block = &mir[location.block];
@@ -158,6 +160,39 @@ impl MirPass for CopyPropagation {
158160
}
159161
}
160162

163+
fn eliminate_self_assignments<'tcx>(
164+
mir: &mut Mir<'tcx>,
165+
def_use_analysis: &DefUseAnalysis<'tcx>,
166+
) -> bool {
167+
let mut changed = false;
168+
169+
for dest_local in mir.local_decls.indices() {
170+
let dest_use_info = def_use_analysis.local_info(dest_local);
171+
172+
for def in dest_use_info.defs_not_including_drop() {
173+
let location = def.location;
174+
if let Some(stmt) = mir[location.block].statements.get(location.statement_index) {
175+
match stmt.kind {
176+
StatementKind::Assign(
177+
Lvalue::Local(local),
178+
Rvalue::Use(Operand::Consume(Lvalue::Local(src_local))),
179+
) if local == dest_local && dest_local == src_local => {}
180+
_ => {
181+
continue;
182+
}
183+
}
184+
} else {
185+
continue;
186+
}
187+
debug!("Deleting a self-assignment for {:?}", dest_local);
188+
mir.make_statement_nop(location);
189+
changed = true;
190+
}
191+
}
192+
193+
changed
194+
}
195+
161196
enum Action<'tcx> {
162197
PropagateLocalCopy(Local),
163198
PropagateConstant(Constant<'tcx>),

src/librustc_mir/util/def_use.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use rustc::mir::visit::{LvalueContext, MutVisitor, Visitor};
1515
use rustc_data_structures::indexed_vec::IndexVec;
1616
use std::marker::PhantomData;
1717
use std::mem;
18+
use std::slice;
19+
use std::iter;
1820

1921
pub struct DefUseAnalysis<'tcx> {
2022
info: IndexVec<Local, Info<'tcx>>,
@@ -39,13 +41,21 @@ impl<'tcx> DefUseAnalysis<'tcx> {
3941
}
4042

4143
pub fn analyze(&mut self, mir: &Mir<'tcx>) {
44+
self.clear();
45+
4246
let mut finder = DefUseFinder {
4347
info: mem::replace(&mut self.info, IndexVec::new()),
4448
};
4549
finder.visit_mir(mir);
4650
self.info = finder.info
4751
}
4852

53+
fn clear(&mut self) {
54+
for info in &mut self.info {
55+
info.clear();
56+
}
57+
}
58+
4959
pub fn local_info(&self, local: Local) -> &Info<'tcx> {
5060
&self.info[local]
5161
}
@@ -93,14 +103,24 @@ impl<'tcx> Info<'tcx> {
93103
}
94104
}
95105

106+
fn clear(&mut self) {
107+
self.defs_and_uses.clear();
108+
}
109+
96110
pub fn def_count(&self) -> usize {
97111
self.defs_and_uses.iter().filter(|lvalue_use| lvalue_use.context.is_mutating_use()).count()
98112
}
99113

100114
pub fn def_count_not_including_drop(&self) -> usize {
115+
self.defs_not_including_drop().count()
116+
}
117+
118+
pub fn defs_not_including_drop(
119+
&self,
120+
) -> iter::Filter<slice::Iter<Use<'tcx>>, fn(&&Use<'tcx>) -> bool> {
101121
self.defs_and_uses.iter().filter(|lvalue_use| {
102122
lvalue_use.context.is_mutating_use() && !lvalue_use.context.is_drop()
103-
}).count()
123+
})
104124
}
105125

106126
pub fn use_count(&self) -> usize {

src/test/mir-opt/copy_propagation_arg.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ fn main() {
3434
// Make sure the function actually gets instantiated.
3535
foo(0);
3636
bar(0);
37+
baz(0);
3738
}
3839

3940
// END RUST SOURCE
@@ -112,4 +113,4 @@ fn main() {
112113
// _0 = ();
113114
// return;
114115
// }
115-
// END rustc.baz.CopyPropagation.after.mir
116+
// END rustc.baz.CopyPropagation.after.mir

0 commit comments

Comments
 (0)