From 9f0cb566ea2f81392de6fb49b09c7e9b4ef4bf1d Mon Sep 17 00:00:00 2001 From: The 8472 Date: Thu, 6 Oct 2022 21:20:02 +0200 Subject: [PATCH] optimize field ordering by grouping power-of-two arrays with larger types --- compiler/rustc_ty_utils/src/layout.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 92e8542795f..1505ce41b96 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -138,8 +138,17 @@ fn univariant_uninterned<'tcx>( if optimize { let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() }; let optimizing = &mut inverse_memory_index[..end]; - let field_align = |f: &TyAndLayout<'_>| { - if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi } + let effective_field_align = |f: &TyAndLayout<'_>| { + if let Some(pack) = pack { + f.align.abi.min(pack) + } else if f.size.bytes().is_power_of_two() && f.size.bytes() >= f.align.abi.bytes() { + // Try to put fields which have a 2^n size and smaller alignment together with + // fields that have an alignment matching that size. + // E.g. group [u8; 4] with u32 fields + Align::from_bytes(f.align.abi.bytes()).unwrap_or(f.align.abi) + } else { + f.align.abi + } }; // If `-Z randomize-layout` was enabled for the type definition we can shuffle @@ -161,14 +170,14 @@ fn univariant_uninterned<'tcx>( // Place ZSTs first to avoid "interesting offsets", // especially with only one or two non-ZST fields. let f = &fields[x as usize]; - (!f.is_zst(), cmp::Reverse(field_align(f))) + (!f.is_zst(), cmp::Reverse(effective_field_align(f))) }); } StructKind::Prefixed(..) => { // Sort in ascending alignment so that the layout stays optimal // regardless of the prefix - optimizing.sort_by_key(|&x| field_align(&fields[x as usize])); + optimizing.sort_by_key(|&x| effective_field_align(&fields[x as usize])); } }