Skip to content

Commit 7f34f6e

Browse files
committed
Do not hash opaques in GVN.
1 parent 3d0eda7 commit 7f34f6e

File tree

1 file changed

+90
-39
lines changed
  • compiler/rustc_mir_transform/src

1 file changed

+90
-39
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 90 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ use rustc_data_structures::fx::FxHasher;
100100
use rustc_data_structures::graph::dominators::Dominators;
101101
use rustc_hir::def::DefKind;
102102
use rustc_index::bit_set::DenseBitSet;
103-
use rustc_index::{IndexVec, newtype_index};
103+
use rustc_index::{Idx, IndexVec, newtype_index};
104104
use rustc_middle::bug;
105105
use rustc_middle::mir::interpret::GlobalAlloc;
106106
use rustc_middle::mir::visit::*;
@@ -158,6 +158,14 @@ newtype_index! {
158158
struct VnIndex {}
159159
}
160160

161+
newtype_index! {
162+
/// Counter type to ensure that all unique values are created using `insert_unique`.
163+
#[debug_format = "_o{}"]
164+
struct VnOpaque {
165+
const DETERMINISTIC = 0;
166+
}
167+
}
168+
161169
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
162170
enum AddressKind {
163171
Ref(BorrowKind),
@@ -169,14 +177,14 @@ enum Value<'tcx> {
169177
// Root values.
170178
/// Used to represent values we know nothing about.
171179
/// The `usize` is a counter incremented by `new_opaque`.
172-
Opaque(usize),
180+
Opaque(VnOpaque),
173181
/// Evaluated or unevaluated constant value.
174182
Constant {
175183
value: Const<'tcx>,
176184
/// Some constants do not have a deterministic value. To avoid merging two instances of the
177185
/// same `Const`, we assign them an additional integer index.
178-
// `disambiguator` is 0 iff the constant is deterministic.
179-
disambiguator: usize,
186+
// `disambiguator` is `DETERMINISTIC` iff the constant is deterministic.
187+
disambiguator: VnOpaque,
180188
},
181189
/// An aggregate value, either tuple/closure/struct/enum.
182190
/// This does not contain unions, as we cannot reason with the value.
@@ -195,7 +203,7 @@ enum Value<'tcx> {
195203
place: Place<'tcx>,
196204
kind: AddressKind,
197205
/// Give each borrow and pointer a different provenance, so we don't merge them.
198-
provenance: usize,
206+
provenance: VnOpaque,
199207
},
200208

201209
// Extractions.
@@ -227,7 +235,7 @@ struct ValueSet<'tcx> {
227235
values: IndexVec<VnIndex, Value<'tcx>>,
228236
types: IndexVec<VnIndex, Ty<'tcx>>,
229237
/// Counter to generate different values.
230-
next_opaque: usize,
238+
next_opaque: VnOpaque,
231239
}
232240

233241
impl<'tcx> ValueSet<'tcx> {
@@ -237,14 +245,45 @@ impl<'tcx> ValueSet<'tcx> {
237245
hashes: IndexVec::with_capacity(num_values),
238246
values: IndexVec::with_capacity(num_values),
239247
types: IndexVec::with_capacity(num_values),
240-
next_opaque: 1,
248+
// The first opaque is 1, as 0 means deterministic constant.
249+
next_opaque: VnOpaque::from_u32(1),
241250
}
242251
}
243252

253+
/// Insert a `(Value, Ty)` pair without hashing or deduplication.
254+
#[inline]
255+
fn insert_unique(
256+
&mut self,
257+
ty: Ty<'tcx>,
258+
value: impl FnOnce(VnOpaque) -> Value<'tcx>,
259+
) -> VnIndex {
260+
let value = value(self.next_opaque);
261+
self.next_opaque.increment_by(1);
262+
263+
debug_assert!(match value {
264+
Value::Opaque(_) | Value::Address { .. } => true,
265+
Value::Constant { disambiguator, .. } => disambiguator != DETERMINISTIC,
266+
_ => false,
267+
});
268+
269+
let index = self.hashes.push(0);
270+
let _index = self.types.push(ty);
271+
debug_assert_eq!(index, _index);
272+
let _index = self.values.push(value);
273+
debug_assert_eq!(index, _index);
274+
index
275+
}
276+
244277
/// Insert a `(Value, Ty)` pair to be deduplicated.
245278
/// Returns `true` as second tuple field if this value did not exist previously.
246279
#[allow(rustc::pass_by_value)] // closures take `&VnIndex`
247280
fn insert(&mut self, ty: Ty<'tcx>, value: Value<'tcx>) -> (VnIndex, bool) {
281+
debug_assert!(match value {
282+
Value::Opaque(_) | Value::Address { .. } => false,
283+
Value::Constant { disambiguator, .. } => disambiguator == DETERMINISTIC,
284+
_ => true,
285+
});
286+
248287
let hash: u64 = {
249288
let mut h = FxHasher::default();
250289
value.hash(&mut h);
@@ -271,14 +310,6 @@ impl<'tcx> ValueSet<'tcx> {
271310
}
272311
}
273312

274-
/// Increment the opaque index counter return a new unique value.
275-
#[inline]
276-
fn next_opaque(&mut self) -> usize {
277-
let next_opaque = self.next_opaque;
278-
self.next_opaque += 1;
279-
next_opaque
280-
}
281-
282313
/// Return the `Value` associated with the given `VnIndex`.
283314
#[inline]
284315
fn value(&self, index: VnIndex) -> &Value<'tcx> {
@@ -294,8 +325,8 @@ impl<'tcx> ValueSet<'tcx> {
294325
/// Replace the value associated with `index` with an opaque value.
295326
#[inline]
296327
fn forget(&mut self, index: VnIndex) {
297-
let opaque = self.next_opaque();
298-
self.values[index] = Value::Opaque(opaque);
328+
self.values[index] = Value::Opaque(self.next_opaque);
329+
self.next_opaque.increment_by(1);
299330
}
300331
}
301332

@@ -373,8 +404,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
373404
/// from all the others.
374405
#[instrument(level = "trace", skip(self), ret)]
375406
fn new_opaque(&mut self, ty: Ty<'tcx>) -> VnIndex {
376-
let value = Value::Opaque(self.values.next_opaque());
377-
self.insert(ty, value)
407+
let index = self.values.insert_unique(ty, Value::Opaque);
408+
let _index = self.evaluated.push(None);
409+
debug_assert_eq!(index, _index);
410+
let _index = self.rev_locals.push(SmallVec::new());
411+
debug_assert_eq!(index, _index);
412+
index
378413
}
379414

380415
/// Create a new `Value::Address` distinct from all the others.
@@ -387,8 +422,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
387422
}
388423
AddressKind::Address(mutbl) => Ty::new_ptr(self.tcx, pty, mutbl.to_mutbl_lossy()),
389424
};
390-
let value = Value::Address { place, kind, provenance: self.values.next_opaque() };
391-
self.insert(ty, value)
425+
let index =
426+
self.values.insert_unique(ty, |provenance| Value::Address { place, kind, provenance });
427+
let evaluated = self.eval_to_const(index);
428+
let _index = self.evaluated.push(evaluated);
429+
debug_assert_eq!(index, _index);
430+
let _index = self.rev_locals.push(SmallVec::new());
431+
debug_assert_eq!(index, _index);
432+
index
433+
}
434+
435+
#[instrument(level = "trace", skip(self), ret)]
436+
fn insert_constant(&mut self, value: Const<'tcx>) -> VnIndex {
437+
let (index, new) = if value.is_deterministic() {
438+
// The constant is deterministic, no need to disambiguate.
439+
let constant = Value::Constant { value, disambiguator: DETERMINISTIC };
440+
self.values.insert(value.ty(), constant)
441+
} else {
442+
// Multiple mentions of this constant will yield different values,
443+
// so assign a different `disambiguator` to ensure they do not get the same `VnIndex`.
444+
let index = self.values.insert_unique(value.ty(), |disambiguator| {
445+
debug_assert_ne!(disambiguator, DETERMINISTIC);
446+
Value::Constant { value, disambiguator }
447+
});
448+
(index, true)
449+
};
450+
if new {
451+
let evaluated = self.eval_to_const(index);
452+
let _index = self.evaluated.push(evaluated);
453+
debug_assert_eq!(index, _index);
454+
let _index = self.rev_locals.push(SmallVec::new());
455+
debug_assert_eq!(index, _index);
456+
}
457+
index
392458
}
393459

394460
#[inline]
@@ -409,33 +475,18 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
409475
self.rev_locals[value].push(local);
410476
}
411477

412-
fn insert_constant(&mut self, value: Const<'tcx>) -> VnIndex {
413-
let disambiguator = if value.is_deterministic() {
414-
// The constant is deterministic, no need to disambiguate.
415-
0
416-
} else {
417-
// Multiple mentions of this constant will yield different values,
418-
// so assign a different `disambiguator` to ensure they do not get the same `VnIndex`.
419-
let disambiguator = self.values.next_opaque();
420-
// `disambiguator: 0` means deterministic.
421-
debug_assert_ne!(disambiguator, 0);
422-
disambiguator
423-
};
424-
self.insert(value.ty(), Value::Constant { value, disambiguator })
425-
}
426-
427478
fn insert_bool(&mut self, flag: bool) -> VnIndex {
428479
// Booleans are deterministic.
429480
let value = Const::from_bool(self.tcx, flag);
430481
debug_assert!(value.is_deterministic());
431-
self.insert(self.tcx.types.bool, Value::Constant { value, disambiguator: 0 })
482+
self.insert(self.tcx.types.bool, Value::Constant { value, disambiguator: DETERMINISTIC })
432483
}
433484

434485
fn insert_scalar(&mut self, ty: Ty<'tcx>, scalar: Scalar) -> VnIndex {
435486
// Scalars are deterministic.
436487
let value = Const::from_scalar(self.tcx, scalar, ty);
437488
debug_assert!(value.is_deterministic());
438-
self.insert(ty, Value::Constant { value, disambiguator: 0 })
489+
self.insert(ty, Value::Constant { value, disambiguator: DETERMINISTIC })
439490
}
440491

441492
fn insert_tuple(&mut self, ty: Ty<'tcx>, values: Vec<VnIndex>) -> VnIndex {
@@ -1680,7 +1731,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16801731
// This was already constant in MIR, do not change it. If the constant is not
16811732
// deterministic, adding an additional mention of it in MIR will not give the same value as
16821733
// the former mention.
1683-
if let Value::Constant { value, disambiguator: 0 } = *self.get(index) {
1734+
if let Value::Constant { value, disambiguator: DETERMINISTIC } = *self.get(index) {
16841735
debug_assert!(value.is_deterministic());
16851736
return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value });
16861737
}

0 commit comments

Comments
 (0)