@@ -138,8 +138,17 @@ fn univariant_uninterned<'tcx>(
138
138
if optimize {
139
139
let end = if let StructKind :: MaybeUnsized = kind { fields. len ( ) - 1 } else { fields. len ( ) } ;
140
140
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
+ }
143
152
} ;
144
153
145
154
// If `-Z randomize-layout` was enabled for the type definition we can shuffle
@@ -161,14 +170,14 @@ fn univariant_uninterned<'tcx>(
161
170
// Place ZSTs first to avoid "interesting offsets",
162
171
// especially with only one or two non-ZST fields.
163
172
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) ) )
165
174
} ) ;
166
175
}
167
176
168
177
StructKind :: Prefixed ( ..) => {
169
178
// Sort in ascending alignment so that the layout stays optimal
170
179
// 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 ] ) ) ;
172
181
}
173
182
}
174
183
0 commit comments