Skip to content

Commit 9f0cb56

Browse files
committed
optimize field ordering by grouping power-of-two arrays with larger types
1 parent 66ccf36 commit 9f0cb56

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

compiler/rustc_ty_utils/src/layout.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,17 @@ fn univariant_uninterned<'tcx>(
138138
if optimize {
139139
let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
140140
let optimizing = &mut inverse_memory_index[..end];
141-
let field_align = |f: &TyAndLayout<'_>| {
142-
if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi }
141+
let effective_field_align = |f: &TyAndLayout<'_>| {
142+
if let Some(pack) = pack {
143+
f.align.abi.min(pack)
144+
} else if f.size.bytes().is_power_of_two() && f.size.bytes() >= f.align.abi.bytes() {
145+
// Try to put fields which have a 2^n size and smaller alignment together with
146+
// fields that have an alignment matching that size.
147+
// E.g. group [u8; 4] with u32 fields
148+
Align::from_bytes(f.align.abi.bytes()).unwrap_or(f.align.abi)
149+
} else {
150+
f.align.abi
151+
}
143152
};
144153

145154
// If `-Z randomize-layout` was enabled for the type definition we can shuffle
@@ -161,14 +170,14 @@ fn univariant_uninterned<'tcx>(
161170
// Place ZSTs first to avoid "interesting offsets",
162171
// especially with only one or two non-ZST fields.
163172
let f = &fields[x as usize];
164-
(!f.is_zst(), cmp::Reverse(field_align(f)))
173+
(!f.is_zst(), cmp::Reverse(effective_field_align(f)))
165174
});
166175
}
167176

168177
StructKind::Prefixed(..) => {
169178
// Sort in ascending alignment so that the layout stays optimal
170179
// regardless of the prefix
171-
optimizing.sort_by_key(|&x| field_align(&fields[x as usize]));
180+
optimizing.sort_by_key(|&x| effective_field_align(&fields[x as usize]));
172181
}
173182
}
174183

0 commit comments

Comments
 (0)