]> git.lizzy.rs Git - rust.git/commitdiff
optimize field ordering by grouping power-of-two arrays with larger types
authorThe 8472 <git@infinite-source.de>
Thu, 6 Oct 2022 19:20:02 +0000 (21:20 +0200)
committerThe 8472 <git@infinite-source.de>
Tue, 22 Nov 2022 22:12:26 +0000 (23:12 +0100)
compiler/rustc_ty_utils/src/layout.rs

index 92e8542795faea78ae7790c5cca6ed3fa89decb1..1505ce41b9630f78fd78f60d17d2deaa30cb97e2 100644 (file)
@@ -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]));
                 }
             }