Skip to content

Commit d77734f

Browse files
committed
Fold consecutive PtrToPtr casts.
1 parent f857a8b commit d77734f

13 files changed

+383
-361
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ use rustc_index::IndexVec;
9393
use rustc_middle::mir::interpret::GlobalAlloc;
9494
use rustc_middle::mir::visit::*;
9595
use rustc_middle::mir::*;
96-
use rustc_middle::ty::adjustment::PointerCoercion;
9796
use rustc_middle::ty::layout::LayoutOf;
9897
use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut};
9998
use rustc_span::def_id::DefId;
@@ -777,18 +776,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
777776

778777
// Operations.
779778
Rvalue::Len(ref mut place) => return self.simplify_len(place, location),
780-
Rvalue::Cast(kind, ref mut value, to) => {
781-
let from = value.ty(self.local_decls, self.tcx);
782-
let value = self.simplify_operand(value, location)?;
783-
if let CastKind::PointerCoercion(
784-
PointerCoercion::ReifyFnPointer | PointerCoercion::ClosureFnPointer(_),
785-
) = kind
786-
{
787-
// Each reification of a generic fn may get a different pointer.
788-
// Do not try to merge them.
789-
return self.new_opaque();
790-
}
791-
Value::Cast { kind, value, from, to }
779+
Rvalue::Cast(ref mut kind, ref mut value, to) => {
780+
return self.simplify_cast(kind, value, to, location);
792781
}
793782
Rvalue::BinaryOp(op, box (ref mut lhs, ref mut rhs)) => {
794783
let ty = lhs.ty(self.local_decls, self.tcx);
@@ -1031,6 +1020,47 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10311020
}
10321021
}
10331022

1023+
fn simplify_cast(
1024+
&mut self,
1025+
kind: &mut CastKind,
1026+
operand: &mut Operand<'tcx>,
1027+
to: Ty<'tcx>,
1028+
location: Location,
1029+
) -> Option<VnIndex> {
1030+
use rustc_middle::ty::adjustment::PointerCoercion::*;
1031+
use CastKind::*;
1032+
1033+
let mut from = operand.ty(self.local_decls, self.tcx);
1034+
let mut value = self.simplify_operand(operand, location)?;
1035+
1036+
if let CastKind::PointerCoercion(ReifyFnPointer | ClosureFnPointer(_)) = kind {
1037+
// Each reification of a generic fn may get a different pointer.
1038+
// Do not try to merge them.
1039+
return self.new_opaque();
1040+
}
1041+
1042+
if let PtrToPtr | PointerCoercion(MutToConstPointer) = kind
1043+
&& let Value::Cast { kind: inner_kind, value: inner_value, from: inner_from, to: _ } =
1044+
*self.get(value)
1045+
&& let PtrToPtr | PointerCoercion(MutToConstPointer) = inner_kind
1046+
{
1047+
from = inner_from;
1048+
value = inner_value;
1049+
*kind = PtrToPtr;
1050+
if inner_from == to {
1051+
return Some(inner_value);
1052+
}
1053+
if let Some(const_) = self.try_as_constant(value) {
1054+
*operand = Operand::Constant(Box::new(const_));
1055+
} else if let Some(local) = self.try_as_local(value, location) {
1056+
*operand = Operand::Copy(local.into());
1057+
self.reused_locals.insert(local);
1058+
}
1059+
}
1060+
1061+
Some(self.insert(Value::Cast { kind: *kind, value, from, to }))
1062+
}
1063+
10341064
fn simplify_len(&mut self, place: &mut Place<'tcx>, location: Location) -> Option<VnIndex> {
10351065
// Trivial case: we are fetching a statically known length.
10361066
let place_ty = place.ty(self.local_decls, self.tcx).ty;

tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,16 @@
101101
StorageDead(_15);
102102
StorageDead(_12);
103103
StorageDead(_6);
104-
StorageLive(_18);
104+
- StorageLive(_18);
105+
+ nop;
105106
_18 = (_5.0: *const [u8]);
106-
_4 = move _18 as *mut [u8] (PtrToPtr);
107-
StorageDead(_18);
107+
- _4 = move _18 as *mut [u8] (PtrToPtr);
108+
- StorageDead(_18);
109+
+ _4 = _18 as *mut [u8] (PtrToPtr);
110+
+ nop;
108111
StorageDead(_5);
109-
_3 = move _4 as *mut u8 (PtrToPtr);
112+
- _3 = move _4 as *mut u8 (PtrToPtr);
113+
+ _3 = _18 as *mut u8 (PtrToPtr);
110114
StorageDead(_4);
111115
StorageDead(_3);
112116
return;

tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,16 @@
4848

4949
bb1: {
5050
StorageDead(_6);
51-
StorageLive(_12);
51+
- StorageLive(_12);
52+
+ nop;
5253
_12 = (_5.0: *const [u8]);
53-
_4 = move _12 as *mut [u8] (PtrToPtr);
54-
StorageDead(_12);
54+
- _4 = move _12 as *mut [u8] (PtrToPtr);
55+
- StorageDead(_12);
56+
+ _4 = _12 as *mut [u8] (PtrToPtr);
57+
+ nop;
5558
StorageDead(_5);
56-
_3 = move _4 as *mut u8 (PtrToPtr);
59+
- _3 = move _4 as *mut u8 (PtrToPtr);
60+
+ _3 = _12 as *mut u8 (PtrToPtr);
5761
StorageDead(_4);
5862
StorageDead(_3);
5963
return;

tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,16 @@
101101
StorageDead(_15);
102102
StorageDead(_12);
103103
StorageDead(_6);
104-
StorageLive(_18);
104+
- StorageLive(_18);
105+
+ nop;
105106
_18 = (_5.0: *const [u8]);
106-
_4 = move _18 as *mut [u8] (PtrToPtr);
107-
StorageDead(_18);
107+
- _4 = move _18 as *mut [u8] (PtrToPtr);
108+
- StorageDead(_18);
109+
+ _4 = _18 as *mut [u8] (PtrToPtr);
110+
+ nop;
108111
StorageDead(_5);
109-
_3 = move _4 as *mut u8 (PtrToPtr);
112+
- _3 = move _4 as *mut u8 (PtrToPtr);
113+
+ _3 = _18 as *mut u8 (PtrToPtr);
110114
StorageDead(_4);
111115
StorageDead(_3);
112116
return;

tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,16 @@
4848

4949
bb1: {
5050
StorageDead(_6);
51-
StorageLive(_12);
51+
- StorageLive(_12);
52+
+ nop;
5253
_12 = (_5.0: *const [u8]);
53-
_4 = move _12 as *mut [u8] (PtrToPtr);
54-
StorageDead(_12);
54+
- _4 = move _12 as *mut [u8] (PtrToPtr);
55+
- StorageDead(_12);
56+
+ _4 = _12 as *mut [u8] (PtrToPtr);
57+
+ nop;
5558
StorageDead(_5);
56-
_3 = move _4 as *mut u8 (PtrToPtr);
59+
- _3 = move _4 as *mut u8 (PtrToPtr);
60+
+ _3 = _12 as *mut u8 (PtrToPtr);
5761
StorageDead(_4);
5862
StorageDead(_3);
5963
return;

tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
8787
StorageLive(_12);
8888
StorageLive(_11);
8989
StorageLive(_10);
90-
_10 = _9 as *const () (PointerCoercion(MutToConstPointer));
90+
_10 = _8 as *const () (PtrToPtr);
9191
_11 = std::ptr::metadata::PtrComponents::<[u32]> { data_address: move _10, metadata: _6 };
9292
StorageDead(_10);
9393
_12 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 };

tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
8787
StorageLive(_12);
8888
StorageLive(_11);
8989
StorageLive(_10);
90-
_10 = _9 as *const () (PointerCoercion(MutToConstPointer));
90+
_10 = _8 as *const () (PtrToPtr);
9191
_11 = std::ptr::metadata::PtrComponents::<[u32]> { data_address: move _10, metadata: _6 };
9292
StorageDead(_10);
9393
_12 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 };

tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir

Lines changed: 54 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
44
debug slice => _1;
55
debug f => _2;
66
let mut _0: ();
7-
let mut _13: std::slice::Iter<'_, T>;
7+
let mut _12: std::slice::Iter<'_, T>;
8+
let mut _13: std::iter::Enumerate<std::slice::Iter<'_, T>>;
89
let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>;
9-
let mut _15: std::iter::Enumerate<std::slice::Iter<'_, T>>;
10-
let mut _16: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
11-
let mut _17: std::option::Option<(usize, &T)>;
12-
let mut _18: isize;
13-
let mut _21: &impl Fn(usize, &T);
14-
let mut _22: (usize, &T);
15-
let _23: ();
10+
let mut _15: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
11+
let mut _16: std::option::Option<(usize, &T)>;
12+
let mut _17: isize;
13+
let mut _20: &impl Fn(usize, &T);
14+
let mut _21: (usize, &T);
15+
let _22: ();
1616
scope 1 {
17-
debug iter => _15;
18-
let _19: usize;
19-
let _20: &T;
17+
debug iter => _14;
18+
let _18: usize;
19+
let _19: &T;
2020
scope 2 {
21-
debug i => _19;
22-
debug x => _20;
21+
debug i => _18;
22+
debug x => _19;
2323
}
2424
}
2525
scope 3 (inlined core::slice::<impl [T]>::iter) {
@@ -31,8 +31,8 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
3131
let mut _6: usize;
3232
let mut _8: usize;
3333
let mut _9: *mut T;
34-
let mut _11: std::ptr::NonNull<T>;
35-
let mut _12: *const T;
34+
let mut _10: std::ptr::NonNull<T>;
35+
let mut _11: *const T;
3636
scope 5 {
3737
debug ptr => _4;
3838
scope 6 {
@@ -41,21 +41,20 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
4141
debug end_or_len => _7;
4242
scope 13 (inlined NonNull::<T>::new_unchecked) {
4343
debug ptr => _9;
44-
let mut _10: *const T;
4544
scope 14 {
4645
scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) {
4746
debug ptr => _9;
4847
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) {
4948
debug self => _9;
50-
let mut _24: *mut u8;
49+
let mut _23: *mut u8;
5150
scope 17 {
5251
scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
53-
debug ptr => _24;
52+
debug ptr => _23;
5453
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
55-
debug self => _24;
54+
debug self => _23;
5655
scope 20 {
5756
scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
58-
debug self => _24;
57+
debug self => _23;
5958
}
6059
}
6160
}
@@ -86,22 +85,21 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
8685
}
8786
}
8887
scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) {
89-
debug self => _13;
88+
debug self => _12;
9089
scope 23 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) {
91-
debug iter => _13;
90+
debug iter => _12;
9291
}
9392
}
9493
scope 24 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
95-
debug self => _14;
94+
debug self => _13;
9695
}
9796

9897
bb0: {
99-
StorageLive(_13);
98+
StorageLive(_12);
10099
StorageLive(_4);
101100
StorageLive(_3);
102101
_3 = &raw const (*_1);
103-
_4 = move _3 as *const T (PtrToPtr);
104-
StorageDead(_3);
102+
_4 = _3 as *const T (PtrToPtr);
105103
StorageLive(_7);
106104
StorageLive(_5);
107105
_5 = const _;
@@ -126,46 +124,44 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
126124

127125
bb3: {
128126
StorageDead(_5);
129-
StorageLive(_11);
130-
StorageLive(_9);
131-
_9 = _4 as *mut T (PtrToPtr);
132127
StorageLive(_10);
133-
StorageLive(_24);
134-
_10 = _9 as *const T (PointerCoercion(MutToConstPointer));
135-
_11 = NonNull::<T> { pointer: _10 };
136-
StorageDead(_24);
137-
StorageDead(_10);
128+
StorageLive(_9);
129+
_9 = _3 as *mut T (PtrToPtr);
130+
StorageLive(_23);
131+
_10 = NonNull::<T> { pointer: _4 };
132+
StorageDead(_23);
138133
StorageDead(_9);
139-
StorageLive(_12);
140-
_12 = _7;
141-
_13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
142-
StorageDead(_12);
134+
StorageLive(_11);
135+
_11 = _7;
136+
_12 = std::slice::Iter::<'_, T> { ptr: move _10, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> };
143137
StorageDead(_11);
138+
StorageDead(_10);
144139
StorageDead(_7);
140+
StorageDead(_3);
145141
StorageDead(_4);
146-
_14 = Enumerate::<std::slice::Iter<'_, T>> { iter: move _13, count: const 0_usize };
147-
StorageDead(_13);
148-
StorageLive(_15);
149-
_15 = move _14;
142+
_13 = Enumerate::<std::slice::Iter<'_, T>> { iter: move _12, count: const 0_usize };
143+
StorageDead(_12);
144+
StorageLive(_14);
145+
_14 = move _13;
150146
goto -> bb4;
151147
}
152148

153149
bb4: {
154-
StorageLive(_17);
155150
StorageLive(_16);
156-
_16 = &mut _15;
157-
_17 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _16) -> [return: bb5, unwind unreachable];
151+
StorageLive(_15);
152+
_15 = &mut _14;
153+
_16 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _15) -> [return: bb5, unwind unreachable];
158154
}
159155

160156
bb5: {
161-
StorageDead(_16);
162-
_18 = discriminant(_17);
163-
switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10];
157+
StorageDead(_15);
158+
_17 = discriminant(_16);
159+
switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10];
164160
}
165161

166162
bb6: {
167-
StorageDead(_17);
168-
StorageDead(_15);
163+
StorageDead(_16);
164+
StorageDead(_14);
169165
drop(_2) -> [return: bb7, unwind unreachable];
170166
}
171167

@@ -174,19 +170,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
174170
}
175171

176172
bb8: {
177-
_19 = (((_17 as Some).0: (usize, &T)).0: usize);
178-
_20 = (((_17 as Some).0: (usize, &T)).1: &T);
173+
_18 = (((_16 as Some).0: (usize, &T)).0: usize);
174+
_19 = (((_16 as Some).0: (usize, &T)).1: &T);
175+
StorageLive(_20);
176+
_20 = &_2;
179177
StorageLive(_21);
180-
_21 = &_2;
181-
StorageLive(_22);
182-
_22 = (_19, _20);
183-
_23 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _21, move _22) -> [return: bb9, unwind unreachable];
178+
_21 = (_18, _19);
179+
_22 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _20, move _21) -> [return: bb9, unwind unreachable];
184180
}
185181

186182
bb9: {
187-
StorageDead(_22);
188183
StorageDead(_21);
189-
StorageDead(_17);
184+
StorageDead(_20);
185+
StorageDead(_16);
190186
goto -> bb4;
191187
}
192188

0 commit comments

Comments
 (0)