Iteratively replace pointers.
This commit is contained in:
parent
b64e9113e2
commit
d0d4e0237f
@ -85,7 +85,9 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
let ssa = SsaLocals::new(body);
|
||||
|
||||
let mut replacer = compute_replacement(tcx, body, &ssa);
|
||||
debug!(?replacer.targets, ?replacer.allowed_replacements, ?replacer.storage_to_remove);
|
||||
debug!(?replacer.targets);
|
||||
debug!(?replacer.allowed_replacements);
|
||||
debug!(?replacer.storage_to_remove);
|
||||
|
||||
replacer.visit_body_preserves_cfg(body);
|
||||
|
||||
@ -190,8 +192,11 @@ fn compute_replacement<'tcx>(
|
||||
continue;
|
||||
}
|
||||
|
||||
// Whether the current local is subject to the uniqueness rule.
|
||||
let needs_unique = ty.is_mutable_ptr();
|
||||
|
||||
// If this a mutable reference that we cannot fully replace, mark it as unknown.
|
||||
if ty.is_mutable_ptr() && !fully_replacable_locals.contains(local) {
|
||||
if needs_unique && !fully_replacable_locals.contains(local) {
|
||||
debug!("not fully replaceable");
|
||||
continue;
|
||||
}
|
||||
@ -217,10 +222,10 @@ fn compute_replacement<'tcx>(
|
||||
let mut place = *place;
|
||||
// Try to see through `place` in order to collapse reborrow chains.
|
||||
if place.projection.first() == Some(&PlaceElem::Deref)
|
||||
&& let Value::Pointer(target, refmut) = targets[place.local]
|
||||
&& let Value::Pointer(target, needs_unique) = targets[place.local]
|
||||
// Only see through immutable reference and pointers, as we do not know yet if
|
||||
// mutable references are fully replaced.
|
||||
&& !refmut
|
||||
&& !needs_unique
|
||||
// Only collapse chain if the pointee is definitely live.
|
||||
&& can_perform_opt(target, location)
|
||||
{
|
||||
@ -228,7 +233,7 @@ fn compute_replacement<'tcx>(
|
||||
}
|
||||
assert_ne!(place.local, local);
|
||||
if is_constant_place(place) {
|
||||
targets[local] = Value::Pointer(place, ty.is_mutable_ptr());
|
||||
targets[local] = Value::Pointer(place, needs_unique);
|
||||
}
|
||||
}
|
||||
// We do not know what to do, so keep as not-a-pointer.
|
||||
@ -276,16 +281,35 @@ fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, loc: Location
|
||||
return;
|
||||
}
|
||||
|
||||
if let Value::Pointer(target, refmut) = self.targets[place.local]
|
||||
&& place.projection.first() == Some(&PlaceElem::Deref)
|
||||
{
|
||||
let perform_opt = (self.can_perform_opt)(target, loc);
|
||||
if perform_opt {
|
||||
self.allowed_replacements.insert((target.local, loc));
|
||||
} else if refmut {
|
||||
// This mutable reference is not fully replacable, so drop it.
|
||||
self.targets[place.local] = Value::Unknown;
|
||||
if place.projection.first() != Some(&PlaceElem::Deref) {
|
||||
// This is not a dereference, nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
let mut place = place.as_ref();
|
||||
loop {
|
||||
if let Value::Pointer(target, needs_unique) = self.targets[place.local] {
|
||||
let perform_opt = (self.can_perform_opt)(target, loc);
|
||||
debug!(?place, ?target, ?needs_unique, ?perform_opt);
|
||||
|
||||
// This a reborrow chain, recursively allow the replacement.
|
||||
//
|
||||
// This also allows to detect cases where `target.local` is not replacable,
|
||||
// and mark it as such.
|
||||
if let &[PlaceElem::Deref] = &target.projection[..] {
|
||||
assert!(perform_opt);
|
||||
self.allowed_replacements.insert((target.local, loc));
|
||||
place.local = target.local;
|
||||
continue;
|
||||
} else if perform_opt {
|
||||
self.allowed_replacements.insert((target.local, loc));
|
||||
} else if needs_unique {
|
||||
// This mutable reference is not fully replacable, so drop it.
|
||||
self.targets[place.local] = Value::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -326,18 +350,23 @@ fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
}
|
||||
|
||||
fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
|
||||
if let Value::Pointer(target, _) = self.targets[place.local]
|
||||
&& place.projection.first() == Some(&PlaceElem::Deref)
|
||||
{
|
||||
let perform_opt = matches!(ctxt, PlaceContext::NonUse(_))
|
||||
|| self.allowed_replacements.contains(&(target.local, loc));
|
||||
if place.projection.first() != Some(&PlaceElem::Deref) {
|
||||
return;
|
||||
}
|
||||
|
||||
if perform_opt {
|
||||
*place = target.project_deeper(&place.projection[1..], self.tcx);
|
||||
self.any_replacement = true;
|
||||
loop {
|
||||
if let Value::Pointer(target, _) = self.targets[place.local] {
|
||||
let perform_opt = matches!(ctxt, PlaceContext::NonUse(_))
|
||||
|| self.allowed_replacements.contains(&(target.local, loc));
|
||||
|
||||
if perform_opt {
|
||||
*place = target.project_deeper(&place.projection[1..], self.tcx);
|
||||
self.any_replacement = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.super_place(place, ctxt, loc);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,7 @@
|
||||
- StorageLive(_5); // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
|
||||
- _5 = &mut (*_2); // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
|
||||
- _4 = &raw mut (*_5); // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
|
||||
+ _5 = &mut _1; // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
|
||||
+ _4 = &raw mut (*_2); // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
|
||||
+ _4 = &raw mut _1; // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
|
||||
_3 = _4; // scope 2 at $DIR/reference_prop.rs:+3:16: +3:36
|
||||
- StorageDead(_5); // scope 2 at $DIR/reference_prop.rs:+3:36: +3:37
|
||||
StorageDead(_4); // scope 2 at $DIR/reference_prop.rs:+3:36: +3:37
|
||||
@ -55,8 +54,8 @@
|
||||
- (*_3) = const 4_i32; // scope 6 at $DIR/reference_prop.rs:+7:14: +7:23
|
||||
- _8 = const (); // scope 6 at $DIR/reference_prop.rs:+7:5: +7:26
|
||||
- StorageDead(_8); // scope 5 at $DIR/reference_prop.rs:+7:25: +7:26
|
||||
+ _7 = (*_2); // scope 4 at $DIR/reference_prop.rs:+6:13: +6:18
|
||||
+ (*_5) = const 4_i32; // scope 6 at $DIR/reference_prop.rs:+7:14: +7:23
|
||||
+ _7 = _1; // scope 4 at $DIR/reference_prop.rs:+6:13: +6:18
|
||||
+ _1 = const 4_i32; // scope 6 at $DIR/reference_prop.rs:+7:14: +7:23
|
||||
StorageLive(_9); // scope 5 at $DIR/reference_prop.rs:+8:6: +8:7
|
||||
_9 = _7; // scope 5 at $DIR/reference_prop.rs:+8:6: +8:7
|
||||
StorageLive(_10); // scope 5 at $DIR/reference_prop.rs:+8:9: +8:10
|
||||
|
@ -9,15 +9,14 @@
|
||||
let mut _5: *mut usize; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
|
||||
|
||||
bb0: {
|
||||
_2 = &mut (*_1); // scope 0 at $DIR/reference_prop.rs:+10:13: +10:25
|
||||
- _2 = &mut (*_1); // scope 0 at $DIR/reference_prop.rs:+10:13: +10:25
|
||||
- _3 = &mut (*_2); // scope 0 at $DIR/reference_prop.rs:+11:13: +11:26
|
||||
- _4 = &raw mut (*_2); // scope 0 at $DIR/reference_prop.rs:+12:13: +12:30
|
||||
- _5 = &raw mut (*_3); // scope 0 at $DIR/reference_prop.rs:+13:13: +13:30
|
||||
- _0 = (*_4); // scope 0 at $DIR/reference_prop.rs:+15:13: +15:22
|
||||
- _0 = (*_5); // scope 0 at $DIR/reference_prop.rs:+16:13: +16:22
|
||||
+ _3 = &mut (*_1); // scope 0 at $DIR/reference_prop.rs:+11:13: +11:26
|
||||
+ _0 = (*_2); // scope 0 at $DIR/reference_prop.rs:+15:13: +15:22
|
||||
+ _0 = (*_3); // scope 0 at $DIR/reference_prop.rs:+16:13: +16:22
|
||||
+ _0 = (*_1); // scope 0 at $DIR/reference_prop.rs:+15:13: +15:22
|
||||
+ _0 = (*_1); // scope 0 at $DIR/reference_prop.rs:+16:13: +16:22
|
||||
return; // scope 0 at $DIR/reference_prop.rs:+17:13: +17:21
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user