@@ -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