Skip to content

Commit

Permalink
Add de-init to destination place
Browse files Browse the repository at this point in the history
  • Loading branch information
JulianKnodt committed Feb 8, 2023
1 parent 15f4eec commit 15d4728
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 120 deletions.
17 changes: 10 additions & 7 deletions compiler/rustc_mir_transform/src/large_enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_middle::mir::interpret::AllocId;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, AdtDef, Const, ParamEnv, Ty, TyCtxt};
use rustc_session::Session;
use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants};

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

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

let deinit_old =
Statement { source_info, kind: StatementKind::Deinit(box dst) };

let copy_bytes = Statement {
source_info,
kind: StatementKind::Intrinsic(
Expand All @@ -279,6 +281,7 @@ impl EnumSizeOpt {
dst_cast,
src_ptr,
src_cast,
deinit_old,
copy_bytes,
store_dead,
]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
tcx,
body,
&[
&large_enums::EnumSizeOpt { discrepancy: 128 },
&reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode.
&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
&unreachable_prop::UnreachablePropagation,
Expand Down Expand Up @@ -586,6 +585,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&simplify::SimplifyLocals::new("final"),
&multiple_return_terminators::MultipleReturnTerminators,
&deduplicate_blocks::DeduplicateBlocks,
&large_enums::EnumSizeOpt { discrepancy: 128 },
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
&add_call_guards::CriticalCallEdges,
// Dump the end result for testing and debugging purposes.
Expand Down
45 changes: 31 additions & 14 deletions tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
- // MIR for `cand` before EnumSizeOpt
+ // MIR for `cand` after EnumSizeOpt

fn cand() -> () {
let mut _0: (); // return place in scope 0 at $DIR/enum_opt.rs:+0:15: +0:15
fn cand() -> Candidate {
let mut _0: Candidate; // return place in scope 0 at $DIR/enum_opt.rs:+0:18: +0:27
let mut _1: Candidate; // in scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
let mut _2: Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:7: +2:34
let mut _3: [u64; 1024]; // in scope 0 at $DIR/enum_opt.rs:+2:24: +2:33
let mut _3: [u8; 8196]; // in scope 0 at $DIR/enum_opt.rs:+2:24: +2:33
+ let mut _4: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
+ let mut _5: isize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
+ let mut _6: usize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
Expand All @@ -14,38 +14,55 @@
+ let mut _9: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
+ let mut _10: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
+ let mut _11: *const u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
+ let mut _12: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _13: isize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _14: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _15: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _16: *mut Candidate; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _17: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _18: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _19: *const u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
scope 1 {
debug a => _1; // in scope 1 at $DIR/enum_opt.rs:+1:7: +1:12
}

bb0: {
StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
Deinit(_1); // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
((_1 as Small).0: u8) = const 1_u8; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
_1 = Candidate::Small(const 1_u8); // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
_3 = [const 1_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
Deinit(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
((_2 as Large).0: [u64; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
_3 = [const 1_u8; 8196]; // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
_2 = Candidate::Large(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
- _1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _4 = const [2_usize, 8196_usize]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _4 = const [2_usize, 8197_usize]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _5 = discriminant(_2); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _6 = _5 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _7 = _4[_6]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _8 = &raw mut _1; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _9 = _8 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _10 = &raw const _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _11 = _10 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ Deinit(_8); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ copy_nonoverlapping(dst = _9, src = _11, count = _7); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
_0 = const (); // scope 0 at $DIR/enum_opt.rs:+0:15: +3:2
StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+3:1: +3:2
return; // scope 0 at $DIR/enum_opt.rs:+3:2: +3:2
- _0 = move _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ StorageLive(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _12 = const [2_usize, 8197_usize]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _13 = discriminant(_1); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _14 = _13 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _15 = _12[_14]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _16 = &raw mut _0; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _17 = _16 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _18 = &raw const _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _19 = _18 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ Deinit(_16); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ copy_nonoverlapping(dst = _17, src = _19, count = _15); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ StorageDead(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+4:1: +4:2
return; // scope 0 at $DIR/enum_opt.rs:+4:2: +4:2
}
}

45 changes: 31 additions & 14 deletions tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
- // MIR for `cand` before EnumSizeOpt
+ // MIR for `cand` after EnumSizeOpt

fn cand() -> () {
let mut _0: (); // return place in scope 0 at $DIR/enum_opt.rs:+0:15: +0:15
fn cand() -> Candidate {
let mut _0: Candidate; // return place in scope 0 at $DIR/enum_opt.rs:+0:18: +0:27
let mut _1: Candidate; // in scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
let mut _2: Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:7: +2:34
let mut _3: [u64; 1024]; // in scope 0 at $DIR/enum_opt.rs:+2:24: +2:33
let mut _3: [u8; 8196]; // in scope 0 at $DIR/enum_opt.rs:+2:24: +2:33
+ let mut _4: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
+ let mut _5: isize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
+ let mut _6: usize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
Expand All @@ -14,38 +14,55 @@
+ let mut _9: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
+ let mut _10: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
+ let mut _11: *const u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
+ let mut _12: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _13: isize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _14: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _15: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _16: *mut Candidate; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _17: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _18: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ let mut _19: *const u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
scope 1 {
debug a => _1; // in scope 1 at $DIR/enum_opt.rs:+1:7: +1:12
}

bb0: {
StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
Deinit(_1); // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
((_1 as Small).0: u8) = const 1_u8; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
_1 = Candidate::Small(const 1_u8); // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
_3 = [const 1_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
Deinit(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
((_2 as Large).0: [u64; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
_3 = [const 1_u8; 8196]; // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
_2 = Candidate::Large(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
- _1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _4 = const [2_usize, 8200_usize]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _4 = const [2_usize, 8197_usize]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _5 = discriminant(_2); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _6 = _5 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _7 = _4[_6]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _8 = &raw mut _1; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _9 = _8 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _10 = &raw const _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ _11 = _10 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ Deinit(_8); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ copy_nonoverlapping(dst = _9, src = _11, count = _7); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
_0 = const (); // scope 0 at $DIR/enum_opt.rs:+0:15: +3:2
StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+3:1: +3:2
return; // scope 0 at $DIR/enum_opt.rs:+3:2: +3:2
- _0 = move _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ StorageLive(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _12 = const [2_usize, 8197_usize]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _13 = discriminant(_1); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _14 = _13 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _15 = _12[_14]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _16 = &raw mut _0; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _17 = _16 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _18 = &raw const _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ _19 = _18 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ Deinit(_16); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ copy_nonoverlapping(dst = _17, src = _19, count = _15); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ StorageDead(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+4:1: +4:2
return; // scope 0 at $DIR/enum_opt.rs:+4:2: +4:2
}
}

17 changes: 7 additions & 10 deletions tests/mir-opt/enum_opt.invalid.EnumSizeOpt.32bit.diff
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
- // MIR for `invalid` before EnumSizeOpt
+ // MIR for `invalid` after EnumSizeOpt

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

bb0: {
StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
Deinit(_1); // scope 0 at $DIR/enum_opt.rs:+1:15: +1:29
discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:29
_1 = InvalidIdxs::A; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:29
StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:26: +2:35
_3 = [const 0_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:+2:26: +2:35
Deinit(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
((_2 as Large).0: [u64; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
_2 = InvalidIdxs::Large(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:35: +2:36
_1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:36
StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:35: +2:36
_0 = const (); // scope 0 at $DIR/enum_opt.rs:+0:18: +3:2
StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+3:1: +3:2
return; // scope 0 at $DIR/enum_opt.rs:+3:2: +3:2
_0 = move _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+4:1: +4:2
return; // scope 0 at $DIR/enum_opt.rs:+4:2: +4:2
}
}

Loading

0 comments on commit 15d4728

Please sign in to comment.