From 5d9f5145ac9ce07d79aeb75ad049cab957b0fb92 Mon Sep 17 00:00:00 2001 From: kadmin Date: Wed, 16 Jun 2021 05:46:56 +0000 Subject: [PATCH] Rm allocation in candidate Instead of storing an extra array for discriminant values, create an allocation there and store those in an allocation immediately. --- .../rustc_mir/src/transform/large_enums.rs | 278 ----------------- .../rustc_mir_transform/src/large_enums.rs | 283 ++++++++++++++++++ compiler/rustc_mir_transform/src/lib.rs | 3 +- tests/codegen/consts.rs | 2 +- tests/codegen/function-arguments.rs | 2 +- .../enum_opt.cand.EnumSizeOpt.32bit.diff | 55 ++++ .../enum_opt.cand.EnumSizeOpt.64bit.diff | 55 ++++ .../enum_opt.invalid.EnumSizeOpt.32bit.diff | 35 +++ .../enum_opt.invalid.EnumSizeOpt.64bit.diff | 35 +++ tests/mir-opt/enum_opt.rs | 79 +++++ .../enum_opt.trunc.EnumSizeOpt.32bit.diff | 46 +++ .../enum_opt.trunc.EnumSizeOpt.64bit.diff | 46 +++ .../enum_opt.unin.EnumSizeOpt.32bit.diff | 54 ++++ .../enum_opt.unin.EnumSizeOpt.64bit.diff | 54 ++++ 14 files changed, 746 insertions(+), 281 deletions(-) delete mode 100644 compiler/rustc_mir/src/transform/large_enums.rs create mode 100644 compiler/rustc_mir_transform/src/large_enums.rs create mode 100644 tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff create mode 100644 tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff create mode 100644 tests/mir-opt/enum_opt.invalid.EnumSizeOpt.32bit.diff create mode 100644 tests/mir-opt/enum_opt.invalid.EnumSizeOpt.64bit.diff create mode 100644 tests/mir-opt/enum_opt.rs create mode 100644 tests/mir-opt/enum_opt.trunc.EnumSizeOpt.32bit.diff create mode 100644 tests/mir-opt/enum_opt.trunc.EnumSizeOpt.64bit.diff create mode 100644 tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff create mode 100644 tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff diff --git a/compiler/rustc_mir/src/transform/large_enums.rs b/compiler/rustc_mir/src/transform/large_enums.rs deleted file mode 100644 index 51bf880313a6..000000000000 --- a/compiler/rustc_mir/src/transform/large_enums.rs +++ /dev/null @@ -1,278 +0,0 @@ -use crate::transform::MirPass; -use rustc_data_structures::stable_map::FxHashMap; -use rustc_middle::mir::*; -use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, Const, Ty, TyCtxt}; -use rustc_span::def_id::DefId; -use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants}; -use std::array::IntoIter; - -/// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large -/// enough discrepanc between them -pub struct EnumSizeOpt; - -impl<'tcx, const D: u64> MirPass<'tcx> for EnumSizeOpt { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - self.optim(tcx, body); - } -} - -impl EnumSizeOpt { - fn candidate<'tcx>( - tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>, - body_did: DefId, - ) -> Option<(u64, Vec)> { - match ty.kind() { - ty::Adt(adt_def, _substs) if adt_def.is_enum() => { - let p_e = tcx.param_env(body_did); - let layout = - if let Ok(layout) = tcx.layout_of(p_e.and(ty)) { layout } else { return None }; - let variants = &layout.variants; - match variants { - Variants::Single { .. } => None, - Variants::Multiple { variants, .. } if variants.len() <= 1 => None, - Variants::Multiple { tag_encoding, .. } - if matches!(tag_encoding, TagEncoding::Niche { .. }) => - { - None - } - Variants::Multiple { variants, .. } => { - let min = variants.iter().map(|v| v.size).min().unwrap(); - let max = variants.iter().map(|v| v.size).max().unwrap(); - if max.bytes() - min.bytes() < D { - return None; - } - let mut discr_sizes = vec![Size::ZERO; adt_def.discriminants(tcx).count()]; - for (var_idx, layout) in variants.iter_enumerated() { - let disc_idx = - adt_def.discriminant_for_variant(tcx, var_idx).val as usize; - assert_eq!(discr_sizes[disc_idx], Size::ZERO); - discr_sizes[disc_idx] = layout.size; - } - Some((variants.len() as u64, discr_sizes)) - } - } - } - _ => None, - } - } - fn optim(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let mut alloc_cache = FxHashMap::default(); - let body_did = body.source.def_id(); - let (bbs, local_decls) = body.basic_blocks_and_local_decls_mut(); - for bb in bbs { - bb.expand_statements(|st| { - match &st.kind { - StatementKind::Assign(box ( - lhs, - Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)), - )) => { - let ty = lhs.ty(local_decls, tcx).ty; - - let source_info = st.source_info; - let span = source_info.span; - - let (num_variants, sizes) = - if let Some(cand) = Self::candidate(tcx, ty, body_did) { - cand - } else { - return None; - }; - let adt_def = ty.ty_adt_def().unwrap(); - let alloc = if let Some(alloc) = alloc_cache.get(ty) { - alloc - } else { - let data_layout = tcx.data_layout(); - let ptr_sized_int = data_layout.ptr_sized_integer(); - let target_bytes = ptr_sized_int.size().bytes() as usize; - let mut data = vec![0; target_bytes * num_variants as usize]; - let mut curr = 0; - macro_rules! encode_store { - ($endian: expr, $bytes: expr) => { - let bytes = match $endian { - rustc_target::abi::Endian::Little => $bytes.to_le_bytes(), - rustc_target::abi::Endian::Big => $bytes.to_be_bytes(), - }; - for b in bytes { - data[curr] = b; - curr += 1; - } - }; - } - - for sz in sizes { - match ptr_sized_int { - rustc_target::abi::Integer::I32 => { - encode_store!(data_layout.endian, sz.bytes() as u32); - } - rustc_target::abi::Integer::I64 => { - encode_store!(data_layout.endian, sz.bytes()); - } - _ => unreachable!(), - }; - } - let alloc = interpret::Allocation::from_bytes( - data, - tcx.data_layout.ptr_sized_integer().align(&tcx.data_layout).abi, - Mutability::Not, - ); - let alloc = tcx.intern_const_alloc(alloc); - alloc_cache.insert(ty, alloc); - // FIXME(jknodt) use entry API - alloc_cache.get(ty).unwrap() - }; - - let tmp_ty = tcx.mk_ty(ty::Array( - tcx.types.usize, - Const::from_usize(tcx, num_variants), - )); - - let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span)); - let store_live = Statement { - source_info, - kind: StatementKind::StorageLive(size_array_local), - }; - - let place = Place::from(size_array_local); - let constant_vals = Constant { - span, - user_ty: None, - literal: ConstantKind::Val( - interpret::ConstValue::ByRef { alloc, offset: Size::ZERO }, - tmp_ty, - ), - }; - let rval = Rvalue::Use(Operand::Constant(box (constant_vals))); - - let const_assign = Statement { - source_info, - kind: StatementKind::Assign(box (place, rval)), - }; - - let discr_place = Place::from( - local_decls - .push(LocalDecl::new(adt_def.repr.discr_type().to_ty(tcx), span)), - ); - - let store_discr = Statement { - source_info, - kind: StatementKind::Assign(box ( - discr_place, - Rvalue::Discriminant(*rhs), - )), - }; - - let discr_cast_place = - Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); - - let cast_discr = Statement { - source_info, - kind: StatementKind::Assign(box ( - discr_cast_place, - Rvalue::Cast( - CastKind::Misc, - Operand::Copy(discr_place), - tcx.types.usize, - ), - )), - }; - - let size_place = - Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); - - let store_size = Statement { - source_info, - kind: StatementKind::Assign(box ( - size_place, - Rvalue::Use(Operand::Copy(Place { - local: size_array_local, - projection: tcx.intern_place_elems(&[PlaceElem::Index( - discr_cast_place.local, - )]), - })), - )), - }; - - let dst = - Place::from(local_decls.push(LocalDecl::new(tcx.mk_mut_ptr(ty), span))); - - let dst_ptr = Statement { - source_info, - kind: StatementKind::Assign(box ( - dst, - Rvalue::AddressOf(Mutability::Mut, *lhs), - )), - }; - - let dst_cast_ty = tcx.mk_mut_ptr(tcx.types.u8); - let dst_cast_place = - Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span))); - - let dst_cast = Statement { - source_info, - kind: StatementKind::Assign(box ( - dst_cast_place, - Rvalue::Cast(CastKind::Misc, Operand::Copy(dst), dst_cast_ty), - )), - }; - - let src = - Place::from(local_decls.push(LocalDecl::new(tcx.mk_imm_ptr(ty), span))); - - let src_ptr = Statement { - source_info, - kind: StatementKind::Assign(box ( - src, - Rvalue::AddressOf(Mutability::Not, *rhs), - )), - }; - - let src_cast_ty = tcx.mk_imm_ptr(tcx.types.u8); - let src_cast_place = - Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span))); - - let src_cast = Statement { - source_info, - kind: StatementKind::Assign(box ( - src_cast_place, - Rvalue::Cast(CastKind::Misc, Operand::Copy(src), src_cast_ty), - )), - }; - - let copy_bytes = Statement { - source_info, - kind: StatementKind::CopyNonOverlapping(box CopyNonOverlapping { - src: Operand::Copy(src_cast_place), - dst: Operand::Copy(dst_cast_place), - count: Operand::Copy(size_place), - }), - }; - - let store_dead = Statement { - source_info, - kind: StatementKind::StorageDead(size_array_local), - }; - let iter = IntoIter::new([ - store_live, - const_assign, - store_discr, - cast_discr, - store_size, - dst_ptr, - dst_cast, - src_ptr, - src_cast, - copy_bytes, - store_dead, - ]); - - st.make_nop(); - Some(iter) - } - _ => return None, - } - }); - } - } -} diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs new file mode 100644 index 000000000000..1919720de499 --- /dev/null +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -0,0 +1,283 @@ +use crate::rustc_middle::ty::util::IntTypeExt; +use crate::MirPass; +use rustc_data_structures::stable_map::FxHashMap; +use rustc_middle::mir::interpret::AllocId; +use rustc_middle::mir::*; +use rustc_middle::ty::{self, AdtDef, Const, ParamEnv, Ty, TyCtxt}; +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 +/// enough discrepancy between them. +/// +/// i.e. If there is are two variants: +/// ``` +/// enum Example { +/// Small, +/// Large([u32; 1024]), +/// } +/// ``` +/// Instead of emitting moves of the large variant, +/// Perform a memcpy instead. +/// Based off of [this HackMD](https://hackmd.io/@ft4bxUsFT5CEUBmRKYHr7w/rJM8BBPzD). +pub struct EnumSizeOpt { + pub(crate) discrepancy: u64, +} + +impl<'tcx> MirPass<'tcx> for EnumSizeOpt { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let sess = tcx.sess; + if (!sess.opts.debugging_opts.unsound_mir_opts) || sess.mir_opt_level() < 3 { + return; + } + self.optim(tcx, body); + } +} + +impl EnumSizeOpt { + fn candidate<'tcx>( + &self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ty: Ty<'tcx>, + alloc_cache: &mut FxHashMap, AllocId>, + ) -> Option<(AdtDef<'tcx>, usize, AllocId)> { + let adt_def = match ty.kind() { + ty::Adt(adt_def, _substs) if adt_def.is_enum() => adt_def, + _ => return None, + }; + let layout = tcx.layout_of(param_env.and(ty)).ok()?; + let variants = match &layout.variants { + Variants::Single { .. } => return None, + Variants::Multiple { tag_encoding, .. } + if matches!(tag_encoding, TagEncoding::Niche { .. }) => + { + return None; + } + Variants::Multiple { variants, .. } if variants.len() <= 1 => return None, + Variants::Multiple { variants, .. } => variants, + }; + let min = variants.iter().map(|v| v.size()).min().unwrap(); + let max = variants.iter().map(|v| v.size()).max().unwrap(); + if max.bytes() - min.bytes() < self.discrepancy { + return None; + } + + let num_discrs = adt_def.discriminants(tcx).count(); + if variants.iter_enumerated().any(|(var_idx, _)| { + let discr_for_var = adt_def.discriminant_for_variant(tcx, var_idx).val; + (discr_for_var > usize::MAX as u128) || (discr_for_var as usize >= num_discrs) + }) { + return None; + } + if let Some(alloc_id) = alloc_cache.get(&ty) { + return Some((*adt_def, num_discrs, *alloc_id)); + } + + let data_layout = tcx.data_layout(); + let ptr_sized_int = data_layout.ptr_sized_integer(); + let target_bytes = ptr_sized_int.size().bytes() as usize; + let mut data = vec![0; target_bytes * num_discrs]; + macro_rules! encode_store { + ($curr_idx: expr, $endian: expr, $bytes: expr) => { + let bytes = match $endian { + rustc_target::abi::Endian::Little => $bytes.to_le_bytes(), + rustc_target::abi::Endian::Big => $bytes.to_be_bytes(), + }; + for (i, b) in bytes.into_iter().enumerate() { + data[$curr_idx + i] = b; + } + }; + } + + for (var_idx, layout) in variants.iter_enumerated() { + let curr_idx = + target_bytes * adt_def.discriminant_for_variant(tcx, var_idx).val as usize; + let sz = layout.size(); + match ptr_sized_int { + rustc_target::abi::Integer::I32 => { + encode_store!(curr_idx, data_layout.endian, sz.bytes() as u32); + } + rustc_target::abi::Integer::I64 => { + encode_store!(curr_idx, data_layout.endian, sz.bytes()); + } + _ => unreachable!(), + }; + } + let alloc = interpret::Allocation::from_bytes( + data, + tcx.data_layout.ptr_sized_integer().align(&tcx.data_layout).abi, + Mutability::Not, + ); + let alloc = tcx.create_memory_alloc(tcx.intern_const_alloc(alloc)); + Some((*adt_def, num_discrs, *alloc_cache.entry(ty).or_insert(alloc))) + } + fn optim<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let mut alloc_cache = FxHashMap::default(); + let body_did = body.source.def_id(); + let param_env = tcx.param_env(body_did); + let (bbs, local_decls) = body.basic_blocks_and_local_decls_mut(); + for bb in bbs { + bb.expand_statements(|st| { + if let StatementKind::Assign(box ( + lhs, + Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)), + )) = &st.kind + { + let ty = lhs.ty(local_decls, tcx).ty; + + let source_info = st.source_info; + let span = source_info.span; + + let (adt_def, num_variants, alloc_id) = + self.candidate(tcx, param_env, ty, &mut alloc_cache)?; + let alloc = tcx.global_alloc(alloc_id).unwrap_memory(); + + let tmp_ty = tcx.mk_ty(ty::Array( + tcx.types.usize, + Const::from_usize(tcx, num_variants as u64), + )); + + let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span)); + let store_live = Statement { + source_info, + kind: StatementKind::StorageLive(size_array_local), + }; + + let place = Place::from(size_array_local); + let constant_vals = Constant { + span, + user_ty: None, + literal: ConstantKind::Val( + interpret::ConstValue::ByRef { alloc, offset: Size::ZERO }, + tmp_ty, + ), + }; + let rval = Rvalue::Use(Operand::Constant(box (constant_vals))); + + let const_assign = + Statement { source_info, kind: StatementKind::Assign(box (place, rval)) }; + + let discr_place = Place::from( + local_decls + .push(LocalDecl::new(adt_def.repr().discr_type().to_ty(tcx), span)), + ); + + let store_discr = Statement { + source_info, + kind: StatementKind::Assign(box (discr_place, Rvalue::Discriminant(*rhs))), + }; + + let discr_cast_place = + Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); + + let cast_discr = Statement { + source_info, + kind: StatementKind::Assign(box ( + discr_cast_place, + Rvalue::Cast( + CastKind::Misc, + Operand::Copy(discr_place), + tcx.types.usize, + ), + )), + }; + + let size_place = + Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); + + let store_size = Statement { + source_info, + kind: StatementKind::Assign(box ( + size_place, + Rvalue::Use(Operand::Copy(Place { + local: size_array_local, + projection: tcx.intern_place_elems(&[PlaceElem::Index( + discr_cast_place.local, + )]), + })), + )), + }; + + let dst = + Place::from(local_decls.push(LocalDecl::new(tcx.mk_mut_ptr(ty), span))); + + let dst_ptr = Statement { + source_info, + kind: StatementKind::Assign(box ( + dst, + Rvalue::AddressOf(Mutability::Mut, *lhs), + )), + }; + + let dst_cast_ty = tcx.mk_mut_ptr(tcx.types.u8); + let dst_cast_place = + Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span))); + + let dst_cast = Statement { + source_info, + kind: StatementKind::Assign(box ( + dst_cast_place, + Rvalue::Cast(CastKind::Misc, Operand::Copy(dst), dst_cast_ty), + )), + }; + + let src = + Place::from(local_decls.push(LocalDecl::new(tcx.mk_imm_ptr(ty), span))); + + let src_ptr = Statement { + source_info, + kind: StatementKind::Assign(box ( + src, + Rvalue::AddressOf(Mutability::Not, *rhs), + )), + }; + + let src_cast_ty = tcx.mk_imm_ptr(tcx.types.u8); + let src_cast_place = + Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span))); + + let src_cast = Statement { + source_info, + kind: StatementKind::Assign(box ( + src_cast_place, + Rvalue::Cast(CastKind::Misc, Operand::Copy(src), src_cast_ty), + )), + }; + + let copy_bytes = Statement { + source_info, + kind: StatementKind::CopyNonOverlapping(box CopyNonOverlapping { + src: Operand::Copy(src_cast_place), + dst: Operand::Copy(dst_cast_place), + count: Operand::Copy(size_place), + }), + }; + + let store_dead = Statement { + source_info, + kind: StatementKind::StorageDead(size_array_local), + }; + let iter = [ + store_live, + const_assign, + store_discr, + cast_discr, + store_size, + dst_ptr, + dst_cast, + src_ptr, + src_cast, + copy_bytes, + store_dead, + ] + .into_iter(); + + st.make_nop(); + Some(iter) + } else { + None + } + }); + } + } +} diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 00ec4b3e7545..8cd268eb6ce1 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -3,7 +3,6 @@ #![feature(drain_filter)] #![feature(let_chains)] #![feature(let_else)] -#![feature(entry_insert)] #![feature(map_try_insert)] #![feature(min_specialization)] #![feature(never_type)] @@ -75,6 +74,7 @@ mod function_item_references; mod generator; mod inline; mod instcombine; +mod large_enums; mod lower_intrinsics; mod lower_slice_len; mod match_branches; @@ -547,6 +547,7 @@ 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, diff --git a/tests/codegen/consts.rs b/tests/codegen/consts.rs index 9d75356b03dc..260d9de86708 100644 --- a/tests/codegen/consts.rs +++ b/tests/codegen/consts.rs @@ -1,4 +1,4 @@ -// compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0 +// compile-flags: -C no-prepopulate-passes // min-llvm-version: 14.0 #![crate_type = "lib"] diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs index 020d9234e57c..96dfde18683e 100644 --- a/tests/codegen/function-arguments.rs +++ b/tests/codegen/function-arguments.rs @@ -1,4 +1,4 @@ -// compile-flags: -O -C no-prepopulate-passes -Zmir-opt-level=0 +// compile-flags: -O -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff new file mode 100644 index 000000000000..d9923ec7cba7 --- /dev/null +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff @@ -0,0 +1,55 @@ +- // 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:49:15: 49:15 + let mut _1: Candidate; // in scope 0 at $DIR/enum_opt.rs:50:7: 50:12 + let mut _2: Candidate; // in scope 0 at $DIR/enum_opt.rs:51:7: 51:34 + let mut _3: [u64; 1024]; // in scope 0 at $DIR/enum_opt.rs:51:24: 51:33 ++ let mut _4: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _5: isize; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _6: usize; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _7: usize; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _8: *mut Candidate; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _9: *mut u8; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _10: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _11: *const u8; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 + scope 1 { + debug a => _1; // in scope 1 at $DIR/enum_opt.rs:50:7: 50:12 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:50:7: 50:12 + Deinit(_1); // scope 0 at $DIR/enum_opt.rs:50:15: 50:34 + ((_1 as Small).0: u8) = const 1_u8; // scope 0 at $DIR/enum_opt.rs:50:15: 50:34 + discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:50:15: 50:34 + StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:51:7: 51:34 + StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:51:24: 51:33 + _3 = [const 1_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:51:24: 51:33 + Deinit(_2); // scope 1 at $DIR/enum_opt.rs:51:7: 51:34 + ((_2 as Large).0: [u64; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:51:7: 51:34 + discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:51:7: 51:34 + StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:51:33: 51:34 +- _1 = move _2; // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _4 = const [2_usize, 8196_usize]; // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _5 = discriminant(_2); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _6 = _5 as usize (Misc); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _7 = _4[_6]; // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _8 = &raw mut _1; // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _9 = _8 as *mut u8 (Misc); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _10 = &raw const _2; // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _11 = _10 as *const u8 (Misc); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ copy_nonoverlapping(src=_11, dst=_9, count=_7); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 + StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:51:33: 51:34 + _0 = const (); // scope 0 at $DIR/enum_opt.rs:49:15: 52:2 + StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:52:1: 52:2 + return; // scope 0 at $DIR/enum_opt.rs:52:2: 52:2 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/enum_opt.rs:49:1: 52:2 + } + } + diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff new file mode 100644 index 000000000000..e79d2f67a839 --- /dev/null +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff @@ -0,0 +1,55 @@ +- // 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:49:15: 49:15 + let mut _1: Candidate; // in scope 0 at $DIR/enum_opt.rs:50:7: 50:12 + let mut _2: Candidate; // in scope 0 at $DIR/enum_opt.rs:51:7: 51:34 + let mut _3: [u64; 1024]; // in scope 0 at $DIR/enum_opt.rs:51:24: 51:33 ++ let mut _4: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _5: isize; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _6: usize; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _7: usize; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _8: *mut Candidate; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _9: *mut u8; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _10: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 ++ let mut _11: *const u8; // in scope 0 at $DIR/enum_opt.rs:51:3: 51:34 + scope 1 { + debug a => _1; // in scope 1 at $DIR/enum_opt.rs:50:7: 50:12 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:50:7: 50:12 + Deinit(_1); // scope 0 at $DIR/enum_opt.rs:50:15: 50:34 + ((_1 as Small).0: u8) = const 1_u8; // scope 0 at $DIR/enum_opt.rs:50:15: 50:34 + discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:50:15: 50:34 + StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:51:7: 51:34 + StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:51:24: 51:33 + _3 = [const 1_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:51:24: 51:33 + Deinit(_2); // scope 1 at $DIR/enum_opt.rs:51:7: 51:34 + ((_2 as Large).0: [u64; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:51:7: 51:34 + discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:51:7: 51:34 + StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:51:33: 51:34 +- _1 = move _2; // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _4 = const [2_usize, 8200_usize]; // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _5 = discriminant(_2); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _6 = _5 as usize (Misc); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _7 = _4[_6]; // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _8 = &raw mut _1; // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _9 = _8 as *mut u8 (Misc); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _10 = &raw const _2; // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ _11 = _10 as *const u8 (Misc); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ copy_nonoverlapping(src=_11, dst=_9, count=_7); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 ++ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:51:3: 51:34 + StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:51:33: 51:34 + _0 = const (); // scope 0 at $DIR/enum_opt.rs:49:15: 52:2 + StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:52:1: 52:2 + return; // scope 0 at $DIR/enum_opt.rs:52:2: 52:2 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/enum_opt.rs:49:1: 52:2 + } + } + diff --git a/tests/mir-opt/enum_opt.invalid.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.invalid.EnumSizeOpt.32bit.diff new file mode 100644 index 000000000000..d8b6a7940151 --- /dev/null +++ b/tests/mir-opt/enum_opt.invalid.EnumSizeOpt.32bit.diff @@ -0,0 +1,35 @@ +- // 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:55:18: 55:18 + let mut _1: InvalidIdxs; // in scope 0 at $DIR/enum_opt.rs:56:7: 56:12 + let mut _2: InvalidIdxs; // in scope 0 at $DIR/enum_opt.rs:57:7: 57:36 + let mut _3: [u64; 1024]; // in scope 0 at $DIR/enum_opt.rs:57:26: 57:35 + scope 1 { + debug a => _1; // in scope 1 at $DIR/enum_opt.rs:56:7: 56:12 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:56:7: 56:12 + Deinit(_1); // scope 0 at $DIR/enum_opt.rs:56:15: 56:29 + discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:56:15: 56:29 + StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:57:7: 57:36 + StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:57:26: 57:35 + _3 = [const 0_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:57:26: 57:35 + Deinit(_2); // scope 1 at $DIR/enum_opt.rs:57:7: 57:36 + ((_2 as Large).0: [u64; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:57:7: 57:36 + discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:57:7: 57:36 + StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:57:35: 57:36 + _1 = move _2; // scope 1 at $DIR/enum_opt.rs:57:3: 57:36 + StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:57:35: 57:36 + _0 = const (); // scope 0 at $DIR/enum_opt.rs:55:18: 58:2 + StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:58:1: 58:2 + return; // scope 0 at $DIR/enum_opt.rs:58:2: 58:2 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/enum_opt.rs:55:1: 58:2 + } + } + diff --git a/tests/mir-opt/enum_opt.invalid.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.invalid.EnumSizeOpt.64bit.diff new file mode 100644 index 000000000000..d8b6a7940151 --- /dev/null +++ b/tests/mir-opt/enum_opt.invalid.EnumSizeOpt.64bit.diff @@ -0,0 +1,35 @@ +- // 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:55:18: 55:18 + let mut _1: InvalidIdxs; // in scope 0 at $DIR/enum_opt.rs:56:7: 56:12 + let mut _2: InvalidIdxs; // in scope 0 at $DIR/enum_opt.rs:57:7: 57:36 + let mut _3: [u64; 1024]; // in scope 0 at $DIR/enum_opt.rs:57:26: 57:35 + scope 1 { + debug a => _1; // in scope 1 at $DIR/enum_opt.rs:56:7: 56:12 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:56:7: 56:12 + Deinit(_1); // scope 0 at $DIR/enum_opt.rs:56:15: 56:29 + discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:56:15: 56:29 + StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:57:7: 57:36 + StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:57:26: 57:35 + _3 = [const 0_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:57:26: 57:35 + Deinit(_2); // scope 1 at $DIR/enum_opt.rs:57:7: 57:36 + ((_2 as Large).0: [u64; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:57:7: 57:36 + discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:57:7: 57:36 + StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:57:35: 57:36 + _1 = move _2; // scope 1 at $DIR/enum_opt.rs:57:3: 57:36 + StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:57:35: 57:36 + _0 = const (); // scope 0 at $DIR/enum_opt.rs:55:18: 58:2 + StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:58:1: 58:2 + return; // scope 0 at $DIR/enum_opt.rs:58:2: 58:2 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/enum_opt.rs:55:1: 58:2 + } + } + diff --git a/tests/mir-opt/enum_opt.rs b/tests/mir-opt/enum_opt.rs new file mode 100644 index 000000000000..bc72c93da09f --- /dev/null +++ b/tests/mir-opt/enum_opt.rs @@ -0,0 +1,79 @@ +// EMIT_MIR_FOR_EACH_BIT_WIDTH +// compile-flags: -Zunsound-mir-opts -Zmir-opt-level=3 +#![feature(arbitrary_enum_discriminant, repr128)] + +// Tests that an enum with a variant with no data gets correctly transformed. +pub enum NoData { + None, + Large([u64; 1024]), +} + +// Tests that an enum with a variant with data that is a valid candidate gets transformed. +pub enum Candidate { + Small(u8), + Large([u64; 1024]), +} + +// Tests that an enum which has a discriminant much higher than the variant does not get +// tformed. +#[repr(u32)] +pub enum InvalidIdxs { + A = 302, + Large([u64; 1024]), +} + +// Tests that an enum with too high of a discriminant index (not in bounds of usize) does not +// get tformed. +#[repr(u128)] +pub enum Truncatable { + A = 0, + B([u8; 1024]) = 1, + C([u8; 4096]) = 0x10000000000000001, +} + +// Tests that an enum with discriminants in random order still gets tformed correctly. +#[repr(u32)] +pub enum RandOrderDiscr { + A = 13, + B([u8; 1024]) = 5, + C = 7, +} + +// EMIT_MIR enum_opt.unin.EnumSizeOpt.diff +pub fn unin() { + let mut a = NoData::None; + a = NoData::Large([1; 1024]); +} + +// EMIT_MIR enum_opt.cand.EnumSizeOpt.diff +pub fn cand() { + let mut a = Candidate::Small(1); + a = Candidate::Large([1; 1024]); +} + +// EMIT_MIR enum_opt.invalid.EnumSizeOpt.diff +pub fn invalid() { + let mut a = InvalidIdxs::A; + a = InvalidIdxs::Large([0; 1024]); +} + +// EMIT_MIR enum_opt.trunc.EnumSizeOpt.diff +pub fn trunc() { + let mut a = Truncatable::A; + a = Truncatable::B([0; 1024]); + a = Truncatable::C([0; 4096]); +} + +pub fn rand_order() { + let mut a = RandOrderDiscr::A; + a = RandOrderDiscr::B([0; 1024]); + a = RandOrderDiscr::C; +} + +pub fn main() { + unin(); + cand(); + invalid(); + trunc(); + rand_order(); +} diff --git a/tests/mir-opt/enum_opt.trunc.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.trunc.EnumSizeOpt.32bit.diff new file mode 100644 index 000000000000..650c6695f3f0 --- /dev/null +++ b/tests/mir-opt/enum_opt.trunc.EnumSizeOpt.32bit.diff @@ -0,0 +1,46 @@ +- // MIR for `trunc` before EnumSizeOpt ++ // MIR for `trunc` after EnumSizeOpt + + fn trunc() -> () { + let mut _0: (); // return place in scope 0 at $DIR/enum_opt.rs:61:16: 61:16 + let mut _1: Truncatable; // in scope 0 at $DIR/enum_opt.rs:62:7: 62:12 + let mut _2: Truncatable; // in scope 0 at $DIR/enum_opt.rs:63:7: 63:32 + let mut _3: [u8; 1024]; // in scope 0 at $DIR/enum_opt.rs:63:22: 63:31 + let mut _4: Truncatable; // in scope 0 at $DIR/enum_opt.rs:64:7: 64:32 + let mut _5: [u8; 4096]; // in scope 0 at $DIR/enum_opt.rs:64:22: 64:31 + scope 1 { + debug a => _1; // in scope 1 at $DIR/enum_opt.rs:62:7: 62:12 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:62:7: 62:12 + Deinit(_1); // scope 0 at $DIR/enum_opt.rs:62:15: 62:29 + discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:62:15: 62:29 + StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:63:7: 63:32 + StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:63:22: 63:31 + _3 = [const 0_u8; 1024]; // scope 1 at $DIR/enum_opt.rs:63:22: 63:31 + Deinit(_2); // scope 1 at $DIR/enum_opt.rs:63:7: 63:32 + ((_2 as B).0: [u8; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:63:7: 63:32 + discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:63:7: 63:32 + StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:63:31: 63:32 + _1 = move _2; // scope 1 at $DIR/enum_opt.rs:63:3: 63:32 + StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:63:31: 63:32 + StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:64:7: 64:32 + StorageLive(_5); // scope 1 at $DIR/enum_opt.rs:64:22: 64:31 + _5 = [const 0_u8; 4096]; // scope 1 at $DIR/enum_opt.rs:64:22: 64:31 + Deinit(_4); // scope 1 at $DIR/enum_opt.rs:64:7: 64:32 + ((_4 as C).0: [u8; 4096]) = move _5; // scope 1 at $DIR/enum_opt.rs:64:7: 64:32 + discriminant(_4) = 2; // scope 1 at $DIR/enum_opt.rs:64:7: 64:32 + StorageDead(_5); // scope 1 at $DIR/enum_opt.rs:64:31: 64:32 + _1 = move _4; // scope 1 at $DIR/enum_opt.rs:64:3: 64:32 + StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:64:31: 64:32 + _0 = const (); // scope 0 at $DIR/enum_opt.rs:61:16: 65:2 + StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:65:1: 65:2 + return; // scope 0 at $DIR/enum_opt.rs:65:2: 65:2 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/enum_opt.rs:61:1: 65:2 + } + } + diff --git a/tests/mir-opt/enum_opt.trunc.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.trunc.EnumSizeOpt.64bit.diff new file mode 100644 index 000000000000..650c6695f3f0 --- /dev/null +++ b/tests/mir-opt/enum_opt.trunc.EnumSizeOpt.64bit.diff @@ -0,0 +1,46 @@ +- // MIR for `trunc` before EnumSizeOpt ++ // MIR for `trunc` after EnumSizeOpt + + fn trunc() -> () { + let mut _0: (); // return place in scope 0 at $DIR/enum_opt.rs:61:16: 61:16 + let mut _1: Truncatable; // in scope 0 at $DIR/enum_opt.rs:62:7: 62:12 + let mut _2: Truncatable; // in scope 0 at $DIR/enum_opt.rs:63:7: 63:32 + let mut _3: [u8; 1024]; // in scope 0 at $DIR/enum_opt.rs:63:22: 63:31 + let mut _4: Truncatable; // in scope 0 at $DIR/enum_opt.rs:64:7: 64:32 + let mut _5: [u8; 4096]; // in scope 0 at $DIR/enum_opt.rs:64:22: 64:31 + scope 1 { + debug a => _1; // in scope 1 at $DIR/enum_opt.rs:62:7: 62:12 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:62:7: 62:12 + Deinit(_1); // scope 0 at $DIR/enum_opt.rs:62:15: 62:29 + discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:62:15: 62:29 + StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:63:7: 63:32 + StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:63:22: 63:31 + _3 = [const 0_u8; 1024]; // scope 1 at $DIR/enum_opt.rs:63:22: 63:31 + Deinit(_2); // scope 1 at $DIR/enum_opt.rs:63:7: 63:32 + ((_2 as B).0: [u8; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:63:7: 63:32 + discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:63:7: 63:32 + StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:63:31: 63:32 + _1 = move _2; // scope 1 at $DIR/enum_opt.rs:63:3: 63:32 + StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:63:31: 63:32 + StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:64:7: 64:32 + StorageLive(_5); // scope 1 at $DIR/enum_opt.rs:64:22: 64:31 + _5 = [const 0_u8; 4096]; // scope 1 at $DIR/enum_opt.rs:64:22: 64:31 + Deinit(_4); // scope 1 at $DIR/enum_opt.rs:64:7: 64:32 + ((_4 as C).0: [u8; 4096]) = move _5; // scope 1 at $DIR/enum_opt.rs:64:7: 64:32 + discriminant(_4) = 2; // scope 1 at $DIR/enum_opt.rs:64:7: 64:32 + StorageDead(_5); // scope 1 at $DIR/enum_opt.rs:64:31: 64:32 + _1 = move _4; // scope 1 at $DIR/enum_opt.rs:64:3: 64:32 + StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:64:31: 64:32 + _0 = const (); // scope 0 at $DIR/enum_opt.rs:61:16: 65:2 + StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:65:1: 65:2 + return; // scope 0 at $DIR/enum_opt.rs:65:2: 65:2 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/enum_opt.rs:61:1: 65:2 + } + } + diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff new file mode 100644 index 000000000000..c034c127ecad --- /dev/null +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff @@ -0,0 +1,54 @@ +- // MIR for `unin` before EnumSizeOpt ++ // MIR for `unin` after EnumSizeOpt + + fn unin() -> () { + let mut _0: (); // return place in scope 0 at $DIR/enum_opt.rs:43:15: 43:15 + let mut _1: NoData; // in scope 0 at $DIR/enum_opt.rs:44:7: 44:12 + let mut _2: NoData; // in scope 0 at $DIR/enum_opt.rs:45:7: 45:31 + let mut _3: [u64; 1024]; // in scope 0 at $DIR/enum_opt.rs:45:21: 45:30 ++ let mut _4: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _5: isize; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _6: usize; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _7: usize; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _8: *mut NoData; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _9: *mut u8; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _10: *const NoData; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _11: *const u8; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 + scope 1 { + debug a => _1; // in scope 1 at $DIR/enum_opt.rs:44:7: 44:12 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:44:7: 44:12 + Deinit(_1); // scope 0 at $DIR/enum_opt.rs:44:15: 44:27 + discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:44:15: 44:27 + StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:45:7: 45:31 + StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:45:21: 45:30 + _3 = [const 1_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:45:21: 45:30 + Deinit(_2); // scope 1 at $DIR/enum_opt.rs:45:7: 45:31 + ((_2 as Large).0: [u64; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:45:7: 45:31 + discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:45:7: 45:31 + StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:45:30: 45:31 +- _1 = move _2; // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _4 = const [4_usize, 8196_usize]; // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _5 = discriminant(_2); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _6 = _5 as usize (Misc); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _7 = _4[_6]; // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _8 = &raw mut _1; // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _9 = _8 as *mut u8 (Misc); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _10 = &raw const _2; // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _11 = _10 as *const u8 (Misc); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ copy_nonoverlapping(src=_11, dst=_9, count=_7); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 + StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:45:30: 45:31 + _0 = const (); // scope 0 at $DIR/enum_opt.rs:43:15: 46:2 + StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:46:1: 46:2 + return; // scope 0 at $DIR/enum_opt.rs:46:2: 46:2 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/enum_opt.rs:43:1: 46:2 + } + } + diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff new file mode 100644 index 000000000000..9389c0f12a04 --- /dev/null +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff @@ -0,0 +1,54 @@ +- // MIR for `unin` before EnumSizeOpt ++ // MIR for `unin` after EnumSizeOpt + + fn unin() -> () { + let mut _0: (); // return place in scope 0 at $DIR/enum_opt.rs:43:15: 43:15 + let mut _1: NoData; // in scope 0 at $DIR/enum_opt.rs:44:7: 44:12 + let mut _2: NoData; // in scope 0 at $DIR/enum_opt.rs:45:7: 45:31 + let mut _3: [u64; 1024]; // in scope 0 at $DIR/enum_opt.rs:45:21: 45:30 ++ let mut _4: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _5: isize; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _6: usize; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _7: usize; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _8: *mut NoData; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _9: *mut u8; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _10: *const NoData; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 ++ let mut _11: *const u8; // in scope 0 at $DIR/enum_opt.rs:45:3: 45:31 + scope 1 { + debug a => _1; // in scope 1 at $DIR/enum_opt.rs:44:7: 44:12 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:44:7: 44:12 + Deinit(_1); // scope 0 at $DIR/enum_opt.rs:44:15: 44:27 + discriminant(_1) = 0; // scope 0 at $DIR/enum_opt.rs:44:15: 44:27 + StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:45:7: 45:31 + StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:45:21: 45:30 + _3 = [const 1_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:45:21: 45:30 + Deinit(_2); // scope 1 at $DIR/enum_opt.rs:45:7: 45:31 + ((_2 as Large).0: [u64; 1024]) = move _3; // scope 1 at $DIR/enum_opt.rs:45:7: 45:31 + discriminant(_2) = 1; // scope 1 at $DIR/enum_opt.rs:45:7: 45:31 + StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:45:30: 45:31 +- _1 = move _2; // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _4 = const [8_usize, 8200_usize]; // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _5 = discriminant(_2); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _6 = _5 as usize (Misc); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _7 = _4[_6]; // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _8 = &raw mut _1; // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _9 = _8 as *mut u8 (Misc); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _10 = &raw const _2; // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ _11 = _10 as *const u8 (Misc); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ copy_nonoverlapping(src=_11, dst=_9, count=_7); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 ++ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:45:3: 45:31 + StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:45:30: 45:31 + _0 = const (); // scope 0 at $DIR/enum_opt.rs:43:15: 46:2 + StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:46:1: 46:2 + return; // scope 0 at $DIR/enum_opt.rs:46:2: 46:2 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/enum_opt.rs:43:1: 46:2 + } + } +