GVN: Do not introduce new dereferences if they borrow from non-SSA locals

This commit is contained in:
dianqk 2025-12-29 21:30:37 +08:00
parent 9f9c4c8b0b
commit bc2bf6b544
No known key found for this signature in database
28 changed files with 339 additions and 238 deletions

View file

@ -135,7 +135,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls, &arena); VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls, &arena);
for local in body.args_iter().filter(|&local| ssa.is_ssa(local)) { for local in body.args_iter().filter(|&local| ssa.is_ssa(local)) {
let opaque = state.new_opaque(body.local_decls[local].ty); let opaque = state.new_argument(body.local_decls[local].ty);
state.assign(local, opaque); state.assign(local, opaque);
} }
@ -198,8 +198,9 @@ enum AddressBase {
enum Value<'a, 'tcx> { enum Value<'a, 'tcx> {
// Root values. // Root values.
/// Used to represent values we know nothing about. /// Used to represent values we know nothing about.
/// The `usize` is a counter incremented by `new_opaque`.
Opaque(VnOpaque), Opaque(VnOpaque),
/// The value is a argument.
Argument(VnOpaque),
/// Evaluated or unevaluated constant value. /// Evaluated or unevaluated constant value.
Constant { Constant {
value: Const<'tcx>, value: Const<'tcx>,
@ -284,7 +285,7 @@ impl<'a, 'tcx> ValueSet<'a, 'tcx> {
let value = value(VnOpaque); let value = value(VnOpaque);
debug_assert!(match value { debug_assert!(match value {
Value::Opaque(_) | Value::Address { .. } => true, Value::Opaque(_) | Value::Argument(_) | Value::Address { .. } => true,
Value::Constant { disambiguator, .. } => disambiguator.is_some(), Value::Constant { disambiguator, .. } => disambiguator.is_some(),
_ => false, _ => false,
}); });
@ -440,6 +441,13 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
index index
} }
#[instrument(level = "trace", skip(self), ret)]
fn new_argument(&mut self, ty: Ty<'tcx>) -> VnIndex {
let index = self.insert_unique(ty, Value::Argument);
self.evaluated[index] = Some(None);
index
}
/// Create a new `Value::Address` distinct from all the others. /// Create a new `Value::Address` distinct from all the others.
#[instrument(level = "trace", skip(self), ret)] #[instrument(level = "trace", skip(self), ret)]
fn new_pointer(&mut self, place: Place<'tcx>, kind: AddressKind) -> Option<VnIndex> { fn new_pointer(&mut self, place: Place<'tcx>, kind: AddressKind) -> Option<VnIndex> {
@ -457,8 +465,11 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
// Skip the initial `Deref`. // Skip the initial `Deref`.
projection.next(); projection.next();
AddressBase::Deref(base) AddressBase::Deref(base)
} else { } else if self.ssa.is_ssa(place.local) {
// Only propagate the pointer of the SSA local.
AddressBase::Local(place.local) AddressBase::Local(place.local)
} else {
return None;
}; };
// Do not try evaluating inside `Index`, this has been done by `simplify_place_projection`. // Do not try evaluating inside `Index`, this has been done by `simplify_place_projection`.
let projection = let projection =
@ -526,10 +537,6 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
self.insert(ty, Value::Aggregate(VariantIdx::ZERO, self.arena.alloc_slice(values))) self.insert(ty, Value::Aggregate(VariantIdx::ZERO, self.arena.alloc_slice(values)))
} }
fn insert_deref(&mut self, ty: Ty<'tcx>, value: VnIndex) -> VnIndex {
self.insert(ty, Value::Projection(value, ProjectionElem::Deref))
}
#[instrument(level = "trace", skip(self), ret)] #[instrument(level = "trace", skip(self), ret)]
fn eval_to_const_inner(&mut self, value: VnIndex) -> Option<OpTy<'tcx>> { fn eval_to_const_inner(&mut self, value: VnIndex) -> Option<OpTy<'tcx>> {
use Value::*; use Value::*;
@ -543,7 +550,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
let op = match self.get(value) { let op = match self.get(value) {
_ if ty.is_zst() => ImmTy::uninit(ty).into(), _ if ty.is_zst() => ImmTy::uninit(ty).into(),
Opaque(_) => return None, Opaque(_) | Argument(_) => return None,
// Keep runtime check constants as symbolic. // Keep runtime check constants as symbolic.
RuntimeChecks(..) => return None, RuntimeChecks(..) => return None,
@ -795,7 +802,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
// An immutable borrow `_x` always points to the same value for the // An immutable borrow `_x` always points to the same value for the
// lifetime of the borrow, so we can merge all instances of `*_x`. // lifetime of the borrow, so we can merge all instances of `*_x`.
return Some((projection_ty, self.insert_deref(projection_ty.ty, value))); let deref = self
.insert(projection_ty.ty, Value::Projection(value, ProjectionElem::Deref));
return Some((projection_ty, deref));
} else { } else {
return None; return None;
} }
@ -1014,7 +1023,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
let op = self.simplify_operand(op, location)?; let op = self.simplify_operand(op, location)?;
Value::Repeat(op, amount) Value::Repeat(op, amount)
} }
Rvalue::Aggregate(..) => return self.simplify_aggregate(lhs, rvalue, location), Rvalue::Aggregate(..) => return self.simplify_aggregate(rvalue, location),
Rvalue::Ref(_, borrow_kind, ref mut place) => { Rvalue::Ref(_, borrow_kind, ref mut place) => {
self.simplify_place_projection(place, location); self.simplify_place_projection(place, location);
return self.new_pointer(*place, AddressKind::Ref(borrow_kind)); return self.new_pointer(*place, AddressKind::Ref(borrow_kind));
@ -1125,7 +1134,6 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
fn simplify_aggregate( fn simplify_aggregate(
&mut self, &mut self,
lhs: &Place<'tcx>,
rvalue: &mut Rvalue<'tcx>, rvalue: &mut Rvalue<'tcx>,
location: Location, location: Location,
) -> Option<VnIndex> { ) -> Option<VnIndex> {
@ -1208,12 +1216,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
} }
if let Some(value) = self.simplify_aggregate_to_copy(ty, variant_index, &fields) { if let Some(value) = self.simplify_aggregate_to_copy(ty, variant_index, &fields) {
// Allow introducing places with non-constant offsets, as those are still better than if let Some(place) = self.try_as_place(value, location, true) {
// reconstructing an aggregate. But avoid creating `*a = copy (*b)`, as they might be
// aliases resulting in overlapping assignments.
let allow_complex_projection =
lhs.projection[..].iter().all(PlaceElem::is_stable_offset);
if let Some(place) = self.try_as_place(value, location, allow_complex_projection) {
self.reused_locals.insert(place.local); self.reused_locals.insert(place.local);
*rvalue = Rvalue::Use(Operand::Copy(place)); *rvalue = Rvalue::Use(Operand::Copy(place));
} }
@ -1867,6 +1870,17 @@ impl<'tcx> VnState<'_, '_, 'tcx> {
&& (allow_complex_projection || proj.is_stable_offset()) && (allow_complex_projection || proj.is_stable_offset())
&& let Some(proj) = self.try_as_place_elem(self.ty(index), proj, loc) && let Some(proj) = self.try_as_place_elem(self.ty(index), proj, loc)
{ {
if proj == PlaceElem::Deref {
// We can introduce a new dereference if the source value cannot be changed in the body.
// Dereferencing an immutable argument always gives the same value in the body.
match self.get(pointer) {
Value::Argument(_)
if let Some(Mutability::Not) = self.ty(pointer).ref_mutability() => {}
_ => {
return None;
}
}
}
projection.push(proj); projection.push(proj);
index = pointer; index = pointer;
} else { } else {

View file

@ -75,8 +75,7 @@
bb0: { bb0: {
StorageLive(_1); StorageLive(_1);
- StorageLive(_2); StorageLive(_2);
+ nop;
StorageLive(_3); StorageLive(_3);
StorageLive(_4); StorageLive(_4);
- _4 = (); - _4 = ();
@ -144,12 +143,10 @@
StorageDead(_4); StorageDead(_4);
_2 = &_3; _2 = &_3;
_1 = &(*_2); _1 = &(*_2);
- StorageDead(_2); StorageDead(_2);
- StorageLive(_5); - StorageLive(_5);
- _10 = copy (*_1);
+ nop; + nop;
+ nop; _10 = copy (*_1);
+ _10 = copy (*_2);
_11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
_5 = &raw const (*_11); _5 = &raw const (*_11);
- StorageLive(_6); - StorageLive(_6);

View file

@ -37,8 +37,7 @@
bb0: { bb0: {
StorageLive(_1); StorageLive(_1);
- StorageLive(_2); StorageLive(_2);
+ nop;
StorageLive(_3); StorageLive(_3);
StorageLive(_4); StorageLive(_4);
- _4 = (); - _4 = ();
@ -51,12 +50,10 @@
StorageDead(_4); StorageDead(_4);
_2 = &_3; _2 = &_3;
_1 = &(*_2); _1 = &(*_2);
- StorageDead(_2); StorageDead(_2);
- StorageLive(_5); - StorageLive(_5);
- _10 = copy (*_1);
+ nop; + nop;
+ nop; _10 = copy (*_1);
+ _10 = copy (*_2);
_11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
_5 = &raw const (*_11); _5 = &raw const (*_11);
- StorageLive(_6); - StorageLive(_6);

View file

@ -75,8 +75,7 @@
bb0: { bb0: {
StorageLive(_1); StorageLive(_1);
- StorageLive(_2); StorageLive(_2);
+ nop;
StorageLive(_3); StorageLive(_3);
StorageLive(_4); StorageLive(_4);
- _4 = (); - _4 = ();
@ -144,12 +143,10 @@
StorageDead(_4); StorageDead(_4);
_2 = &_3; _2 = &_3;
_1 = &(*_2); _1 = &(*_2);
- StorageDead(_2); StorageDead(_2);
- StorageLive(_5); - StorageLive(_5);
- _10 = copy (*_1);
+ nop; + nop;
+ nop; _10 = copy (*_1);
+ _10 = copy (*_2);
_11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
_5 = &raw const (*_11); _5 = &raw const (*_11);
- StorageLive(_6); - StorageLive(_6);

View file

@ -37,8 +37,7 @@
bb0: { bb0: {
StorageLive(_1); StorageLive(_1);
- StorageLive(_2); StorageLive(_2);
+ nop;
StorageLive(_3); StorageLive(_3);
StorageLive(_4); StorageLive(_4);
- _4 = (); - _4 = ();
@ -51,12 +50,10 @@
StorageDead(_4); StorageDead(_4);
_2 = &_3; _2 = &_3;
_1 = &(*_2); _1 = &(*_2);
- StorageDead(_2); StorageDead(_2);
- StorageLive(_5); - StorageLive(_5);
- _10 = copy (*_1);
+ nop; + nop;
+ nop; _10 = copy (*_1);
+ _10 = copy (*_2);
_11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
_5 = &raw const (*_11); _5 = &raw const (*_11);
- StorageLive(_6); - StorageLive(_6);

View file

@ -107,18 +107,23 @@
StorageLive(_18); StorageLive(_18);
_18 = &(*_1); _18 = &(*_1);
StorageLive(_19); StorageLive(_19);
StorageLive(_20); - StorageLive(_20);
+ nop;
_20 = copy (*_18); _20 = copy (*_18);
_19 = opaque::<u32>(move _20) -> [return: bb7, unwind unreachable]; - _19 = opaque::<u32>(move _20) -> [return: bb7, unwind unreachable];
+ _19 = opaque::<u32>(copy _20) -> [return: bb7, unwind unreachable];
} }
bb7: { bb7: {
StorageDead(_20); - StorageDead(_20);
+ nop;
StorageDead(_19); StorageDead(_19);
StorageLive(_21); StorageLive(_21);
StorageLive(_22); StorageLive(_22);
_22 = copy (*_18); - _22 = copy (*_18);
_21 = opaque::<u32>(move _22) -> [return: bb8, unwind unreachable]; - _21 = opaque::<u32>(move _22) -> [return: bb8, unwind unreachable];
+ _22 = copy _20;
+ _21 = opaque::<u32>(copy _20) -> [return: bb8, unwind unreachable];
} }
bb8: { bb8: {
@ -152,18 +157,23 @@
StorageDead(_28); StorageDead(_28);
StorageDead(_27); StorageDead(_27);
StorageLive(_29); StorageLive(_29);
StorageLive(_30); - StorageLive(_30);
+ nop;
_30 = copy ((*_3).0: u32); _30 = copy ((*_3).0: u32);
_29 = opaque::<u32>(move _30) -> [return: bb12, unwind unreachable]; - _29 = opaque::<u32>(move _30) -> [return: bb12, unwind unreachable];
+ _29 = opaque::<u32>(copy _30) -> [return: bb12, unwind unreachable];
} }
bb12: { bb12: {
StorageDead(_30); - StorageDead(_30);
+ nop;
StorageDead(_29); StorageDead(_29);
StorageLive(_31); StorageLive(_31);
StorageLive(_32); StorageLive(_32);
_32 = copy ((*_3).0: u32); - _32 = copy ((*_3).0: u32);
_31 = opaque::<u32>(move _32) -> [return: bb13, unwind unreachable]; - _31 = opaque::<u32>(move _32) -> [return: bb13, unwind unreachable];
+ _32 = copy _30;
+ _31 = opaque::<u32>(copy _30) -> [return: bb13, unwind unreachable];
} }
bb13: { bb13: {

View file

@ -107,18 +107,23 @@
StorageLive(_18); StorageLive(_18);
_18 = &(*_1); _18 = &(*_1);
StorageLive(_19); StorageLive(_19);
StorageLive(_20); - StorageLive(_20);
+ nop;
_20 = copy (*_18); _20 = copy (*_18);
_19 = opaque::<u32>(move _20) -> [return: bb7, unwind continue]; - _19 = opaque::<u32>(move _20) -> [return: bb7, unwind continue];
+ _19 = opaque::<u32>(copy _20) -> [return: bb7, unwind continue];
} }
bb7: { bb7: {
StorageDead(_20); - StorageDead(_20);
+ nop;
StorageDead(_19); StorageDead(_19);
StorageLive(_21); StorageLive(_21);
StorageLive(_22); StorageLive(_22);
_22 = copy (*_18); - _22 = copy (*_18);
_21 = opaque::<u32>(move _22) -> [return: bb8, unwind continue]; - _21 = opaque::<u32>(move _22) -> [return: bb8, unwind continue];
+ _22 = copy _20;
+ _21 = opaque::<u32>(copy _20) -> [return: bb8, unwind continue];
} }
bb8: { bb8: {
@ -152,18 +157,23 @@
StorageDead(_28); StorageDead(_28);
StorageDead(_27); StorageDead(_27);
StorageLive(_29); StorageLive(_29);
StorageLive(_30); - StorageLive(_30);
+ nop;
_30 = copy ((*_3).0: u32); _30 = copy ((*_3).0: u32);
_29 = opaque::<u32>(move _30) -> [return: bb12, unwind continue]; - _29 = opaque::<u32>(move _30) -> [return: bb12, unwind continue];
+ _29 = opaque::<u32>(copy _30) -> [return: bb12, unwind continue];
} }
bb12: { bb12: {
StorageDead(_30); - StorageDead(_30);
+ nop;
StorageDead(_29); StorageDead(_29);
StorageLive(_31); StorageLive(_31);
StorageLive(_32); StorageLive(_32);
_32 = copy ((*_3).0: u32); - _32 = copy ((*_3).0: u32);
_31 = opaque::<u32>(move _32) -> [return: bb13, unwind continue]; - _31 = opaque::<u32>(move _32) -> [return: bb13, unwind continue];
+ _32 = copy _30;
+ _31 = opaque::<u32>(copy _30) -> [return: bb13, unwind continue];
} }
bb13: { bb13: {

View file

@ -8,10 +8,10 @@
let mut _3: fn(u8) -> u8; let mut _3: fn(u8) -> u8;
let _5: (); let _5: ();
let mut _6: fn(u8) -> u8; let mut _6: fn(u8) -> u8;
let mut _9: {closure@$DIR/gvn.rs:618:19: 618:21}; let mut _9: {closure@$DIR/gvn.rs:629:19: 629:21};
let _10: (); let _10: ();
let mut _11: fn(); let mut _11: fn();
let mut _13: {closure@$DIR/gvn.rs:618:19: 618:21}; let mut _13: {closure@$DIR/gvn.rs:629:19: 629:21};
let _14: (); let _14: ();
let mut _15: fn(); let mut _15: fn();
scope 1 { scope 1 {
@ -19,7 +19,7 @@
let _4: fn(u8) -> u8; let _4: fn(u8) -> u8;
scope 2 { scope 2 {
debug g => _4; debug g => _4;
let _7: {closure@$DIR/gvn.rs:618:19: 618:21}; let _7: {closure@$DIR/gvn.rs:629:19: 629:21};
scope 3 { scope 3 {
debug closure => _7; debug closure => _7;
let _8: fn(); let _8: fn();
@ -62,16 +62,16 @@
StorageDead(_6); StorageDead(_6);
StorageDead(_5); StorageDead(_5);
- StorageLive(_7); - StorageLive(_7);
- _7 = {closure@$DIR/gvn.rs:618:19: 618:21}; - _7 = {closure@$DIR/gvn.rs:629:19: 629:21};
- StorageLive(_8); - StorageLive(_8);
+ nop; + nop;
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; + _7 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21};
+ nop; + nop;
StorageLive(_9); StorageLive(_9);
- _9 = copy _7; - _9 = copy _7;
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; + _9 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21};
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); + _8 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
StorageDead(_9); StorageDead(_9);
StorageLive(_10); StorageLive(_10);
StorageLive(_11); StorageLive(_11);
@ -88,8 +88,8 @@
StorageLive(_13); StorageLive(_13);
- _13 = copy _7; - _13 = copy _7;
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; + _13 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21};
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); + _12 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
StorageDead(_13); StorageDead(_13);
StorageLive(_14); StorageLive(_14);
StorageLive(_15); StorageLive(_15);

View file

@ -8,10 +8,10 @@
let mut _3: fn(u8) -> u8; let mut _3: fn(u8) -> u8;
let _5: (); let _5: ();
let mut _6: fn(u8) -> u8; let mut _6: fn(u8) -> u8;
let mut _9: {closure@$DIR/gvn.rs:618:19: 618:21}; let mut _9: {closure@$DIR/gvn.rs:629:19: 629:21};
let _10: (); let _10: ();
let mut _11: fn(); let mut _11: fn();
let mut _13: {closure@$DIR/gvn.rs:618:19: 618:21}; let mut _13: {closure@$DIR/gvn.rs:629:19: 629:21};
let _14: (); let _14: ();
let mut _15: fn(); let mut _15: fn();
scope 1 { scope 1 {
@ -19,7 +19,7 @@
let _4: fn(u8) -> u8; let _4: fn(u8) -> u8;
scope 2 { scope 2 {
debug g => _4; debug g => _4;
let _7: {closure@$DIR/gvn.rs:618:19: 618:21}; let _7: {closure@$DIR/gvn.rs:629:19: 629:21};
scope 3 { scope 3 {
debug closure => _7; debug closure => _7;
let _8: fn(); let _8: fn();
@ -62,16 +62,16 @@
StorageDead(_6); StorageDead(_6);
StorageDead(_5); StorageDead(_5);
- StorageLive(_7); - StorageLive(_7);
- _7 = {closure@$DIR/gvn.rs:618:19: 618:21}; - _7 = {closure@$DIR/gvn.rs:629:19: 629:21};
- StorageLive(_8); - StorageLive(_8);
+ nop; + nop;
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; + _7 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21};
+ nop; + nop;
StorageLive(_9); StorageLive(_9);
- _9 = copy _7; - _9 = copy _7;
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; + _9 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21};
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); + _8 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
StorageDead(_9); StorageDead(_9);
StorageLive(_10); StorageLive(_10);
StorageLive(_11); StorageLive(_11);
@ -88,8 +88,8 @@
StorageLive(_13); StorageLive(_13);
- _13 = copy _7; - _13 = copy _7;
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; + _13 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21};
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); + _12 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
StorageDead(_13); StorageDead(_13);
StorageLive(_14); StorageLive(_14);
StorageLive(_15); StorageLive(_15);

View file

@ -100,14 +100,14 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) {
opaque((x * y) - y); opaque((x * y) - y);
opaque((x * y) - y); opaque((x * y) - y);
// We cannot substitute through an immutable reference. // We can substitute through an immutable reference.
// CHECK: [[ref:_.*]] = &_3; // CHECK: [[ref:_.*]] = &_3;
// CHECK: [[deref:_.*]] = copy (*[[ref]]); // CHECK: [[deref:_.*]] = copy (*[[ref]]);
// CHECK: [[addref:_.*]] = Add(move [[deref]], copy _1); // CHECK: [[addref:_.*]] = Add(copy [[deref]], copy _1);
// CHECK: opaque::<u64>(move [[addref]]) // CHECK: opaque::<u64>(copy [[addref]])
// CHECK: [[deref2:_.*]] = copy (*[[ref]]); // CHECK: [[deref2:_.*]] = copy [[deref]];
// CHECK: [[addref2:_.*]] = Add(move [[deref2]], copy _1); // CHECK: [[addref2:_.*]] = copy [[addref]];
// CHECK: opaque::<u64>(move [[addref2]]) // CHECK: opaque::<u64>(copy [[addref]])
let a = &z; let a = &z;
opaque(*a + x); opaque(*a + x);
opaque(*a + x); opaque(*a + x);
@ -140,15 +140,14 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) {
opaque(*d + x); opaque(*d + x);
} }
// We still cannot substitute again, and never with the earlier computations.
// Important: `e` is not `a`! // Important: `e` is not `a`!
// CHECK: [[ref2:_.*]] = &_3; // CHECK: [[ref2:_.*]] = &_3;
// CHECK: [[deref2:_.*]] = copy (*[[ref2]]); // CHECK: [[deref2:_.*]] = copy (*[[ref2]]);
// CHECK: [[addref2:_.*]] = Add(move [[deref2]], copy _1); // CHECK: [[addref2:_.*]] = Add(copy [[deref2]], copy _1);
// CHECK: opaque::<u64>(move [[addref2]]) // CHECK: opaque::<u64>(copy [[addref2]])
// CHECK: [[deref3:_.*]] = copy (*[[ref2]]); // CHECK: [[deref3:_.*]] = copy [[deref2]];
// CHECK: [[addref3:_.*]] = Add(move [[deref3]], copy _1); // CHECK: [[addref3:_.*]] = copy [[addref2]];
// CHECK: opaque::<u64>(move [[addref3]]) // CHECK: opaque::<u64>(copy [[addref2]])
let e = &z; let e = &z;
opaque(*e + x); opaque(*e + x);
opaque(*e + x); opaque(*e + x);
@ -452,20 +451,21 @@ fn references(mut x: impl Sized) {
// CHECK: opaque::<*mut impl Sized>(move [[ref8]]) // CHECK: opaque::<*mut impl Sized>(move [[ref8]])
opaque(&raw mut x); opaque(&raw mut x);
// FIXME: ReferencePropagation transform this pattern.
let r = &mut x; let r = &mut x;
let s = S(r).0; // Obfuscate `r`. Following lines should still reborrow `r`. let s = S(r).0; // Obfuscate `r`. Following lines should still reborrow `r`.
// CHECK: [[ref9:_.*]] = &mut _1; // CHECK: [[ref9:_.*]] = &mut _1;
// CHECK: [[ref10:_.*]] = &(*[[ref9]]); // COM: CHECK: [[ref10:_.*]] = &(*[[ref9]]);
// CHECK: opaque::<&impl Sized>(move [[ref10]]) // COM: CHECK: opaque::<&impl Sized>(move [[ref10]])
opaque(&*s); opaque(&*s);
// CHECK: [[ref11:_.*]] = &mut (*[[ref9]]); // COM: CHECK: [[ref11:_.*]] = &mut (*[[ref9]]);
// CHECK: opaque::<&mut impl Sized>(move [[ref11]]) // COM: CHECK: opaque::<&mut impl Sized>(move [[ref11]])
opaque(&mut *s); opaque(&mut *s);
// CHECK: [[ref12:_.*]] = &raw const (*[[ref9]]); // COM: CHECK: [[ref12:_.*]] = &raw const (*[[ref9]]);
// CHECK: opaque::<*const impl Sized>(move [[ref12]]) // COM: CHECK: opaque::<*const impl Sized>(move [[ref12]])
opaque(&raw const *s); opaque(&raw const *s);
// CHECK: [[ref12:_.*]] = &raw mut (*[[ref9]]); // COM: CHECK: [[ref12:_.*]] = &raw mut (*[[ref9]]);
// CHECK: opaque::<*mut impl Sized>(move [[ref12]]) // COM: CHECK: opaque::<*mut impl Sized>(move [[ref12]])
opaque(&raw mut *s); opaque(&raw mut *s);
} }
@ -473,17 +473,21 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S<u32>) {
// CHECK-LABEL: fn dereferences( // CHECK-LABEL: fn dereferences(
// Do not reuse dereferences of `&mut`. // Do not reuse dereferences of `&mut`.
// CHECK: bb0:
// CHECK: [[st1:_.*]] = copy (*_1); // CHECK: [[st1:_.*]] = copy (*_1);
// CHECK: opaque::<u32>(move [[st1]]) // CHECK: opaque::<u32>(move [[st1]])
// CHECK: bb1:
// CHECK: [[st2:_.*]] = copy (*_1); // CHECK: [[st2:_.*]] = copy (*_1);
// CHECK: opaque::<u32>(move [[st2]]) // CHECK: opaque::<u32>(move [[st2]])
opaque(*t); opaque(*t);
opaque(*t); opaque(*t);
// Do not reuse dereferences of `*const`. // Do not reuse dereferences of `*const`.
// CHECK: bb2:
// CHECK: [[raw:_.*]] = &raw const (*_1); // CHECK: [[raw:_.*]] = &raw const (*_1);
// CHECK: [[st3:_.*]] = copy (*[[raw]]); // CHECK: [[st3:_.*]] = copy (*[[raw]]);
// CHECK: opaque::<u32>(move [[st3]]) // CHECK: opaque::<u32>(move [[st3]])
// CHECK: bb3:
// CHECK: [[st4:_.*]] = copy (*[[raw]]); // CHECK: [[st4:_.*]] = copy (*[[raw]]);
// CHECK: opaque::<u32>(move [[st4]]) // CHECK: opaque::<u32>(move [[st4]])
let z = &raw const *t; let z = &raw const *t;
@ -491,42 +495,49 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S<u32>) {
unsafe { opaque(*z) }; unsafe { opaque(*z) };
// Do not reuse dereferences of `*mut`. // Do not reuse dereferences of `*mut`.
// CHECK: bb4:
// CHECK: [[ptr:_.*]] = &raw mut (*_1); // CHECK: [[ptr:_.*]] = &raw mut (*_1);
// CHECK: [[st5:_.*]] = copy (*[[ptr]]); // CHECK: [[st5:_.*]] = copy (*[[ptr]]);
// CHECK: opaque::<u32>(move [[st5]]) // CHECK: opaque::<u32>(move [[st5]])
// CHECK: bb5:
// CHECK: [[st6:_.*]] = copy (*[[ptr]]); // CHECK: [[st6:_.*]] = copy (*[[ptr]]);
// CHECK: opaque::<u32>(move [[st6]]) // CHECK: opaque::<u32>(move [[st6]])
let z = &raw mut *t; let z = &raw mut *t;
unsafe { opaque(*z) }; unsafe { opaque(*z) };
unsafe { opaque(*z) }; unsafe { opaque(*z) };
// Do not reuse dereferences of `&Freeze`. // CHECK: bb6:
// CHECK: [[ref:_.*]] = &(*_1); // CHECK: [[ref:_.*]] = &(*_1);
// CHECK: [[st7:_.*]] = copy (*[[ref]]); // CHECK: [[st7:_.*]] = copy (*[[ref]]);
// CHECK: opaque::<u32>(move [[st7]]) // CHECK: opaque::<u32>(copy [[st7]])
// CHECK: [[st8:_.*]] = copy (*[[ref]]); // CHECK: bb7:
// CHECK: opaque::<u32>(move [[st8]]) // CHECK: [[st8:_.*]] = copy [[st7]];
// CHECK: opaque::<u32>(copy [[st7]])
let z = &*t; let z = &*t;
opaque(*z); opaque(*z);
opaque(*z); opaque(*z);
// Not in reborrows either. // Not in reborrows either.
// CHECK: bb8:
// CHECK: [[reborrow:_.*]] = &(*[[ref]]); // CHECK: [[reborrow:_.*]] = &(*[[ref]]);
// CHECK: opaque::<&u32>(move [[reborrow]]) // CHECK: opaque::<&u32>(move [[reborrow]])
opaque(&*z); opaque(&*z);
// `*u` is not Freeze, so we cannot reuse. // `*u` is not Freeze, so we cannot reuse.
// CHECK: bb9:
// CHECK: [[st8:_.*]] = copy (*_2); // CHECK: [[st8:_.*]] = copy (*_2);
// CHECK: opaque::<impl Copy>(move [[st8]]) // CHECK: opaque::<impl Copy>(move [[st8]])
// CHECK: bb10:
// CHECK: [[st9:_.*]] = copy (*_2); // CHECK: [[st9:_.*]] = copy (*_2);
// CHECK: opaque::<impl Copy>(move [[st9]]) // CHECK: opaque::<impl Copy>(move [[st9]])
opaque(*u); opaque(*u);
opaque(*u); opaque(*u);
// `*s` is not Copy, but `(*s).0` is, but we still cannot reuse. // CHECK: bb11:
// CHECK: [[st10:_.*]] = copy ((*_3).0: u32); // CHECK: [[st10:_.*]] = copy ((*_3).0: u32);
// CHECK: opaque::<u32>(move [[st10]]) // CHECK: opaque::<u32>(copy [[st10]])
// CHECK: [[st11:_.*]] = copy ((*_3).0: u32); // CHECK: bb12:
// CHECK: opaque::<u32>(move [[st11]]) // CHECK: [[st11:_.*]] = copy [[st10]];
// CHECK: opaque::<u32>(copy [[st10]])
opaque(s.0); opaque(s.0);
opaque(s.0); opaque(s.0);
} }

View file

@ -758,32 +758,39 @@
StorageLive(_126); StorageLive(_126);
_126 = &_3; _126 = &_3;
StorageLive(_127); StorageLive(_127);
StorageLive(_128); - StorageLive(_128);
StorageLive(_129); - StorageLive(_129);
+ nop;
+ nop;
_129 = copy (*_126); _129 = copy (*_126);
StorageLive(_130); StorageLive(_130);
_130 = copy _1; _130 = copy _1;
- _128 = Add(move _129, move _130); - _128 = Add(move _129, move _130);
+ _128 = Add(move _129, copy _1); + _128 = Add(copy _129, copy _1);
StorageDead(_130); StorageDead(_130);
StorageDead(_129); - StorageDead(_129);
_127 = opaque::<u64>(move _128) -> [return: bb35, unwind unreachable]; - _127 = opaque::<u64>(move _128) -> [return: bb35, unwind unreachable];
+ nop;
+ _127 = opaque::<u64>(copy _128) -> [return: bb35, unwind unreachable];
} }
bb35: { bb35: {
StorageDead(_128); - StorageDead(_128);
+ nop;
StorageDead(_127); StorageDead(_127);
StorageLive(_131); StorageLive(_131);
StorageLive(_132); StorageLive(_132);
StorageLive(_133); StorageLive(_133);
_133 = copy (*_126); - _133 = copy (*_126);
+ _133 = copy _129;
StorageLive(_134); StorageLive(_134);
_134 = copy _1; _134 = copy _1;
- _132 = Add(move _133, move _134); - _132 = Add(move _133, move _134);
+ _132 = Add(move _133, copy _1); + _132 = copy _128;
StorageDead(_134); StorageDead(_134);
StorageDead(_133); StorageDead(_133);
_131 = opaque::<u64>(move _132) -> [return: bb36, unwind unreachable]; - _131 = opaque::<u64>(move _132) -> [return: bb36, unwind unreachable];
+ _131 = opaque::<u64>(copy _128) -> [return: bb36, unwind unreachable];
} }
bb36: { bb36: {
@ -899,32 +906,39 @@
StorageLive(_163); StorageLive(_163);
_163 = &_3; _163 = &_3;
StorageLive(_164); StorageLive(_164);
StorageLive(_165); - StorageLive(_165);
StorageLive(_166); - StorageLive(_166);
+ nop;
+ nop;
_166 = copy (*_163); _166 = copy (*_163);
StorageLive(_167); StorageLive(_167);
_167 = copy _1; _167 = copy _1;
- _165 = Add(move _166, move _167); - _165 = Add(move _166, move _167);
+ _165 = Add(move _166, copy _1); + _165 = Add(copy _166, copy _1);
StorageDead(_167); StorageDead(_167);
StorageDead(_166); - StorageDead(_166);
_164 = opaque::<u64>(move _165) -> [return: bb43, unwind unreachable]; - _164 = opaque::<u64>(move _165) -> [return: bb43, unwind unreachable];
+ nop;
+ _164 = opaque::<u64>(copy _165) -> [return: bb43, unwind unreachable];
} }
bb43: { bb43: {
StorageDead(_165); - StorageDead(_165);
+ nop;
StorageDead(_164); StorageDead(_164);
StorageLive(_168); StorageLive(_168);
StorageLive(_169); StorageLive(_169);
StorageLive(_170); StorageLive(_170);
_170 = copy (*_163); - _170 = copy (*_163);
+ _170 = copy _166;
StorageLive(_171); StorageLive(_171);
_171 = copy _1; _171 = copy _1;
- _169 = Add(move _170, move _171); - _169 = Add(move _170, move _171);
+ _169 = Add(move _170, copy _1); + _169 = copy _165;
StorageDead(_171); StorageDead(_171);
StorageDead(_170); StorageDead(_170);
_168 = opaque::<u64>(move _169) -> [return: bb44, unwind unreachable]; - _168 = opaque::<u64>(move _169) -> [return: bb44, unwind unreachable];
+ _168 = opaque::<u64>(copy _165) -> [return: bb44, unwind unreachable];
} }
bb44: { bb44: {

View file

@ -758,32 +758,39 @@
StorageLive(_126); StorageLive(_126);
_126 = &_3; _126 = &_3;
StorageLive(_127); StorageLive(_127);
StorageLive(_128); - StorageLive(_128);
StorageLive(_129); - StorageLive(_129);
+ nop;
+ nop;
_129 = copy (*_126); _129 = copy (*_126);
StorageLive(_130); StorageLive(_130);
_130 = copy _1; _130 = copy _1;
- _128 = Add(move _129, move _130); - _128 = Add(move _129, move _130);
+ _128 = Add(move _129, copy _1); + _128 = Add(copy _129, copy _1);
StorageDead(_130); StorageDead(_130);
StorageDead(_129); - StorageDead(_129);
_127 = opaque::<u64>(move _128) -> [return: bb35, unwind continue]; - _127 = opaque::<u64>(move _128) -> [return: bb35, unwind continue];
+ nop;
+ _127 = opaque::<u64>(copy _128) -> [return: bb35, unwind continue];
} }
bb35: { bb35: {
StorageDead(_128); - StorageDead(_128);
+ nop;
StorageDead(_127); StorageDead(_127);
StorageLive(_131); StorageLive(_131);
StorageLive(_132); StorageLive(_132);
StorageLive(_133); StorageLive(_133);
_133 = copy (*_126); - _133 = copy (*_126);
+ _133 = copy _129;
StorageLive(_134); StorageLive(_134);
_134 = copy _1; _134 = copy _1;
- _132 = Add(move _133, move _134); - _132 = Add(move _133, move _134);
+ _132 = Add(move _133, copy _1); + _132 = copy _128;
StorageDead(_134); StorageDead(_134);
StorageDead(_133); StorageDead(_133);
_131 = opaque::<u64>(move _132) -> [return: bb36, unwind continue]; - _131 = opaque::<u64>(move _132) -> [return: bb36, unwind continue];
+ _131 = opaque::<u64>(copy _128) -> [return: bb36, unwind continue];
} }
bb36: { bb36: {
@ -899,32 +906,39 @@
StorageLive(_163); StorageLive(_163);
_163 = &_3; _163 = &_3;
StorageLive(_164); StorageLive(_164);
StorageLive(_165); - StorageLive(_165);
StorageLive(_166); - StorageLive(_166);
+ nop;
+ nop;
_166 = copy (*_163); _166 = copy (*_163);
StorageLive(_167); StorageLive(_167);
_167 = copy _1; _167 = copy _1;
- _165 = Add(move _166, move _167); - _165 = Add(move _166, move _167);
+ _165 = Add(move _166, copy _1); + _165 = Add(copy _166, copy _1);
StorageDead(_167); StorageDead(_167);
StorageDead(_166); - StorageDead(_166);
_164 = opaque::<u64>(move _165) -> [return: bb43, unwind continue]; - _164 = opaque::<u64>(move _165) -> [return: bb43, unwind continue];
+ nop;
+ _164 = opaque::<u64>(copy _165) -> [return: bb43, unwind continue];
} }
bb43: { bb43: {
StorageDead(_165); - StorageDead(_165);
+ nop;
StorageDead(_164); StorageDead(_164);
StorageLive(_168); StorageLive(_168);
StorageLive(_169); StorageLive(_169);
StorageLive(_170); StorageLive(_170);
_170 = copy (*_163); - _170 = copy (*_163);
+ _170 = copy _166;
StorageLive(_171); StorageLive(_171);
_171 = copy _1; _171 = copy _1;
- _169 = Add(move _170, move _171); - _169 = Add(move _170, move _171);
+ _169 = Add(move _170, copy _1); + _169 = copy _165;
StorageDead(_171); StorageDead(_171);
StorageDead(_170); StorageDead(_170);
_168 = opaque::<u64>(move _169) -> [return: bb44, unwind continue]; - _168 = opaque::<u64>(move _169) -> [return: bb44, unwind continue];
+ _168 = opaque::<u64>(copy _165) -> [return: bb44, unwind continue];
} }
bb44: { bb44: {

View file

@ -47,7 +47,7 @@
StorageLive(_7); StorageLive(_7);
_7 = copy _4; _7 = copy _4;
- _0 = AllCopy { a: move _5, b: move _6, c: move _7 }; - _0 = AllCopy { a: move _5, b: move _6, c: move _7 };
+ _0 = copy (*_8); + _0 = AllCopy { a: copy _2, b: copy _3, c: copy _4 };
StorageDead(_7); StorageDead(_7);
StorageDead(_6); StorageDead(_6);
StorageDead(_5); StorageDead(_5);

View file

@ -0,0 +1,61 @@
- // MIR for `all_copy_mut` before GVN
+ // MIR for `all_copy_mut` after GVN
fn all_copy_mut(_1: &mut AllCopy) -> AllCopy {
debug mut_v => _1;
let mut _0: AllCopy;
let _2: &AllCopy;
let mut _6: i32;
let mut _7: u64;
let mut _8: [i8; 3];
scope 1 {
debug v => _2;
let _3: i32;
scope 2 {
debug a => _3;
let _4: u64;
scope 3 {
debug b => _4;
let _5: [i8; 3];
scope 4 {
debug c => _5;
}
}
}
}
bb0: {
StorageLive(_2);
_2 = &(*_1);
- StorageLive(_3);
+ nop;
_3 = copy ((*_2).0: i32);
- StorageLive(_4);
+ nop;
_4 = copy ((*_2).1: u64);
- StorageLive(_5);
+ nop;
_5 = copy ((*_2).2: [i8; 3]);
((*_1).0: i32) = const 0_i32;
StorageLive(_6);
_6 = copy _3;
StorageLive(_7);
_7 = copy _4;
StorageLive(_8);
_8 = copy _5;
- _0 = AllCopy { a: move _6, b: move _7, c: move _8 };
+ _0 = AllCopy { a: copy _3, b: copy _4, c: copy _5 };
StorageDead(_8);
StorageDead(_7);
StorageDead(_6);
- StorageDead(_5);
- StorageDead(_4);
- StorageDead(_3);
+ nop;
+ nop;
+ nop;
StorageDead(_2);
return;
}
}

View file

@ -21,9 +21,8 @@
bb0: { bb0: {
StorageLive(_1); StorageLive(_1);
- _1 = Single(const 0_u8); - _1 = Single(const 0_u8);
- StorageLive(_2);
+ _1 = const Single(0_u8); + _1 = const Single(0_u8);
+ nop; StorageLive(_2);
_2 = &_1; _2 = &_1;
- StorageLive(_3); - StorageLive(_3);
+ nop; + nop;
@ -37,12 +36,11 @@
StorageLive(_5); StorageLive(_5);
_5 = copy _3; _5 = copy _3;
- _0 = Single(move _5); - _0 = Single(move _5);
+ _0 = copy (*_2); + _0 = Single(copy _3);
StorageDead(_5); StorageDead(_5);
- StorageDead(_3); - StorageDead(_3);
- StorageDead(_2);
+ nop;
+ nop; + nop;
StorageDead(_2);
StorageDead(_1); StorageDead(_1);
return; return;
} }

View file

@ -7,7 +7,7 @@
let mut _3: &Single; let mut _3: &Single;
let _4: &Single; let _4: &Single;
let mut _7: Single; let mut _7: Single;
let mut _9: u8; let mut _8: u8;
scope 1 { scope 1 {
debug a => _1; debug a => _1;
let _2: SingleRef<'_>; let _2: SingleRef<'_>;
@ -19,10 +19,6 @@
let _6: u8; let _6: u8;
scope 4 { scope 4 {
debug c => _6; debug c => _6;
let _8: Single;
scope 5 {
debug d => _8;
}
} }
} }
} }
@ -34,24 +30,22 @@
+ _1 = const Single(0_u8); + _1 = const Single(0_u8);
StorageLive(_2); StorageLive(_2);
- StorageLive(_3); - StorageLive(_3);
- StorageLive(_4);
+ nop;
+ nop; + nop;
StorageLive(_4);
_4 = &_1; _4 = &_1;
_3 = &(*_4); _3 = &(*_4);
- _2 = SingleRef::<'_>(move _3); - _2 = SingleRef::<'_>(move _3);
- StorageDead(_3); - StorageDead(_3);
- StorageDead(_4);
+ _2 = SingleRef::<'_>(copy _3); + _2 = SingleRef::<'_>(copy _3);
+ nop; + nop;
+ nop; StorageDead(_4);
StorageLive(_5); StorageLive(_5);
- _5 = copy (_2.0: &Single); - _5 = copy (_2.0: &Single);
- StorageLive(_6); - StorageLive(_6);
- _6 = copy ((*_5).0: u8); - _6 = copy ((*_5).0: u8);
+ _5 = copy _3; + _5 = copy _3;
+ nop; + nop;
+ _6 = copy ((*_4).0: u8); + _6 = copy ((*_3).0: u8);
StorageLive(_7); StorageLive(_7);
- _7 = Single(const 1_u8); - _7 = Single(const 1_u8);
- _1 = move _7; - _1 = move _7;
@ -59,12 +53,9 @@
+ _1 = const Single(1_u8); + _1 = const Single(1_u8);
StorageDead(_7); StorageDead(_7);
StorageLive(_8); StorageLive(_8);
StorageLive(_9); _8 = copy _6;
_9 = copy _6; - _0 = Single(move _8);
- _8 = Single(move _9); + _0 = Single(copy _6);
+ _8 = copy (*_4);
StorageDead(_9);
_0 = move _8;
StorageDead(_8); StorageDead(_8);
- StorageDead(_6); - StorageDead(_6);
+ nop; + nop;

View file

@ -24,13 +24,25 @@ fn all_copy(v: &AllCopy) -> AllCopy {
AllCopy { a, b, c } AllCopy { a, b, c }
} }
// EMIT_MIR gvn_copy_aggregate.all_copy_mut.GVN.diff
fn all_copy_mut(mut_v: &mut AllCopy) -> AllCopy {
// CHECK-LABEL: fn all_copy_mut(
// CHECK: = AllCopy { {{.*}} };
// CHECK-NOT: _0 = copy ({{.*}});
let v = &*mut_v;
let a = v.a;
let b = v.b;
let c = v.c;
mut_v.a = 0;
AllCopy { a, b, c }
}
// Nested references may be modified.
// EMIT_MIR gvn_copy_aggregate.all_copy_2.GVN.diff // EMIT_MIR gvn_copy_aggregate.all_copy_2.GVN.diff
fn all_copy_2(v: &&AllCopy) -> AllCopy { fn all_copy_2(v: &&AllCopy) -> AllCopy {
// CHECK-LABEL: fn all_copy_2( // CHECK-LABEL: fn all_copy_2(
// CHECK: bb0: { // CHECK: bb0: {
// CHECK-NOT: = AllCopy { {{.*}} }; // CHECK: _0 = AllCopy { {{.*}} };
// CHECK: [[V1:_.*]] = copy (*_1);
// CHECK: _0 = copy (*[[V1]]);
let a = v.a; let a = v.a;
let b = v.b; let b = v.b;
let c = v.c; let c = v.c;
@ -264,6 +276,8 @@ pub struct Single(u8);
// EMIT_MIR gvn_copy_aggregate.deref_nonssa.GVN.diff // EMIT_MIR gvn_copy_aggregate.deref_nonssa.GVN.diff
fn deref_nonssa() -> Single { fn deref_nonssa() -> Single {
// CHECK-LABEL: fn deref_nonssa(
// CHECK: _0 = Single(copy {{.*}});
let mut a = Single(0); let mut a = Single(0);
let b = &a; let b = &a;
let c = (*b).0; let c = (*b).0;
@ -276,11 +290,12 @@ pub struct SingleRef<'a>(&'a Single);
// EMIT_MIR gvn_copy_aggregate.deref_nonssa_2.GVN.diff // EMIT_MIR gvn_copy_aggregate.deref_nonssa_2.GVN.diff
pub fn deref_nonssa_2() -> Single { pub fn deref_nonssa_2() -> Single {
// CHECK-LABEL: fn deref_nonssa_2(
// CHECK: _0 = Single(copy {{.*}});
let mut a = Single(0); let mut a = Single(0);
let r = SingleRef(&a); let r = SingleRef(&a);
let b = r.0; let b = r.0;
let c = (*b).0; let c = (*b).0;
a = Single(1); a = Single(1);
let d = Single(c); Single(c)
d
} }

View file

@ -17,7 +17,7 @@
let mut _15: !; let mut _15: !;
let mut _16: Value; let mut _16: Value;
scope 1 { scope 1 {
debug val_alias => _2; debug val_alias => _3;
let mut _5: bool; let mut _5: bool;
scope 2 { scope 2 {
debug stop => _5; debug stop => _5;
@ -33,23 +33,16 @@
} }
bb0: { bb0: {
StorageLive(_2);
- StorageLive(_3);
+ nop;
StorageLive(_4); StorageLive(_4);
_4 = &(*_1); _4 = &(*_1);
_3 = get::<Value>(move _4) -> [return: bb1, unwind unreachable]; _3 = get::<Value>(copy _4) -> [return: bb1, unwind unreachable];
} }
bb1: { bb1: {
_2 = &(*_3);
StorageDead(_4); StorageDead(_4);
- StorageDead(_3);
+ nop;
StorageLive(_5); StorageLive(_5);
_5 = const false; _5 = const false;
- _8 = discriminant((*_2)); _8 = discriminant((*_3));
+ _8 = discriminant((*_3));
switchInt(move _8) -> [0: bb3, otherwise: bb2]; switchInt(move _8) -> [0: bb3, otherwise: bb2];
} }
@ -59,10 +52,8 @@
bb3: { bb3: {
- StorageLive(_7); - StorageLive(_7);
- _7 = copy (((*_2) as V0).0: i32);
+ nop; + nop;
+ _7 = copy (((*_3) as V0).0: i32); _7 = copy (((*_3) as V0).0: i32);
StorageLive(_9);
goto -> bb4; goto -> bb4;
} }
@ -73,7 +64,6 @@
- _11 = Value::V0(move _12); - _11 = Value::V0(move _12);
+ _11 = Value::V0(copy _7); + _11 = Value::V0(copy _7);
StorageDead(_12); StorageDead(_12);
StorageLive(_13);
StorageLive(_14); StorageLive(_14);
_14 = copy _5; _14 = copy _5;
switchInt(move _14) -> [0: bb6, otherwise: bb5]; switchInt(move _14) -> [0: bb6, otherwise: bb5];
@ -82,20 +72,15 @@
bb5: { bb5: {
_0 = move _11; _0 = move _11;
StorageDead(_14); StorageDead(_14);
StorageDead(_13);
StorageDead(_11); StorageDead(_11);
StorageDead(_9);
- StorageDead(_7); - StorageDead(_7);
+ nop; + nop;
StorageDead(_5); StorageDead(_5);
StorageDead(_2);
return; return;
} }
bb6: { bb6: {
_13 = const ();
StorageDead(_14); StorageDead(_14);
StorageDead(_13);
_5 = const true; _5 = const true;
StorageLive(_16); StorageLive(_16);
- _16 = Value::V1; - _16 = Value::V1;
@ -103,7 +88,6 @@
+ _16 = const Value::V1; + _16 = const Value::V1;
+ (*_1) = const Value::V1; + (*_1) = const Value::V1;
StorageDead(_16); StorageDead(_16);
_10 = const ();
StorageDead(_11); StorageDead(_11);
goto -> bb4; goto -> bb4;
} }

View file

@ -1,5 +1,5 @@
//@ test-mir-pass: GVN //@ test-mir-pass: GVN
//@ compile-flags: -Zdump-mir-exclude-alloc-bytes //@ compile-flags: -Zdump-mir-exclude-alloc-bytes -Zmir-enable-passes=+ReferencePropagation
#![crate_type = "lib"] #![crate_type = "lib"]
#![feature(core_intrinsics, rustc_attrs)] #![feature(core_intrinsics, rustc_attrs)]

View file

@ -11,8 +11,7 @@
((_1 as variant#1).0: u32) = const 0_u32; ((_1 as variant#1).0: u32) = const 0_u32;
_3 = &_1; _3 = &_1;
_2 = copy (((*_3) as variant#1).0: u32); _2 = copy (((*_3) as variant#1).0: u32);
- _1 = Adt::Some(copy _2); _1 = Adt::Some(copy _2);
+ _1 = copy (*_3);
return; return;
} }
} }

View file

@ -3,12 +3,12 @@
fn overlapping(_1: Adt) -> () { fn overlapping(_1: Adt) -> () {
let mut _0: (); let mut _0: ();
let mut _2: *mut Adt; let mut _2: &mut Adt;
let mut _3: u32; let mut _3: u32;
let mut _4: &Adt; let mut _4: &Adt;
bb0: { bb0: {
_2 = &raw mut _1; _2 = &mut _1;
_4 = &(*_2); _4 = &(*_2);
_3 = copy (((*_4) as variant#1).0: u32); _3 = copy (((*_4) as variant#1).0: u32);
(*_2) = Adt::Some(copy _3); (*_2) = Adt::Some(copy _3);

View file

@ -7,19 +7,19 @@ use std::intrinsics::mir::*;
// EMIT_MIR gvn_overlapping.overlapping.GVN.diff // EMIT_MIR gvn_overlapping.overlapping.GVN.diff
/// Check that we do not create overlapping assignments. /// Check that we do not create overlapping assignments.
#[custom_mir(dialect = "runtime")] #[custom_mir(dialect = "runtime")]
fn overlapping(_17: Adt) { fn overlapping(_1: Adt) {
// CHECK-LABEL: fn overlapping( // CHECK-LABEL: fn overlapping(
// CHECK: let mut [[PTR:.*]]: *mut Adt; // CHECK: let mut [[PTR:.*]]: &mut Adt;
// CHECK: (*[[PTR]]) = Adt::Some(copy {{.*}}); // CHECK: (*[[PTR]]) = Adt::Some(copy {{.*}});
mir! { mir! {
let _33: *mut Adt; let _2: &mut Adt;
let _48: u32; let _3: u32;
let _73: &Adt; let _4: &Adt;
{ {
_33 = core::ptr::addr_of_mut!(_17); _2 = &mut _1;
_73 = &(*_33); _4 = &(*_2);
_48 = Field(Variant((*_73), 1), 0); _3 = Field(Variant((*_4), 1), 0);
(*_33) = Adt::Some(_48); (*_2) = Adt::Some(_3);
Return() Return()
} }
} }
@ -30,18 +30,19 @@ fn overlapping(_17: Adt) {
#[custom_mir(dialect = "runtime")] #[custom_mir(dialect = "runtime")]
fn stable_projection(_1: (Adt,)) { fn stable_projection(_1: (Adt,)) {
// CHECK-LABEL: fn stable_projection( // CHECK-LABEL: fn stable_projection(
// CHECK: let mut _2: *mut Adt; // CHECK: let mut _2: &Adt;
// CHECK: let mut _4: &Adt; // CHECK: let mut _4: &Adt;
// CHECK: (_1.0: Adt) = copy (*_4); // CHECK: (_5.0: Adt) = copy (_1.0: Adt);
mir! { mir! {
let _2: *mut Adt; let _2: &Adt;
let _3: u32; let _3: u32;
let _4: &Adt; let _4: &Adt;
let _5: (Adt,);
{ {
_2 = core::ptr::addr_of_mut!(_1.0); _2 = &_1.0;
_4 = &(*_2); _4 = &(*_2);
_3 = Field(Variant((*_4), 1), 0); _3 = Field(Variant((*_4), 1), 0);
_1.0 = Adt::Some(_3); _5.0 = Adt::Some(_3);
Return() Return()
} }
} }

View file

@ -3,16 +3,18 @@
fn stable_projection(_1: (Adt,)) -> () { fn stable_projection(_1: (Adt,)) -> () {
let mut _0: (); let mut _0: ();
let mut _2: *mut Adt; let mut _2: &Adt;
let mut _3: u32; let mut _3: u32;
let mut _4: &Adt; let mut _4: &Adt;
let mut _5: (Adt,);
bb0: { bb0: {
_2 = &raw mut (_1.0: Adt); _2 = &(_1.0: Adt);
_4 = &(*_2); _4 = &(*_2);
_3 = copy (((*_4) as variant#1).0: u32); - _3 = copy (((*_4) as variant#1).0: u32);
- (_1.0: Adt) = Adt::Some(copy _3); - (_5.0: Adt) = Adt::Some(copy _3);
+ (_1.0: Adt) = copy (*_4); + _3 = copy (((_1.0: Adt) as variant#1).0: u32);
+ (_5.0: Adt) = copy (_1.0: Adt);
return; return;
} }
} }

View file

@ -2,9 +2,6 @@
fn src(x: &&u8) -> bool { fn src(x: &&u8) -> bool {
// CHECK-LABEL: fn src( // CHECK-LABEL: fn src(
// CHECK-NOT: _0 = const true;
// CHECK: _0 = Eq({{.*}}, {{.*}});
// CHECK-NOT: _0 = const true;
let y = **x; let y = **x;
unsafe { unknown() }; unsafe { unknown() };
**x == y **x == y

View file

@ -24,12 +24,14 @@
bb1: { bb1: {
StorageLive(_4); StorageLive(_4);
_7 = copy (*_1); - _7 = copy (*_1);
_4 = copy (*_7); - _4 = copy (*_7);
+ _7 = copy _6;
+ _4 = copy _2;
StorageLive(_5); StorageLive(_5);
_5 = copy _2; _5 = copy _2;
- _0 = Eq(move _4, move _5); - _0 = Eq(move _4, move _5);
+ _0 = Eq(move _4, copy _2); + _0 = const true;
StorageDead(_5); StorageDead(_5);
StorageDead(_4); StorageDead(_4);
- StorageDead(_2); - StorageDead(_2);

View file

@ -24,12 +24,14 @@
bb1: { bb1: {
StorageLive(_4); StorageLive(_4);
_7 = copy (*_1); - _7 = copy (*_1);
_4 = copy (*_7); - _4 = copy (*_7);
+ _7 = copy _6;
+ _4 = copy _2;
StorageLive(_5); StorageLive(_5);
_5 = copy _2; _5 = copy _2;
- _0 = Eq(move _4, move _5); - _0 = Eq(move _4, move _5);
+ _0 = Eq(move _4, copy _2); + _0 = const true;
StorageDead(_5); StorageDead(_5);
StorageDead(_4); StorageDead(_4);
- StorageDead(_2); - StorageDead(_2);

View file

@ -6,8 +6,6 @@ fn src(_1: &&u8) -> bool {
let mut _2: &u8; let mut _2: &u8;
let _3: u8; let _3: u8;
let _4: (); let _4: ();
let mut _5: &u8;
let mut _6: u8;
scope 1 { scope 1 {
debug y => _3; debug y => _3;
} }
@ -19,11 +17,7 @@ fn src(_1: &&u8) -> bool {
} }
bb1: { bb1: {
StorageLive(_6); _0 = const true;
_5 = copy (*_1);
_6 = copy (*_5);
_0 = Eq(move _6, copy _3);
StorageDead(_6);
return; return;
} }
} }

View file

@ -6,8 +6,6 @@ fn src(_1: &&u8) -> bool {
let mut _2: &u8; let mut _2: &u8;
let _3: u8; let _3: u8;
let _4: (); let _4: ();
let mut _5: &u8;
let mut _6: u8;
scope 1 { scope 1 {
debug y => _3; debug y => _3;
} }
@ -19,11 +17,7 @@ fn src(_1: &&u8) -> bool {
} }
bb1: { bb1: {
StorageLive(_6); _0 = const true;
_5 = copy (*_1);
_6 = copy (*_5);
_0 = Eq(move _6, copy _3);
StorageDead(_6);
return; return;
} }
} }