1
Fork 0

Rollup merge of #64991 - wesleywiser:fix_too_eager_const_prop, r=oli-obk

[const-prop] Correctly handle locals that can't be propagated

`const_prop()` now handles writing the Rvalue into the Place in the
stack frame for us. So if we're not supposed to propagate that value,
we need to clear it.

r? @oli-obk

Fixes #64970
This commit is contained in:
Mazdak Farrokhzad 2019-10-02 18:24:43 +02:00 committed by GitHub
commit 34ea55908e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 29 deletions

View file

@ -335,34 +335,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
fn get_const(&self, local: Local) -> Option<Const<'tcx>> {
let l = &self.ecx.frame().locals[local];
// If the local is `Unitialized` or `Dead` then we haven't propagated a value into it.
//
// `InterpCx::access_local()` mostly takes care of this for us however, for ZSTs,
// it will synthesize a value for us. In doing so, that will cause the
// `get_const(l).is_empty()` assert right before we call `set_const()` in `visit_statement`
// to fail.
if let LocalValue::Uninitialized | LocalValue::Dead = l.value {
return None;
}
self.ecx.access_local(self.ecx.frame(), local, None).ok()
}
fn set_const(&mut self, local: Local, c: Const<'tcx>) {
let frame = self.ecx.frame_mut();
if let Some(layout) = frame.locals[local].layout.get() {
debug_assert_eq!(c.layout, layout);
}
frame.locals[local] = LocalState {
value: LocalValue::Live(*c),
layout: Cell::new(Some(c.layout)),
};
}
fn remove_const(&mut self, local: Local) {
self.ecx.frame_mut().locals[local] = LocalState {
value: LocalValue::Uninitialized,
@ -735,10 +710,8 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
place) {
trace!("checking whether {:?} can be stored to {:?}", value, local);
if self.can_const_prop[local] {
trace!("storing {:?} to {:?}", value, local);
assert!(self.get_const(local).is_none() ||
self.get_const(local) == Some(value));
self.set_const(local, value);
trace!("stored {:?} to {:?}", value, local);
assert_eq!(self.get_const(local), Some(value));
if self.should_const_prop() {
self.replace_with_const(
@ -747,6 +720,9 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
statement.source_info,
);
}
} else {
trace!("can't propagate {:?} to {:?}", value, local);
self.remove_const(local);
}
}
}

View file

@ -0,0 +1,15 @@
// run-pass
fn main() {
foo(10);
}
fn foo(mut n: i32) {
if false {
n = 0i32;
}
if n > 0i32 {
1i32 / n;
}
}

View file

@ -0,0 +1,8 @@
warning: unused arithmetic operation that must be used
--> $DIR/issue-64970.rs:13:9
|
LL | 1i32 / n;
| ^^^^^^^^
|
= note: `#[warn(unused_must_use)]` on by default