Skip to content

Commit 0171927

Browse files
committed
Invalidate all dereferences
1 parent 418b4ed commit 0171927

File tree

3 files changed

+37
-13
lines changed

3 files changed

+37
-13
lines changed

compiler/rustc_data_structures/src/fx.rs

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ pub type FxIndexSet<V> = indexmap::IndexSet<V, BuildHasherDefault<FxHasher>>;
99
pub type IndexEntry<'a, K, V> = indexmap::map::Entry<'a, K, V>;
1010
pub type IndexOccupiedEntry<'a, K, V> = indexmap::map::OccupiedEntry<'a, K, V>;
1111

12+
pub use indexmap::set::MutableValues;
13+
1214
#[macro_export]
1315
macro_rules! define_id_collections {
1416
($map_name:ident, $set_name:ident, $entry_name:ident, $key:ty) => {

compiler/rustc_mir_transform/src/gvn.rs

+32-8
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ use rustc_const_eval::interpret::{
9393
ImmTy, Immediate, InterpCx, MemPlaceMeta, MemoryKind, OpTy, Projectable, Scalar,
9494
intern_const_alloc_for_constprop,
9595
};
96-
use rustc_data_structures::fx::FxIndexSet;
96+
use rustc_data_structures::fx::{FxIndexSet, MutableValues};
9797
use rustc_data_structures::graph::dominators::Dominators;
9898
use rustc_hir::def::DefKind;
9999
use rustc_index::bit_set::BitSet;
@@ -234,6 +234,8 @@ struct VnState<'body, 'tcx> {
234234
evaluated: IndexVec<VnIndex, Option<OpTy<'tcx>>>,
235235
/// Counter to generate different values.
236236
next_opaque: usize,
237+
/// Cache the deref values.
238+
derefs: Vec<VnIndex>,
237239
/// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop.
238240
feature_unsized_locals: bool,
239241
ssa: &'body SsaLocals,
@@ -266,6 +268,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
266268
values: FxIndexSet::with_capacity_and_hasher(num_values, Default::default()),
267269
evaluated: IndexVec::with_capacity(num_values),
268270
next_opaque: 1,
271+
derefs: Vec::new(),
269272
feature_unsized_locals: tcx.features().unsized_locals(),
270273
ssa,
271274
dominators,
@@ -364,6 +367,21 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
364367
self.insert(Value::Aggregate(AggregateTy::Tuple, VariantIdx::ZERO, values))
365368
}
366369

370+
fn insert_deref(&mut self, value: VnIndex) -> VnIndex {
371+
let value = self.insert(Value::Projection(value, ProjectionElem::Deref));
372+
self.derefs.push(value);
373+
value
374+
}
375+
376+
fn invalidate_derefs(&mut self) {
377+
let mut derefs = Vec::new();
378+
std::mem::swap(&mut derefs, &mut self.derefs);
379+
for deref in derefs {
380+
let opaque = self.next_opaque();
381+
*self.values.get_index_mut2(deref.index()).unwrap() = Value::Opaque(opaque);
382+
}
383+
}
384+
367385
#[instrument(level = "trace", skip(self), ret)]
368386
fn eval_to_const(&mut self, value: VnIndex) -> Option<OpTy<'tcx>> {
369387
use Value::*;
@@ -624,7 +642,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
624642
{
625643
// An immutable borrow `_x` always points to the same value for the
626644
// lifetime of the borrow, so we can merge all instances of `*_x`.
627-
ProjectionElem::Deref
645+
return Some(self.insert_deref(value));
628646
} else {
629647
return None;
630648
}
@@ -1626,6 +1644,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
16261644
self.assign(local, value);
16271645
Some(value)
16281646
} else {
1647+
// Non-local assignments maybe invalidate deref.
1648+
self.invalidate_derefs();
16291649
value
16301650
};
16311651
let Some(value) = value else { return };
@@ -1645,12 +1665,16 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
16451665
}
16461666

16471667
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) {
1648-
if let Terminator { kind: TerminatorKind::Call { destination, .. }, .. } = terminator
1649-
&& let Some(local) = destination.as_local()
1650-
&& self.ssa.is_ssa(local)
1651-
{
1652-
let opaque = self.new_opaque();
1653-
self.assign(local, opaque);
1668+
if let Terminator { kind: TerminatorKind::Call { destination, .. }, .. } = terminator {
1669+
if let Some(local) = destination.as_local()
1670+
&& self.ssa.is_ssa(local)
1671+
{
1672+
let opaque = self.new_opaque();
1673+
self.assign(local, opaque);
1674+
}
1675+
// Function calls maybe invalidate nested deref, and non-local assignments maybe invalidate deref.
1676+
// Currently, no distinction is made between these two cases.
1677+
self.invalidate_derefs();
16541678
}
16551679
self.super_terminator(terminator, location);
16561680
}

tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff

+3-5
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
}
2020

2121
bb0: {
22-
- StorageLive(_2);
23-
+ nop;
22+
StorageLive(_2);
2423
StorageLive(_3);
2524
StorageLive(_4);
2625
_4 = &_1;
@@ -50,13 +49,12 @@
5049
StorageLive(_9);
5150
_9 = copy _6;
5251
- _0 = Option::<i32>::Some(move _9);
53-
+ _0 = copy (*_2);
52+
+ _0 = Option::<i32>::Some(copy _6);
5453
StorageDead(_9);
5554
- StorageDead(_6);
5655
+ nop;
5756
StorageDead(_4);
58-
- StorageDead(_2);
59-
+ nop;
57+
StorageDead(_2);
6058
return;
6159
}
6260

0 commit comments

Comments
 (0)