Skip to content

Commit b7e2153

Browse files
committed
Do not hash opaques in GVN.
1 parent 57befd8 commit b7e2153

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
@@ -99,7 +99,7 @@ use rustc_data_structures::fx::FxHasher;
9999
use rustc_data_structures::graph::dominators::Dominators;
100100
use rustc_hir::def::DefKind;
101101
use rustc_index::bit_set::DenseBitSet;
102-
use rustc_index::{IndexVec, newtype_index};
102+
use rustc_index::{Idx, IndexVec, newtype_index};
103103
use rustc_middle::bug;
104104
use rustc_middle::mir::interpret::GlobalAlloc;
105105
use rustc_middle::mir::visit::*;
@@ -157,6 +157,14 @@ newtype_index! {
157157
struct VnIndex {}
158158
}
159159

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

200208
// Extractions.
@@ -226,7 +234,7 @@ struct ValueSet<'tcx> {
226234
values: IndexVec<VnIndex, Value<'tcx>>,
227235
types: IndexVec<VnIndex, Ty<'tcx>>,
228236
/// Counter to generate different values.
229-
next_opaque: usize,
237+
next_opaque: VnOpaque,
230238
}
231239

232240
impl<'tcx> ValueSet<'tcx> {
@@ -236,14 +244,45 @@ impl<'tcx> ValueSet<'tcx> {
236244
hashes: IndexVec::with_capacity(num_values),
237245
values: IndexVec::with_capacity(num_values),
238246
types: IndexVec::with_capacity(num_values),
239-
next_opaque: 1,
247+
// The first opaque is 1, as 0 means deterministic constant.
248+
next_opaque: VnOpaque::from_u32(1),
240249
}
241250
}
242251

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

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

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

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

393459
#[inline]
@@ -408,33 +474,18 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
408474
self.rev_locals[value].push(local);
409475
}
410476

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

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

440491
fn insert_tuple(&mut self, ty: Ty<'tcx>, values: Vec<VnIndex>) -> VnIndex {
@@ -1690,7 +1741,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16901741
// This was already constant in MIR, do not change it. If the constant is not
16911742
// deterministic, adding an additional mention of it in MIR will not give the same value as
16921743
// the former mention.
1693-
if let Value::Constant { value, disambiguator: 0 } = *self.get(index) {
1744+
if let Value::Constant { value, disambiguator: DETERMINISTIC } = *self.get(index) {
16941745
debug_assert!(value.is_deterministic());
16951746
return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value });
16961747
}

0 commit comments

Comments
 (0)