Skip to content

Commit b2ff77c

Browse files
committed
Do not clone valtree and slice constants.
1 parent 5f9d64d commit b2ff77c

9 files changed

+605
-0
lines changed

compiler/rustc_mir_transform/src/gvn.rs

+31
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,35 @@ impl<'tcx> VnState<'_, 'tcx> {
418418
/// If `index` is a `Value::Constant`, return the `Constant` to be put in the MIR.
419419
fn try_as_constant(&mut self, index: VnIndex) -> Option<ConstOperand<'tcx>> {
420420
if let Value::Constant(const_) = *self.get(index) {
421+
// Some constants may contain pointers. We need to preserve the provenance of these
422+
// pointers, but not all constants guarantee this:
423+
// - valtrees purposefully do not;
424+
// - ConstValue::Slice does not either.
425+
match const_ {
426+
Const::Ty(c) => match c.kind() {
427+
ty::ConstKind::Value(valtree) => match valtree {
428+
// This is just an integer, keep it.
429+
ty::ValTree::Leaf(_) => {}
430+
ty::ValTree::Branch(_) => return None,
431+
},
432+
ty::ConstKind::Param(..)
433+
| ty::ConstKind::Unevaluated(..)
434+
| ty::ConstKind::Expr(..) => {}
435+
// Should not appear in runtime MIR.
436+
ty::ConstKind::Infer(..)
437+
| ty::ConstKind::Bound(..)
438+
| ty::ConstKind::Placeholder(..)
439+
| ty::ConstKind::Error(..) => bug!(),
440+
},
441+
Const::Unevaluated(..) => {}
442+
// If the same slice appears twice in the MIR, we cannot guarantee that we will
443+
// give the same `AllocId` to the data.
444+
Const::Val(ConstValue::Slice { .. }, _) => return None,
445+
Const::Val(
446+
ConstValue::ZeroSized | ConstValue::Scalar(_) | ConstValue::Indirect { .. },
447+
_,
448+
) => {}
449+
}
421450
Some(ConstOperand { span: rustc_span::DUMMY_SP, user_ty: None, const_ })
422451
} else {
423452
None
@@ -447,6 +476,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
447476
fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) {
448477
self.super_statement(stmt, location);
449478
if let StatementKind::Assign(box (_, ref mut rvalue)) = stmt.kind
479+
// Do not try to simplify a constant, it's already in canonical shape.
480+
&& !matches!(rvalue, Rvalue::Use(Operand::Constant(_)))
450481
&& let Some(value) = self.simplify_rvalue(rvalue, location)
451482
{
452483
if let Some(const_) = self.try_as_constant(value) {

tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff

+3
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@
6868
_2 = const 2_u8;
6969
_3 = const 3_u8;
7070
StorageLive(_4);
71+
StorageLive(_5);
72+
_5 = const 3_u8;
7173
_4 = const 6_u8;
74+
StorageDead(_5);
7275
StorageLive(_9);
7376
_9 = const "hello, world!";
7477
StorageLive(_14);

tests/mir-opt/gvn.rs

+13
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,17 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S<u32>) {
212212
opaque(s.0); // *s is not Copy, by (*s).0 is, so we can reuse.
213213
}
214214

215+
fn slices() {
216+
let s = "my favourite slice"; // This is a `Const::Slice` in MIR.
217+
opaque(s);
218+
let t = s; // This should be the same pointer, so cannot be a `Const::Slice`.
219+
opaque(t);
220+
assert_eq!(s.as_ptr(), t.as_ptr());
221+
let u = unsafe { std::mem::transmute::<&str, &[u8]>(s) };
222+
opaque(u);
223+
assert_eq!(s.as_ptr(), u.as_ptr());
224+
}
225+
215226
fn main() {
216227
subexpression_elimination(2, 4, 5);
217228
wrap_unwrap(5);
@@ -223,6 +234,7 @@ fn main() {
223234
multiple_branches(true, 5, 9);
224235
references(5);
225236
dereferences(&mut 5, &6, &S(7));
237+
slices();
226238
}
227239

228240
#[inline(never)]
@@ -238,3 +250,4 @@ fn opaque(_: impl Sized) {}
238250
// EMIT_MIR gvn.multiple_branches.GVN.diff
239251
// EMIT_MIR gvn.references.GVN.diff
240252
// EMIT_MIR gvn.dereferences.GVN.diff
253+
// EMIT_MIR gvn.slices.GVN.diff
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
- // MIR for `slices` before GVN
2+
+ // MIR for `slices` after GVN
3+
4+
fn slices() -> () {
5+
let mut _0: ();
6+
let _1: &str;
7+
let _2: ();
8+
let mut _3: &str;
9+
let _5: ();
10+
let mut _6: &str;
11+
let _7: ();
12+
let mut _8: (&*const u8, &*const u8);
13+
let mut _9: &*const u8;
14+
let _10: *const u8;
15+
let mut _11: &str;
16+
let mut _12: &*const u8;
17+
let _13: *const u8;
18+
let mut _14: &str;
19+
let mut _17: bool;
20+
let mut _18: *const u8;
21+
let mut _19: *const u8;
22+
let mut _20: !;
23+
let _22: !;
24+
let mut _23: core::panicking::AssertKind;
25+
let mut _24: &*const u8;
26+
let _25: &*const u8;
27+
let mut _26: &*const u8;
28+
let _27: &*const u8;
29+
let mut _28: std::option::Option<std::fmt::Arguments<'_>>;
30+
let mut _30: &str;
31+
let _31: ();
32+
let mut _32: &[u8];
33+
let _33: ();
34+
let mut _34: (&*const u8, &*const u8);
35+
let mut _35: &*const u8;
36+
let _36: *const u8;
37+
let mut _37: &str;
38+
let mut _38: &*const u8;
39+
let _39: *const u8;
40+
let mut _40: &[u8];
41+
let mut _43: bool;
42+
let mut _44: *const u8;
43+
let mut _45: *const u8;
44+
let mut _46: !;
45+
let _48: !;
46+
let mut _49: core::panicking::AssertKind;
47+
let mut _50: &*const u8;
48+
let _51: &*const u8;
49+
let mut _52: &*const u8;
50+
let _53: &*const u8;
51+
let mut _54: std::option::Option<std::fmt::Arguments<'_>>;
52+
scope 1 {
53+
debug s => _1;
54+
let _4: &str;
55+
scope 2 {
56+
debug t => _4;
57+
let _15: &*const u8;
58+
let _16: &*const u8;
59+
let _29: &[u8];
60+
scope 3 {
61+
debug left_val => _15;
62+
debug right_val => _16;
63+
let _21: core::panicking::AssertKind;
64+
scope 4 {
65+
debug kind => _21;
66+
}
67+
}
68+
scope 5 {
69+
debug u => _29;
70+
let _41: &*const u8;
71+
let _42: &*const u8;
72+
scope 7 {
73+
debug left_val => _41;
74+
debug right_val => _42;
75+
let _47: core::panicking::AssertKind;
76+
scope 8 {
77+
debug kind => _47;
78+
}
79+
}
80+
}
81+
scope 6 {
82+
}
83+
}
84+
}
85+
86+
bb0: {
87+
- StorageLive(_1);
88+
_1 = const "my favourite slice";
89+
StorageLive(_2);
90+
- StorageLive(_3);
91+
- _3 = _1;
92+
- _2 = opaque::<&str>(move _3) -> [return: bb1, unwind unreachable];
93+
+ _2 = opaque::<&str>(_1) -> [return: bb1, unwind unreachable];
94+
}
95+
96+
bb1: {
97+
- StorageDead(_3);
98+
StorageDead(_2);
99+
StorageLive(_4);
100+
_4 = _1;
101+
StorageLive(_5);
102+
- StorageLive(_6);
103+
- _6 = _4;
104+
- _5 = opaque::<&str>(move _6) -> [return: bb2, unwind unreachable];
105+
+ _5 = opaque::<&str>(_1) -> [return: bb2, unwind unreachable];
106+
}
107+
108+
bb2: {
109+
- StorageDead(_6);
110+
StorageDead(_5);
111+
- StorageLive(_7);
112+
StorageLive(_8);
113+
StorageLive(_9);
114+
StorageLive(_10);
115+
StorageLive(_11);
116+
_11 = &(*_1);
117+
_10 = core::str::<impl str>::as_ptr(move _11) -> [return: bb3, unwind unreachable];
118+
}
119+
120+
bb3: {
121+
StorageDead(_11);
122+
_9 = &_10;
123+
StorageLive(_12);
124+
StorageLive(_13);
125+
StorageLive(_14);
126+
_14 = &(*_4);
127+
_13 = core::str::<impl str>::as_ptr(move _14) -> [return: bb4, unwind unreachable];
128+
}
129+
130+
bb4: {
131+
StorageDead(_14);
132+
_12 = &_13;
133+
_8 = (move _9, move _12);
134+
StorageDead(_12);
135+
StorageDead(_9);
136+
StorageLive(_15);
137+
_15 = (_8.0: &*const u8);
138+
StorageLive(_16);
139+
_16 = (_8.1: &*const u8);
140+
StorageLive(_17);
141+
StorageLive(_18);
142+
_18 = (*_15);
143+
StorageLive(_19);
144+
_19 = (*_16);
145+
_17 = Eq(move _18, move _19);
146+
switchInt(move _17) -> [0: bb6, otherwise: bb5];
147+
}
148+
149+
bb5: {
150+
StorageDead(_19);
151+
StorageDead(_18);
152+
- _7 = const ();
153+
StorageDead(_17);
154+
StorageDead(_16);
155+
StorageDead(_15);
156+
StorageDead(_13);
157+
StorageDead(_10);
158+
StorageDead(_8);
159+
- StorageDead(_7);
160+
- StorageLive(_29);
161+
StorageLive(_30);
162+
_30 = &(*_1);
163+
_29 = move _30 as &[u8] (Transmute);
164+
StorageDead(_30);
165+
StorageLive(_31);
166+
- StorageLive(_32);
167+
- _32 = _29;
168+
- _31 = opaque::<&[u8]>(move _32) -> [return: bb7, unwind unreachable];
169+
+ _31 = opaque::<&[u8]>(_29) -> [return: bb7, unwind unreachable];
170+
}
171+
172+
bb6: {
173+
StorageDead(_19);
174+
StorageDead(_18);
175+
- StorageLive(_21);
176+
_21 = core::panicking::AssertKind::Eq;
177+
StorageLive(_22);
178+
- StorageLive(_23);
179+
- _23 = move _21;
180+
StorageLive(_24);
181+
StorageLive(_25);
182+
_25 = &(*_15);
183+
_24 = &(*_25);
184+
StorageLive(_26);
185+
StorageLive(_27);
186+
_27 = &(*_16);
187+
_26 = &(*_27);
188+
StorageLive(_28);
189+
_28 = Option::<Arguments<'_>>::None;
190+
- _22 = core::panicking::assert_failed::<*const u8, *const u8>(move _23, move _24, move _26, move _28) -> unwind unreachable;
191+
+ _22 = core::panicking::assert_failed::<*const u8, *const u8>(_21, move _24, move _26, move _28) -> unwind unreachable;
192+
}
193+
194+
bb7: {
195+
- StorageDead(_32);
196+
StorageDead(_31);
197+
- StorageLive(_33);
198+
StorageLive(_34);
199+
StorageLive(_35);
200+
StorageLive(_36);
201+
StorageLive(_37);
202+
_37 = &(*_1);
203+
_36 = core::str::<impl str>::as_ptr(move _37) -> [return: bb8, unwind unreachable];
204+
}
205+
206+
bb8: {
207+
StorageDead(_37);
208+
_35 = &_36;
209+
StorageLive(_38);
210+
StorageLive(_39);
211+
StorageLive(_40);
212+
_40 = &(*_29);
213+
_39 = core::slice::<impl [u8]>::as_ptr(move _40) -> [return: bb9, unwind unreachable];
214+
}
215+
216+
bb9: {
217+
StorageDead(_40);
218+
_38 = &_39;
219+
_34 = (move _35, move _38);
220+
StorageDead(_38);
221+
StorageDead(_35);
222+
StorageLive(_41);
223+
_41 = (_34.0: &*const u8);
224+
StorageLive(_42);
225+
_42 = (_34.1: &*const u8);
226+
StorageLive(_43);
227+
StorageLive(_44);
228+
_44 = (*_41);
229+
StorageLive(_45);
230+
_45 = (*_42);
231+
_43 = Eq(move _44, move _45);
232+
switchInt(move _43) -> [0: bb11, otherwise: bb10];
233+
}
234+
235+
bb10: {
236+
StorageDead(_45);
237+
StorageDead(_44);
238+
- _33 = const ();
239+
StorageDead(_43);
240+
StorageDead(_42);
241+
StorageDead(_41);
242+
StorageDead(_39);
243+
StorageDead(_36);
244+
StorageDead(_34);
245+
- StorageDead(_33);
246+
_0 = const ();
247+
- StorageDead(_29);
248+
StorageDead(_4);
249+
- StorageDead(_1);
250+
return;
251+
}
252+
253+
bb11: {
254+
StorageDead(_45);
255+
StorageDead(_44);
256+
- StorageLive(_47);
257+
_47 = core::panicking::AssertKind::Eq;
258+
StorageLive(_48);
259+
- StorageLive(_49);
260+
- _49 = move _47;
261+
StorageLive(_50);
262+
StorageLive(_51);
263+
_51 = &(*_41);
264+
_50 = &(*_51);
265+
StorageLive(_52);
266+
StorageLive(_53);
267+
_53 = &(*_42);
268+
_52 = &(*_53);
269+
StorageLive(_54);
270+
_54 = Option::<Arguments<'_>>::None;
271+
- _48 = core::panicking::assert_failed::<*const u8, *const u8>(move _49, move _50, move _52, move _54) -> unwind unreachable;
272+
+ _48 = core::panicking::assert_failed::<*const u8, *const u8>(_47, move _50, move _52, move _54) -> unwind unreachable;
273+
}
274+
}
275+

0 commit comments

Comments
 (0)