Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions compiler/rustc_mir_transform/src/gvn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,12 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
// The base is a pointer's deref, so we introduce the implicit deref.
AddressBase::Deref(reborrow) => {
let place_ty = PlaceTy::from_ty(self.ty(reborrow));
self.project(place_ty, reborrow, ProjectionElem::Deref)?
self.project(place_ty, reborrow, ProjectionElem::Deref).unwrap_or_else(|| {
// Insert a deref instead if `reborrow` cannot be dereferenced.
let projection_ty =
place_ty.projection_ty::<VnIndex>(self.tcx, ProjectionElem::Deref);
return (projection_ty, self.insert_deref(projection_ty.ty, reborrow));
})
}
};
for &proj in projection {
Expand All @@ -817,9 +822,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
if let Some(Mutability::Not) = place_ty.ty.ref_mutability()
&& projection_ty.ty.is_freeze(self.tcx, self.typing_env())
{
if let Value::Address { base, projection, .. } = self.get(value)
&& let Some(value) = self.dereference_address(base, projection)
{
if let Value::Address { base, projection, .. } = self.get(value) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a test for projection, but projection should also be able to invalidate values.

// Bail out if the address cannot be dereferenced.
let value = self.dereference_address(base, projection)?;
return Some((projection_ty, value));
}

Expand Down
6 changes: 4 additions & 2 deletions tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@
_18 = &(*_1);
StorageLive(_19);
StorageLive(_20);
_20 = copy (*_18);
- _20 = copy (*_18);
+ _20 = copy (*_1);
_19 = opaque::<u32>(move _20) -> [return: bb7, unwind unreachable];
}

Expand All @@ -117,7 +118,8 @@
StorageDead(_19);
StorageLive(_21);
StorageLive(_22);
_22 = copy (*_18);
- _22 = copy (*_18);
+ _22 = copy (*_1);
_21 = opaque::<u32>(move _22) -> [return: bb8, unwind unreachable];
}

Expand Down
6 changes: 4 additions & 2 deletions tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@
_18 = &(*_1);
StorageLive(_19);
StorageLive(_20);
_20 = copy (*_18);
- _20 = copy (*_18);
+ _20 = copy (*_1);
_19 = opaque::<u32>(move _20) -> [return: bb7, unwind continue];
}

Expand All @@ -117,7 +118,8 @@
StorageDead(_19);
StorageLive(_21);
StorageLive(_22);
_22 = copy (*_18);
- _22 = copy (*_18);
+ _22 = copy (*_1);
_21 = opaque::<u32>(move _22) -> [return: bb8, unwind continue];
}

Expand Down
18 changes: 9 additions & 9 deletions tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@
let mut _3: fn(u8) -> u8;
let _5: ();
let mut _6: fn(u8) -> u8;
let mut _9: {closure@$DIR/gvn.rs:617:19: 617:21};
let mut _9: {closure@$DIR/gvn.rs:616:19: 616:21};
let _10: ();
let mut _11: fn();
let mut _13: {closure@$DIR/gvn.rs:617:19: 617:21};
let mut _13: {closure@$DIR/gvn.rs:616:19: 616:21};
let _14: ();
let mut _15: fn();
scope 1 {
debug f => _1;
let _4: fn(u8) -> u8;
scope 2 {
debug g => _4;
let _7: {closure@$DIR/gvn.rs:617:19: 617:21};
let _7: {closure@$DIR/gvn.rs:616:19: 616:21};
scope 3 {
debug closure => _7;
let _8: fn();
Expand Down Expand Up @@ -62,16 +62,16 @@
StorageDead(_6);
StorageDead(_5);
- StorageLive(_7);
- _7 = {closure@$DIR/gvn.rs:617:19: 617:21};
- _7 = {closure@$DIR/gvn.rs:616:19: 616:21};
- StorageLive(_8);
+ nop;
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21};
+ nop;
StorageLive(_9);
- _9 = copy _7;
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21};
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
StorageDead(_9);
StorageLive(_10);
StorageLive(_11);
Expand All @@ -88,8 +88,8 @@
StorageLive(_13);
- _13 = copy _7;
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21};
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
StorageDead(_13);
StorageLive(_14);
StorageLive(_15);
Expand Down
18 changes: 9 additions & 9 deletions tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@
let mut _3: fn(u8) -> u8;
let _5: ();
let mut _6: fn(u8) -> u8;
let mut _9: {closure@$DIR/gvn.rs:617:19: 617:21};
let mut _9: {closure@$DIR/gvn.rs:616:19: 616:21};
let _10: ();
let mut _11: fn();
let mut _13: {closure@$DIR/gvn.rs:617:19: 617:21};
let mut _13: {closure@$DIR/gvn.rs:616:19: 616:21};
let _14: ();
let mut _15: fn();
scope 1 {
debug f => _1;
let _4: fn(u8) -> u8;
scope 2 {
debug g => _4;
let _7: {closure@$DIR/gvn.rs:617:19: 617:21};
let _7: {closure@$DIR/gvn.rs:616:19: 616:21};
scope 3 {
debug closure => _7;
let _8: fn();
Expand Down Expand Up @@ -62,16 +62,16 @@
StorageDead(_6);
StorageDead(_5);
- StorageLive(_7);
- _7 = {closure@$DIR/gvn.rs:617:19: 617:21};
- _7 = {closure@$DIR/gvn.rs:616:19: 616:21};
- StorageLive(_8);
+ nop;
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21};
+ nop;
StorageLive(_9);
- _9 = copy _7;
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21};
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
StorageDead(_9);
StorageLive(_10);
StorageLive(_11);
Expand All @@ -88,8 +88,8 @@
StorageLive(_13);
- _13 = copy _7;
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21};
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21};
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:616:19: 616:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
StorageDead(_13);
StorageLive(_14);
StorageLive(_15);
Expand Down
5 changes: 2 additions & 3 deletions tests/mir-opt/gvn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,11 +499,10 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S<u32>) {
unsafe { opaque(*z) };
unsafe { opaque(*z) };

// Do not reuse dereferences of `&Freeze`.
// CHECK: [[ref:_.*]] = &(*_1);
// CHECK: [[st7:_.*]] = copy (*[[ref]]);
// CHECK: [[st7:_.*]] = copy (*_1);
// CHECK: opaque::<u32>(move [[st7]])
// CHECK: [[st8:_.*]] = copy (*[[ref]]);
// CHECK: [[st8:_.*]] = copy (*_1);
// CHECK: opaque::<u32>(move [[st8]])
let z = &*t;
opaque(*z);
Expand Down
48 changes: 48 additions & 0 deletions tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
- // MIR for `deref_nonssa` before GVN
+ // MIR for `deref_nonssa` after GVN

fn deref_nonssa() -> Single {
let mut _0: Single;
let mut _1: Single;
let mut _4: Single;
let mut _5: u8;
scope 1 {
debug a => _1;
let _2: &Single;
scope 2 {
debug b => _2;
let _3: u8;
scope 3 {
debug c => _3;
}
}
}

bb0: {
StorageLive(_1);
- _1 = Single(const 0_u8);
+ _1 = const Single(0_u8);
StorageLive(_2);
_2 = &_1;
- StorageLive(_3);
+ nop;
_3 = copy ((*_2).0: u8);
StorageLive(_4);
- _4 = Single(const 1_u8);
- _1 = move _4;
+ _4 = const Single(1_u8);
+ _1 = const Single(1_u8);
StorageDead(_4);
StorageLive(_5);
_5 = copy _3;
- _0 = Single(move _5);
+ _0 = Single(copy _3);
StorageDead(_5);
- StorageDead(_3);
+ nop;
StorageDead(_2);
StorageDead(_1);
return;
}
}

16 changes: 16 additions & 0 deletions tests/mir-opt/gvn_copy_aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,19 @@ fn remove_storage_dead_from_index(f: fn() -> usize, v: [SameType; 5]) -> SameTyp
}
}
}

pub struct Single(u8);

// EMIT_MIR gvn_copy_aggregate.deref_nonssa.GVN.diff
fn deref_nonssa() -> Single {
// CHECK-LABEL: fn deref_nonssa(
// CHECK: debug c => [[C:_.*]];
// CHECK-NOT: _0 = copy (*_{{.*}});
// CHECK: _0 = Single(copy [[C]]);
let mut a = Single(0);
let b = &a;
let c = (*b).0;
a = Single(1);
// GVN shouldn't replace `Single(c)` with `*b`.
Single(c)
}
18 changes: 18 additions & 0 deletions tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
- // MIR for `copy_overlapping` before GVN
+ // MIR for `copy_overlapping` after GVN

fn copy_overlapping() -> () {
let mut _0: ();
let mut _1: Adt;
let mut _2: u32;
let mut _3: &Adt;

bb0: {
((_1 as variant#1).0: u32) = const 0_u32;
_3 = &_1;
_2 = copy (((*_3) as variant#1).0: u32);
_1 = Adt::Some(copy _2);
return;
}
}

3 changes: 2 additions & 1 deletion tests/mir-opt/gvn_overlapping.overlapping.GVN.diff
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
bb0: {
_2 = &raw mut _1;
_4 = &(*_2);
_3 = copy (((*_4) as variant#1).0: u32);
- _3 = copy (((*_4) as variant#1).0: u32);
+ _3 = copy (((*_2) as variant#1).0: u32);
(*_2) = Adt::Some(copy _3);
return;
}
Expand Down
22 changes: 21 additions & 1 deletion tests/mir-opt/gvn_overlapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fn stable_projection(_1: (Adt,)) {
// CHECK-LABEL: fn stable_projection(
// CHECK: let mut _2: *mut Adt;
// CHECK: let mut _4: &Adt;
// CHECK: (_1.0: Adt) = copy (*_4);
// CHECK: (_1.0: Adt) = copy (*_2);
mir! {
let _2: *mut Adt;
let _3: u32;
Expand Down Expand Up @@ -64,6 +64,26 @@ fn fields(_1: (Adt, Adt)) {
}
}

// EMIT_MIR gvn_overlapping.copy_overlapping.GVN.diff
#[custom_mir(dialect = "runtime")]
fn copy_overlapping() {
// CHECK-LABEL: fn copy_overlapping(
// CHECK-NOT: _1 = copy (*_{{.*}});
// CHECK: _1 = Adt::Some(copy _2);
mir! {
let _1;
let _2;
let _3;
{
place!(Field(Variant(_1, 1), 0)) = 0u32;
_3 = &_1;
_2 = Field(Variant(*_3, 1), 0);
_1 = Adt::Some(_2);
Return()
}
}
}

fn main() {
overlapping(Adt::Some(0));
}
Expand Down
5 changes: 3 additions & 2 deletions tests/mir-opt/gvn_overlapping.stable_projection.GVN.diff
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
bb0: {
_2 = &raw mut (_1.0: Adt);
_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);
+ (_1.0: Adt) = copy (*_4);
+ _3 = copy (((*_2) as variant#1).0: u32);
+ (_1.0: Adt) = copy (*_2);
return;
}
}
Expand Down
Loading