diff options
| author | dianqk <dianqk@dianqk.net> | 2025-03-24 16:55:24 +0800 |
|---|---|---|
| committer | dianqk <dianqk@dianqk.net> | 2025-04-02 19:58:35 +0800 |
| commit | 7830406df1232c59f82d870c218901b8643701bb (patch) | |
| tree | 70cf373018301cccd707f80807ecb2516c01cb7b /compiler | |
| parent | 84af55679131e5074b7236fbdd98b12e9012b94e (diff) | |
| download | rust-7830406df1232c59f82d870c218901b8643701bb.tar.gz rust-7830406df1232c59f82d870c218901b8643701bb.zip | |
Invalidate all dereferences for non-local assignments
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_data_structures/src/fx.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/gvn.rs | 38 |
2 files changed, 32 insertions, 8 deletions
diff --git a/compiler/rustc_data_structures/src/fx.rs b/compiler/rustc_data_structures/src/fx.rs index 80e72250470..f0db9623b67 100644 --- a/compiler/rustc_data_structures/src/fx.rs +++ b/compiler/rustc_data_structures/src/fx.rs @@ -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) => { diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 42d736cf5f4..944c21eab40 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -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,12 +1776,16 @@ 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() - && self.ssa.is_ssa(local) - { - let opaque = self.new_opaque(); - self.assign(local, opaque); + 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); } |
