1
Fork 0

Invalidate all dereferences for non-local assignments

This commit is contained in:
dianqk 2025-03-24 16:55:24 +08:00
parent 84af556791
commit 7830406df1
No known key found for this signature in database
3 changed files with 35 additions and 13 deletions

View file

@ -9,6 +9,8 @@ pub type FxIndexSet<V> = indexmap::IndexSet<V, BuildHasherDefault<FxHasher>>;
pub type IndexEntry<'a, K, V> = indexmap::map::Entry<'a, K, V>;
pub type IndexOccupiedEntry<'a, K, V> = indexmap::map::OccupiedEntry<'a, K, V>;
pub use indexmap::set::MutableValues;
#[macro_export]
macro_rules! define_id_collections {
($map_name:ident, $set_name:ident, $entry_name:ident, $key:ty) => {

View file

@ -93,7 +93,7 @@ use rustc_const_eval::interpret::{
ImmTy, Immediate, InterpCx, MemPlaceMeta, MemoryKind, OpTy, Projectable, Scalar,
intern_const_alloc_for_constprop,
};
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::fx::{FxIndexSet, MutableValues};
use rustc_data_structures::graph::dominators::Dominators;
use rustc_hir::def::DefKind;
use rustc_index::bit_set::DenseBitSet;
@ -238,6 +238,8 @@ struct VnState<'body, 'tcx> {
evaluated: IndexVec<VnIndex, Option<OpTy<'tcx>>>,
/// Counter to generate different values.
next_opaque: usize,
/// Cache the deref values.
derefs: Vec<VnIndex>,
/// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop.
feature_unsized_locals: bool,
ssa: &'body SsaLocals,
@ -270,6 +272,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
values: FxIndexSet::with_capacity_and_hasher(num_values, Default::default()),
evaluated: IndexVec::with_capacity(num_values),
next_opaque: 1,
derefs: Vec::new(),
feature_unsized_locals: tcx.features().unsized_locals(),
ssa,
dominators,
@ -368,6 +371,19 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
self.insert(Value::Aggregate(AggregateTy::Tuple, VariantIdx::ZERO, values))
}
fn insert_deref(&mut self, value: VnIndex) -> VnIndex {
let value = self.insert(Value::Projection(value, ProjectionElem::Deref));
self.derefs.push(value);
value
}
fn invalidate_derefs(&mut self) {
for deref in std::mem::take(&mut self.derefs) {
let opaque = self.next_opaque();
*self.values.get_index_mut2(deref.index()).unwrap() = Value::Opaque(opaque);
}
}
#[instrument(level = "trace", skip(self), ret)]
fn eval_to_const(&mut self, value: VnIndex) -> Option<OpTy<'tcx>> {
use Value::*;
@ -634,7 +650,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
{
// An immutable borrow `_x` always points to the same value for the
// lifetime of the borrow, so we can merge all instances of `*_x`.
ProjectionElem::Deref
return Some(self.insert_deref(value));
} else {
return None;
}
@ -1739,6 +1755,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
self.assign(local, value);
Some(value)
} else {
// Non-local assignments maybe invalidate deref.
self.invalidate_derefs();
value
};
let Some(value) = value else { return };
@ -1758,13 +1776,17 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
}
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) {
if let Terminator { kind: TerminatorKind::Call { destination, .. }, .. } = terminator
&& let Some(local) = destination.as_local()
if let Terminator { kind: TerminatorKind::Call { destination, .. }, .. } = terminator {
if let Some(local) = destination.as_local()
&& self.ssa.is_ssa(local)
{
let opaque = self.new_opaque();
self.assign(local, opaque);
}
// Function calls maybe invalidate nested deref, and non-local assignments maybe invalidate deref.
// Currently, no distinction is made between these two cases.
self.invalidate_derefs();
}
self.super_terminator(terminator, location);
}
}

View file

@ -19,8 +19,7 @@
}
bb0: {
- StorageLive(_2);
+ nop;
StorageLive(_2);
StorageLive(_3);
StorageLive(_4);
_4 = &_1;
@ -50,13 +49,12 @@
StorageLive(_9);
_9 = copy _6;
- _0 = Option::<i32>::Some(move _9);
+ _0 = copy (*_2);
+ _0 = Option::<i32>::Some(copy _6);
StorageDead(_9);
- StorageDead(_6);
+ nop;
StorageDead(_4);
- StorageDead(_2);
+ nop;
StorageDead(_2);
return;
}