1
Fork 0

Iteratively replace pointers.

This commit is contained in:
Camille GILLOT 2023-05-10 17:17:33 +00:00
parent b64e9113e2
commit d0d4e0237f
3 changed files with 59 additions and 32 deletions

View file

@ -85,7 +85,9 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let ssa = SsaLocals::new(body); let ssa = SsaLocals::new(body);
let mut replacer = compute_replacement(tcx, body, &ssa); 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); replacer.visit_body_preserves_cfg(body);
@ -190,8 +192,11 @@ fn compute_replacement<'tcx>(
continue; 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 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"); debug!("not fully replaceable");
continue; continue;
} }
@ -217,10 +222,10 @@ fn compute_replacement<'tcx>(
let mut place = *place; let mut place = *place;
// Try to see through `place` in order to collapse reborrow chains. // Try to see through `place` in order to collapse reborrow chains.
if place.projection.first() == Some(&PlaceElem::Deref) 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 // Only see through immutable reference and pointers, as we do not know yet if
// mutable references are fully replaced. // mutable references are fully replaced.
&& !refmut && !needs_unique
// Only collapse chain if the pointee is definitely live. // Only collapse chain if the pointee is definitely live.
&& can_perform_opt(target, location) && can_perform_opt(target, location)
{ {
@ -228,7 +233,7 @@ fn compute_replacement<'tcx>(
} }
assert_ne!(place.local, local); assert_ne!(place.local, local);
if is_constant_place(place) { 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. // We do not know what to do, so keep as not-a-pointer.
@ -276,16 +281,35 @@ fn compute_replacement<'tcx>(
return; return;
} }
if let Value::Pointer(target, refmut) = self.targets[place.local] if place.projection.first() != Some(&PlaceElem::Deref) {
&& place.projection.first() == Some(&PlaceElem::Deref) // This is not a dereference, nothing to do.
{ return;
let perform_opt = (self.can_perform_opt)(target, loc); }
if perform_opt {
self.allowed_replacements.insert((target.local, loc)); let mut place = place.as_ref();
} else if refmut { loop {
// This mutable reference is not fully replacable, so drop it. if let Value::Pointer(target, needs_unique) = self.targets[place.local] {
self.targets[place.local] = Value::Unknown; 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 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
} }
fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) { fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
if let Value::Pointer(target, _) = self.targets[place.local] if place.projection.first() != Some(&PlaceElem::Deref) {
&& place.projection.first() == Some(&PlaceElem::Deref) return;
{ }
let perform_opt = matches!(ctxt, PlaceContext::NonUse(_))
|| self.allowed_replacements.contains(&(target.local, loc));
if perform_opt { loop {
*place = target.project_deeper(&place.projection[1..], self.tcx); if let Value::Pointer(target, _) = self.targets[place.local] {
self.any_replacement = true; 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;
} }
} }

View file

@ -41,8 +41,7 @@
- StorageLive(_5); // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26 - 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 - _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 - _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 _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
_3 = _4; // scope 2 at $DIR/reference_prop.rs:+3:16: +3:36 _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(_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 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 - (*_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 - _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 - 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 + _7 = _1; // 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 + _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 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 _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 StorageLive(_10); // scope 5 at $DIR/reference_prop.rs:+8:9: +8:10

View file

@ -9,15 +9,14 @@
let mut _5: *mut usize; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL let mut _5: *mut usize; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
bb0: { 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 - _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 - _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 - _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 = (*_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 - _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 = (*_1); // scope 0 at $DIR/reference_prop.rs:+15:13: +15:22
+ _0 = (*_2); // scope 0 at $DIR/reference_prop.rs:+15:13: +15:22 + _0 = (*_1); // scope 0 at $DIR/reference_prop.rs:+16:13: +16:22
+ _0 = (*_3); // scope 0 at $DIR/reference_prop.rs:+16:13: +16:22
return; // scope 0 at $DIR/reference_prop.rs:+17:13: +17:21 return; // scope 0 at $DIR/reference_prop.rs:+17:13: +17:21
} }
} }