Skip to content

Commit 15d4728

Browse files
committed
Add de-init to destination place
1 parent 15f4eec commit 15d4728

11 files changed

+181
-120
lines changed

compiler/rustc_mir_transform/src/large_enums.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_data_structures::fx::FxHashMap;
44
use rustc_middle::mir::interpret::AllocId;
55
use rustc_middle::mir::*;
66
use rustc_middle::ty::{self, AdtDef, Const, ParamEnv, Ty, TyCtxt};
7+
use rustc_session::Session;
78
use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants};
89

910
/// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large
@@ -28,14 +29,12 @@ pub struct EnumSizeOpt {
2829
}
2930

3031
impl<'tcx> MirPass<'tcx> for EnumSizeOpt {
32+
fn is_enabled(&self, sess: &Session) -> bool {
33+
sess.opts.unstable_opts.unsound_mir_opts || sess.mir_opt_level() >= 3
34+
}
3135
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
32-
let sess = tcx.sess;
33-
// FIXME(julianknodt): one thing noticed while testing this mir-opt is that there is a
34-
// different layout of large enums on wasm. It's not clear what is causing this layout
35-
// difference, as it should be identical to i686 (32 bit).
36-
if (!sess.opts.unstable_opts.unsound_mir_opts) || sess.mir_opt_level() < 3 {
37-
return;
38-
}
36+
// NOTE: This pass may produce different MIR based on the alignment of the target
37+
// platform, but it will still be valid.
3938
self.optim(tcx, body);
4039
}
4140
}
@@ -254,6 +253,9 @@ impl EnumSizeOpt {
254253
)),
255254
};
256255

256+
let deinit_old =
257+
Statement { source_info, kind: StatementKind::Deinit(box dst) };
258+
257259
let copy_bytes = Statement {
258260
source_info,
259261
kind: StatementKind::Intrinsic(
@@ -279,6 +281,7 @@ impl EnumSizeOpt {
279281
dst_cast,
280282
src_ptr,
281283
src_cast,
284+
deinit_old,
282285
copy_bytes,
283286
store_dead,
284287
]

compiler/rustc_mir_transform/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
547547
tcx,
548548
body,
549549
&[
550-
&large_enums::EnumSizeOpt { discrepancy: 128 },
551550
&reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode.
552551
&lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
553552
&unreachable_prop::UnreachablePropagation,
@@ -586,6 +585,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
586585
&simplify::SimplifyLocals::new("final"),
587586
&multiple_return_terminators::MultipleReturnTerminators,
588587
&deduplicate_blocks::DeduplicateBlocks,
588+
&large_enums::EnumSizeOpt { discrepancy: 128 },
589589
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
590590
&add_call_guards::CriticalCallEdges,
591591
// Dump the end result for testing and debugging purposes.
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
- // MIR for `cand` before EnumSizeOpt
22
+ // MIR for `cand` after EnumSizeOpt
33

4-
fn cand() -> () {
5-
let mut _0: (); // return place in scope 0 at $DIR/enum_opt.rs:+0:15: +0:15
4+
fn cand() -> Candidate {
5+
let mut _0: Candidate; // return place in scope 0 at $DIR/enum_opt.rs:+0:18: +0:27
66
let mut _1: Candidate; // in scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
77
let mut _2: Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:7: +2:34
8-
let mut _3: [u64; 1024]; // in scope 0 at $DIR/enum_opt.rs:+2:24: +2:33
8+
let mut _3: [u8; 8196]; // in scope 0 at $DIR/enum_opt.rs:+2:24: +2:33
99
+ let mut _4: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
1010
+ let mut _5: isize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
1111
+ let mut _6: usize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
@@ -14,38 +14,55 @@
1414
+ let mut _9: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
1515
+ let mut _10: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
1616
+ let mut _11: *const u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
17+
+ let mut _12: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
18+
+ let mut _13: isize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
19+
+ let mut _14: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
20+
+ let mut _15: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
21+
+ let mut _16: *mut Candidate; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
22+
+ let mut _17: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
23+
+ let mut _18: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
24+
+ let mut _19: *const u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
1725
scope 1 {
1826
debug a => _1; // in scope 1 at $DIR/enum_opt.rs:+1:7: +1:12
1927
}
2028

2129
bb0: {
2230
StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
23-
Deinit(_1); // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
24-
((_1 as Small).0: u8) = const 1_u8; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
25-
discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
31+
_1 = Candidate::Small(const 1_u8); // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
2632
StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
2733
StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
28-
_3 = [const 1_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
29-
Deinit(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
30-
((_2 as Large).0: [u64; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
31-
discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
34+
_3 = [const 1_u8; 8196]; // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
35+
_2 = Candidate::Large(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
3236
StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
3337
- _1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
3438
+ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
35-
+ _4 = const [2_usize, 8196_usize]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
39+
+ _4 = const [2_usize, 8197_usize]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
3640
+ _5 = discriminant(_2); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
3741
+ _6 = _5 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
3842
+ _7 = _4[_6]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
3943
+ _8 = &raw mut _1; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
4044
+ _9 = _8 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
4145
+ _10 = &raw const _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
4246
+ _11 = _10 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
47+
+ Deinit(_8); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
4348
+ copy_nonoverlapping(dst = _9, src = _11, count = _7); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
4449
+ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
4550
StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
46-
_0 = const (); // scope 0 at $DIR/enum_opt.rs:+0:15: +3:2
47-
StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+3:1: +3:2
48-
return; // scope 0 at $DIR/enum_opt.rs:+3:2: +3:2
51+
- _0 = move _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
52+
+ StorageLive(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
53+
+ _12 = const [2_usize, 8197_usize]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
54+
+ _13 = discriminant(_1); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
55+
+ _14 = _13 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
56+
+ _15 = _12[_14]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
57+
+ _16 = &raw mut _0; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
58+
+ _17 = _16 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
59+
+ _18 = &raw const _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
60+
+ _19 = _18 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
61+
+ Deinit(_16); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
62+
+ copy_nonoverlapping(dst = _17, src = _19, count = _15); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
63+
+ StorageDead(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
64+
StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+4:1: +4:2
65+
return; // scope 0 at $DIR/enum_opt.rs:+4:2: +4:2
4966
}
5067
}
5168

Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
- // MIR for `cand` before EnumSizeOpt
22
+ // MIR for `cand` after EnumSizeOpt
33

4-
fn cand() -> () {
5-
let mut _0: (); // return place in scope 0 at $DIR/enum_opt.rs:+0:15: +0:15
4+
fn cand() -> Candidate {
5+
let mut _0: Candidate; // return place in scope 0 at $DIR/enum_opt.rs:+0:18: +0:27
66
let mut _1: Candidate; // in scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
77
let mut _2: Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:7: +2:34
8-
let mut _3: [u64; 1024]; // in scope 0 at $DIR/enum_opt.rs:+2:24: +2:33
8+
let mut _3: [u8; 8196]; // in scope 0 at $DIR/enum_opt.rs:+2:24: +2:33
99
+ let mut _4: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
1010
+ let mut _5: isize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
1111
+ let mut _6: usize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
@@ -14,38 +14,55 @@
1414
+ let mut _9: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
1515
+ let mut _10: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
1616
+ let mut _11: *const u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
17+
+ let mut _12: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
18+
+ let mut _13: isize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
19+
+ let mut _14: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
20+
+ let mut _15: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
21+
+ let mut _16: *mut Candidate; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
22+
+ let mut _17: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
23+
+ let mut _18: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
24+
+ let mut _19: *const u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
1725
scope 1 {
1826
debug a => _1; // in scope 1 at $DIR/enum_opt.rs:+1:7: +1:12
1927
}
2028

2129
bb0: {
2230
StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
23-
Deinit(_1); // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
24-
((_1 as Small).0: u8) = const 1_u8; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
25-
discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
31+
_1 = Candidate::Small(const 1_u8); // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
2632
StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
2733
StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
28-
_3 = [const 1_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
29-
Deinit(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
30-
((_2 as Large).0: [u64; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
31-
discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
34+
_3 = [const 1_u8; 8196]; // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
35+
_2 = Candidate::Large(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
3236
StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
3337
- _1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
3438
+ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
35-
+ _4 = const [2_usize, 8200_usize]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
39+
+ _4 = const [2_usize, 8197_usize]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
3640
+ _5 = discriminant(_2); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
3741
+ _6 = _5 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
3842
+ _7 = _4[_6]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
3943
+ _8 = &raw mut _1; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
4044
+ _9 = _8 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
4145
+ _10 = &raw const _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
4246
+ _11 = _10 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
47+
+ Deinit(_8); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
4348
+ copy_nonoverlapping(dst = _9, src = _11, count = _7); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
4449
+ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
4550
StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
46-
_0 = const (); // scope 0 at $DIR/enum_opt.rs:+0:15: +3:2
47-
StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+3:1: +3:2
48-
return; // scope 0 at $DIR/enum_opt.rs:+3:2: +3:2
51+
- _0 = move _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
52+
+ StorageLive(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
53+
+ _12 = const [2_usize, 8197_usize]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
54+
+ _13 = discriminant(_1); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
55+
+ _14 = _13 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
56+
+ _15 = _12[_14]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
57+
+ _16 = &raw mut _0; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
58+
+ _17 = _16 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
59+
+ _18 = &raw const _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
60+
+ _19 = _18 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
61+
+ Deinit(_16); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
62+
+ copy_nonoverlapping(dst = _17, src = _19, count = _15); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
63+
+ StorageDead(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
64+
StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+4:1: +4:2
65+
return; // scope 0 at $DIR/enum_opt.rs:+4:2: +4:2
4966
}
5067
}
5168

Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
- // MIR for `invalid` before EnumSizeOpt
22
+ // MIR for `invalid` after EnumSizeOpt
33

4-
fn invalid() -> () {
5-
let mut _0: (); // return place in scope 0 at $DIR/enum_opt.rs:+0:18: +0:18
4+
fn invalid() -> InvalidIdxs {
5+
let mut _0: InvalidIdxs; // return place in scope 0 at $DIR/enum_opt.rs:+0:21: +0:32
66
let mut _1: InvalidIdxs; // in scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
77
let mut _2: InvalidIdxs; // in scope 0 at $DIR/enum_opt.rs:+2:7: +2:36
88
let mut _3: [u64; 1024]; // in scope 0 at $DIR/enum_opt.rs:+2:26: +2:35
@@ -12,20 +12,17 @@
1212

1313
bb0: {
1414
StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
15-
Deinit(_1); // scope 0 at $DIR/enum_opt.rs:+1:15: +1:29
16-
discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:29
15+
_1 = InvalidIdxs::A; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:29
1716
StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
1817
StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:26: +2:35
1918
_3 = [const 0_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:+2:26: +2:35
20-
Deinit(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
21-
((_2 as Large).0: [u64; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
22-
discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
19+
_2 = InvalidIdxs::Large(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
2320
StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:35: +2:36
2421
_1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:36
2522
StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:35: +2:36
26-
_0 = const (); // scope 0 at $DIR/enum_opt.rs:+0:18: +3:2
27-
StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+3:1: +3:2
28-
return; // scope 0 at $DIR/enum_opt.rs:+3:2: +3:2
23+
_0 = move _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
24+
StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+4:1: +4:2
25+
return; // scope 0 at $DIR/enum_opt.rs:+4:2: +4:2
2926
}
3027
}
3128

0 commit comments

Comments
 (0)