Skip to content

Commit d0d2850

Browse files
Auto merge of #150222 - dianqk:perf/gvn-new-deref-arg, r=<try>
[PERF] For #147886
2 parents d0e6d77 + 8c81135 commit d0d2850

2 files changed

Lines changed: 52 additions & 10 deletions

File tree

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,13 @@ enum Value<'a, 'tcx> {
243243

244244
// Extractions.
245245
/// This is the *value* obtained by projecting another value.
246-
Projection(VnIndex, ProjectionElem<VnIndex, ()>),
246+
Projection {
247+
base: VnIndex,
248+
elem: ProjectionElem<VnIndex, ()>,
249+
/// Some values may be a borrow or pointer.
250+
/// Give them a different provenance, so we don't merge them.
251+
provenance: Option<VnOpaque>,
252+
},
247253
/// Discriminant of the given value.
248254
Discriminant(VnIndex),
249255

@@ -292,6 +298,7 @@ impl<'a, 'tcx> ValueSet<'a, 'tcx> {
292298
debug_assert!(match value {
293299
Value::Opaque(_) | Value::Address { .. } => true,
294300
Value::Constant { disambiguator, .. } => disambiguator.is_some(),
301+
Value::Projection { provenance, .. } => provenance.is_some(),
295302
_ => false,
296303
});
297304

@@ -545,7 +552,24 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
545552
}
546553

547554
fn insert_deref(&mut self, ty: Ty<'tcx>, value: VnIndex) -> VnIndex {
548-
let value = self.insert(ty, Value::Projection(value, ProjectionElem::Deref));
555+
let value = if ty.is_any_ptr() {
556+
// Give each borrow and pointer a different provenance, so we don't merge them.
557+
let index = self.values.insert_unique(ty, |provenance| Value::Projection {
558+
base: value,
559+
elem: ProjectionElem::Deref,
560+
provenance: Some(provenance),
561+
});
562+
let _index = self.evaluated.push(Some(None));
563+
debug_assert_eq!(index, _index);
564+
let _index = self.rev_locals.push(SmallVec::new());
565+
debug_assert_eq!(index, _index);
566+
index
567+
} else {
568+
self.insert(
569+
ty,
570+
Value::Projection { base: value, elem: ProjectionElem::Deref, provenance: None },
571+
)
572+
};
549573
self.derefs.push(value);
550574
value
551575
}
@@ -649,7 +673,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
649673
ImmTy::from_immediate(ptr_imm, ty).into()
650674
}
651675

652-
Projection(base, elem) => {
676+
Projection { base, elem, .. } => {
653677
let base = self.eval_to_const(base)?;
654678
// `Index` by constants should have been replaced by `ConstantIndex` by
655679
// `simplify_place_projection`.
@@ -829,8 +853,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
829853
ProjectionElem::Field(f, _) => match self.get(value) {
830854
Value::Aggregate(_, fields) => return Some((projection_ty, fields[f.as_usize()])),
831855
Value::Union(active, field) if active == f => return Some((projection_ty, field)),
832-
Value::Projection(outer_value, ProjectionElem::Downcast(_, read_variant))
833-
if let Value::Aggregate(written_variant, fields) = self.get(outer_value)
856+
Value::Projection {
857+
base, elem: ProjectionElem::Downcast(_, read_variant), ..
858+
} if let Value::Aggregate(written_variant, fields) = self.get(base)
834859
// This pass is not aware of control-flow, so we do not know whether the
835860
// replacement we are doing is actually reachable. We could be in any arm of
836861
// ```
@@ -883,7 +908,10 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
883908
ProjectionElem::UnwrapUnsafeBinder(_) => ProjectionElem::UnwrapUnsafeBinder(()),
884909
};
885910

886-
let value = self.insert(projection_ty.ty, Value::Projection(value, proj));
911+
let value = self.insert(
912+
projection_ty.ty,
913+
Value::Projection { base: value, elem: proj, provenance: None },
914+
);
887915
Some((projection_ty, value))
888916
}
889917

@@ -1112,11 +1140,17 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
11121140
fields: &[VnIndex],
11131141
) -> Option<VnIndex> {
11141142
let Some(&first_field) = fields.first() else { return None };
1115-
let Value::Projection(copy_from_value, _) = self.get(first_field) else { return None };
1143+
let Value::Projection { base: copy_from_value, .. } = self.get(first_field) else {
1144+
return None;
1145+
};
11161146

11171147
// All fields must correspond one-to-one and come from the same aggregate value.
11181148
if fields.iter().enumerate().any(|(index, &v)| {
1119-
if let Value::Projection(pointer, ProjectionElem::Field(from_index, _)) = self.get(v)
1149+
if let Value::Projection {
1150+
base: pointer,
1151+
elem: ProjectionElem::Field(from_index, _),
1152+
..
1153+
} = self.get(v)
11201154
&& copy_from_value == pointer
11211155
&& from_index.index() == index
11221156
{
@@ -1128,7 +1162,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
11281162
}
11291163

11301164
let mut copy_from_local_value = copy_from_value;
1131-
if let Value::Projection(pointer, proj) = self.get(copy_from_value)
1165+
if let Value::Projection { base: pointer, elem: proj, .. } = self.get(copy_from_value)
11321166
&& let ProjectionElem::Downcast(_, read_variant) = proj
11331167
{
11341168
if variant_index == read_variant {
@@ -1839,7 +1873,7 @@ impl<'tcx> VnState<'_, '_, 'tcx> {
18391873
// If we are here, we failed to find a local, and we already have a `Deref`.
18401874
// Trying to add projections will only result in an ill-formed place.
18411875
return None;
1842-
} else if let Value::Projection(pointer, proj) = self.get(index)
1876+
} else if let Value::Projection { base: pointer, elem: proj, .. } = self.get(index)
18431877
&& (allow_complex_projection || proj.is_stable_offset())
18441878
&& let Some(proj) = self.try_as_place_elem(self.ty(index), proj, loc)
18451879
{

tests/mir-opt/pre-codegen/deref_nested_borrows.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
fn src(x: &&u8) -> bool {
44
// CHECK-LABEL: fn src(
5+
// CHECK: debug y => [[Y:_.*]];
6+
// CHECK: bb0:
7+
// CHECK: [[BORROW_u8:_.*]] = copy (*_1);
8+
// CHECK: [[Y]] = copy (*[[BORROW_u8]]);
9+
// CHECK: bb1:
10+
// BORROW_u8 outside its lifetime in bb1.
11+
// CHECK-NOT: copy (*[[BORROW_u8]]);
12+
// CHECK: copy (*_1);
513
// CHECK-NOT: _0 = const true;
614
// CHECK: _0 = Eq({{.*}}, {{.*}});
715
// CHECK-NOT: _0 = const true;

0 commit comments

Comments
 (0)