@@ -727,6 +727,14 @@ fn fn_abi_adjust_for_abi<'tcx>(
727727
728728 match arg. layout . abi {
729729 Abi :: Aggregate { .. } => { }
730+ Abi :: ScalarPair ( ..) => {
731+ // FIXME: It is strange that small struct optimizations are enabled
732+ // for 3-fields are more, but disabled for 2-fields (represented by ScalarPair)
733+ // Here 2-fields optimizations are enabled only for return value
734+ if !tcx. sess . opts . unstable_opts . reg_struct_return || arg_idx. is_some ( ) {
735+ return ;
736+ }
737+ }
730738
731739 // This is a fun case! The gist of what this is doing is
732740 // that we want callers and callees to always agree on the
@@ -758,12 +766,22 @@ fn fn_abi_adjust_for_abi<'tcx>(
758766 }
759767 // Compute `Aggregate` ABI.
760768
761- let is_indirect_not_on_stack =
762- matches ! ( arg. mode, PassMode :: Indirect { on_stack: false , .. } ) ;
763- assert ! ( is_indirect_not_on_stack, "{:?}" , arg) ;
769+ let is_indirect_not_on_stack = ! matches ! ( arg . layout . abi , Abi :: Aggregate { .. } )
770+ || matches ! ( arg. mode, PassMode :: Indirect { on_stack: false , .. } ) ;
771+ assert ! ( is_indirect_not_on_stack, "is_indirect_not_on_stack: {:?}" , arg) ;
764772
765773 let size = arg. layout . size ;
766- if !arg. layout . is_unsized ( ) && size <= Pointer ( AddressSpace :: DATA ) . size ( cx) {
774+ let ptr_size = Pointer ( AddressSpace :: DATA ) . size ( cx) ;
775+
776+ // In x86 we may return 2x pointer sized struct as i64
777+ let reg_struct_return_case = tcx. sess . target . arch == "x86"
778+ && arg_idx. is_none ( )
779+ && tcx. sess . opts . unstable_opts . reg_struct_return
780+ && abi != SpecAbi :: RustIntrinsic ;
781+
782+ if !arg. layout . is_unsized ( )
783+ && ( size <= ptr_size || ( reg_struct_return_case && ( size <= 2 * ptr_size) ) )
784+ {
767785 // We want to pass small aggregates as immediates, but using
768786 // an LLVM aggregate type for this leads to bad optimizations,
769787 // so we pick an appropriately sized integer type instead.
0 commit comments