Skip to content

Commit 8fb2777

Browse files
committed
Fold consecutive PtrToPtr casts.
1 parent 9237612 commit 8fb2777

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;
@@ -780,18 +779,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
780779

781780
// Operations.
782781
Rvalue::Len(ref mut place) => return self.simplify_len(place, location),
783-
Rvalue::Cast(kind, ref mut value, to) => {
784-
let from = value.ty(self.local_decls, self.tcx);
785-
let value = self.simplify_operand(value, location)?;
786-
if let CastKind::PointerCoercion(
787-
PointerCoercion::ReifyFnPointer | PointerCoercion::ClosureFnPointer(_),
788-
) = kind
789-
{
790-
// Each reification of a generic fn may get a different pointer.
791-
// Do not try to merge them.
792-
return self.new_opaque();
793-
}
794-
Value::Cast { kind, value, from, to }
782+
Rvalue::Cast(ref mut kind, ref mut value, to) => {
783+
return self.simplify_cast(kind, value, to, location);
795784
}
796785
Rvalue::BinaryOp(op, box (ref mut lhs, ref mut rhs)) => {
797786
let ty = lhs.ty(self.local_decls, self.tcx);
@@ -1017,6 +1006,47 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10171006
}
10181007
}
10191008

1009+
fn simplify_cast(
1010+
&mut self,
1011+
kind: &mut CastKind,
1012+
operand: &mut Operand<'tcx>,
1013+
to: Ty<'tcx>,
1014+
location: Location,
1015+
) -> Option<VnIndex> {
1016+
use rustc_middle::ty::adjustment::PointerCoercion::*;
1017+
use CastKind::*;
1018+
1019+
let mut from = operand.ty(self.local_decls, self.tcx);
1020+
let mut value = self.simplify_operand(operand, location)?;
1021+
1022+
if let CastKind::PointerCoercion(ReifyFnPointer | ClosureFnPointer(_)) = kind {
1023+
// Each reification of a generic fn may get a different pointer.
1024+
// Do not try to merge them.
1025+
return self.new_opaque();
1026+
}
1027+
1028+
if let PtrToPtr | PointerCoercion(MutToConstPointer) = kind
1029+
&& let Value::Cast { kind: inner_kind, value: inner_value, from: inner_from, to: _ } =
1030+
*self.get(value)
1031+
&& let PtrToPtr | PointerCoercion(MutToConstPointer) = inner_kind
1032+
{
1033+
from = inner_from;
1034+
value = inner_value;
1035+
*kind = PtrToPtr;
1036+
if inner_from == to {
1037+
return Some(inner_value);
1038+
}
1039+
if let Some(const_) = self.try_as_constant(value) {
1040+
*operand = Operand::Constant(Box::new(const_));
1041+
} else if let Some(local) = self.try_as_local(value, location) {
1042+
*operand = Operand::Copy(local.into());
1043+
self.reused_locals.insert(local);
1044+
}
1045+
}
1046+
1047+
Some(self.insert(Value::Cast { kind: *kind, value, from, to }))
1048+
}
1049+
10201050
fn simplify_len(&mut self, place: &mut Place<'tcx>, location: Location) -> Option<VnIndex> {
10211051
// Trivial case: we are fetching a statically known length.
10221052
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
@@ -105,12 +105,16 @@
105105
StorageDead(_15);
106106
StorageDead(_12);
107107
StorageDead(_6);
108-
StorageLive(_18);
108+
- StorageLive(_18);
109+
+ nop;
109110
_18 = (_5.0: *const [u8]);
110-
_4 = move _18 as *mut [u8] (PtrToPtr);
111-
StorageDead(_18);
111+
- _4 = move _18 as *mut [u8] (PtrToPtr);
112+
- StorageDead(_18);
113+
+ _4 = _18 as *mut [u8] (PtrToPtr);
114+
+ nop;
112115
StorageDead(_5);
113-
_3 = move _4 as *mut u8 (PtrToPtr);
116+
- _3 = move _4 as *mut u8 (PtrToPtr);
117+
+ _3 = _18 as *mut u8 (PtrToPtr);
114118
StorageDead(_4);
115119
StorageDead(_3);
116120
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
@@ -105,12 +105,16 @@
105105
StorageDead(_15);
106106
StorageDead(_12);
107107
StorageDead(_6);
108-
StorageLive(_18);
108+
- StorageLive(_18);
109+
+ nop;
109110
_18 = (_5.0: *const [u8]);
110-
_4 = move _18 as *mut [u8] (PtrToPtr);
111-
StorageDead(_18);
111+
- _4 = move _18 as *mut [u8] (PtrToPtr);
112+
- StorageDead(_18);
113+
+ _4 = _18 as *mut [u8] (PtrToPtr);
114+
+ nop;
112115
StorageDead(_5);
113-
_3 = move _4 as *mut u8 (PtrToPtr);
116+
- _3 = move _4 as *mut u8 (PtrToPtr);
117+
+ _3 = _18 as *mut u8 (PtrToPtr);
114118
StorageDead(_4);
115119
StorageDead(_3);
116120
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)