@@ -3360,7 +3360,22 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
3360
3360
}
3361
3361
3362
3362
match arg. layout . abi {
3363
- Abi :: Aggregate { .. } => { }
3363
+ Abi :: Aggregate { .. } => {
3364
+ // Pass and return structures up to 2 pointers in size by value,
3365
+ // matching `ScalarPair`. LLVM will usually pass these in 2 registers
3366
+ // which is more efficient than by-ref.
3367
+ let max_by_val_size = Pointer . size ( self ) * 2 ;
3368
+ let size = arg. layout . size ;
3369
+
3370
+ if arg. layout . is_unsized ( ) || size > max_by_val_size {
3371
+ arg. make_indirect ( ) ;
3372
+ } else {
3373
+ // We want to pass small aggregates as immediates, but using
3374
+ // a LLVM aggregate type for this leads to bad optimizations,
3375
+ // so we pick an appropriately sized integer type instead.
3376
+ arg. cast_to ( Reg { kind : RegKind :: Integer , size } ) ;
3377
+ }
3378
+ }
3364
3379
3365
3380
// This is a fun case! The gist of what this is doing is
3366
3381
// that we want callers and callees to always agree on the
@@ -3386,20 +3401,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
3386
3401
&& self . tcx . sess . target . simd_types_indirect =>
3387
3402
{
3388
3403
arg. make_indirect ( ) ;
3389
- return ;
3390
3404
}
3391
3405
3392
- _ => return ,
3393
- }
3394
-
3395
- let size = arg. layout . size ;
3396
- if arg. layout . is_unsized ( ) || size > Pointer . size ( self ) {
3397
- arg. make_indirect ( ) ;
3398
- } else {
3399
- // We want to pass small aggregates as immediates, but using
3400
- // a LLVM aggregate type for this leads to bad optimizations,
3401
- // so we pick an appropriately sized integer type instead.
3402
- arg. cast_to ( Reg { kind : RegKind :: Integer , size } ) ;
3406
+ _ => { } ,
3403
3407
}
3404
3408
} ;
3405
3409
fixup ( & mut fn_abi. ret ) ;
0 commit comments