@@ -5346,7 +5346,8 @@ Explosion NativeConventionSchema::mapIntoNative(IRGenModule &IGM,
53465346 IRGenFunction &IGF,
53475347 Explosion &fromNonNative,
53485348 SILType type,
5349- bool isOutlined) const {
5349+ bool isOutlined,
5350+ bool mayPeepholeLoad) const {
53505351 if (fromNonNative.empty ()) {
53515352 assert (empty () && " Empty explosion must match the native convention" );
53525353 return Explosion ();
@@ -5425,6 +5426,82 @@ Explosion NativeConventionSchema::mapIntoNative(IRGenModule &IGM,
54255426 ? coercionTy
54265427 : overlappedCoercionTy;
54275428
5429+ if (mayPeepholeLoad) {
5430+ auto succeeded = [&]() -> bool {
5431+ if (!overlappedCoercionTy->isEmptyTy ())
5432+ return false ;
5433+ auto load = dyn_cast<llvm::LoadInst>(*fromNonNative.begin ());
5434+ if (!load)
5435+ return false ;
5436+ auto *gep = dyn_cast<llvm::GetElementPtrInst>(load->getPointerOperand ());
5437+ if (!gep)
5438+ return false ;
5439+ auto *alloca = dyn_cast<llvm::AllocaInst>(getUnderlyingObject (gep));
5440+ if (!alloca)
5441+ return false ;
5442+ auto numExplosions = fromNonNative.size ();
5443+ if (numExplosions < 2 )
5444+ return false ;
5445+ for (unsigned i = 0 , e = numExplosions; i < e; ++i) {
5446+ auto *otherLoad = dyn_cast<llvm::LoadInst>(*(fromNonNative.begin () + i));
5447+ if (!otherLoad)
5448+ return false ;
5449+ auto otherAlloca = dyn_cast<llvm::AllocaInst>(
5450+ getUnderlyingObject (otherLoad->getPointerOperand ()));
5451+ if (!otherAlloca || otherAlloca != alloca)
5452+ return false ;
5453+ load = otherLoad;
5454+ }
5455+ auto allocaSize =
5456+ DataLayout.getTypeSizeInBits (alloca->getAllocatedType ());
5457+
5458+ Address origAlloca (alloca, alloca->getAllocatedType (),
5459+ Alignment (alloca->getAlign ().value ()));
5460+
5461+ IRBuilder Builder (*IGM.LLVMContext , false );
5462+ Builder.SetInsertPoint (load);
5463+
5464+ if (allocaSize < coercionSize) {
5465+ auto coerced = IGF.createAlloca (coercionTy, Alignment (alloca->getAlign ().value ()) , " tmp.coerce" );
5466+ // Copy the defined bytes.
5467+ Builder.CreateMemCpy (coerced, origAlloca, Size (allocaSize/8 ));
5468+ origAlloca = coerced;
5469+ }
5470+
5471+ adjustAllocaAlignment (DataLayout, origAlloca, coercionTy);
5472+
5473+
5474+ unsigned expandedMapIdx = 0 ;
5475+ SmallVector<llvm::Value *, 8 > expandedElts (expandedTys.size (), nullptr );
5476+ auto structAddr = Builder.CreateElementBitCast (origAlloca, coercionTy);
5477+ for (auto eltIndex : indices (coercionTy->elements ())) {
5478+ auto layout = DataLayout.getStructLayout (coercionTy);
5479+ auto eltTy = coercionTy->getElementType (eltIndex);
5480+ // Skip padding fields.
5481+ if (eltTy->isArrayTy ())
5482+ continue ;
5483+ Address eltAddr = Builder.CreateStructGEP (structAddr, eltIndex, layout);
5484+ llvm::Value *elt = Builder.CreateLoad (eltAddr);
5485+ auto index = expandedTyIndicesMap[expandedMapIdx];
5486+ assert (expandedElts[index] == nullptr );
5487+ expandedElts[index] = elt;
5488+ ++expandedMapIdx;
5489+ }
5490+
5491+ // Add the values to the explosion.
5492+ for (auto *val : expandedElts)
5493+ nativeExplosion.add (val);
5494+ assert (expandedTys.size () == nativeExplosion.size ());
5495+
5496+ return true ;
5497+ }();
5498+
5499+ if (succeeded) {
5500+ (void )fromNonNative.claimAll ();
5501+ return nativeExplosion;
5502+ }
5503+ }
5504+
54285505 // Allocate a temporary for the coercion.
54295506 Address temporary;
54305507 Size tempSize;
@@ -5514,7 +5591,8 @@ Explosion IRGenFunction::coerceValueTo(SILType fromTy, Explosion &from,
55145591
55155592void IRGenFunction::emitScalarReturn (SILType returnResultType,
55165593 SILType funcResultType, Explosion &result,
5517- bool isSwiftCCReturn, bool isOutlined) {
5594+ bool isSwiftCCReturn, bool isOutlined,
5595+ bool mayPeepholeLoad) {
55185596 if (result.empty ()) {
55195597 assert (IGM.getTypeInfo (returnResultType)
55205598 .nativeReturnValueSchema (IGM)
@@ -5533,7 +5611,8 @@ void IRGenFunction::emitScalarReturn(SILType returnResultType,
55335611 assert (!nativeSchema.requiresIndirect ());
55345612
55355613 Explosion native = nativeSchema.mapIntoNative (IGM, *this , result,
5536- funcResultType, isOutlined);
5614+ funcResultType, isOutlined,
5615+ mayPeepholeLoad);
55375616 if (native.size () == 1 ) {
55385617 Builder.CreateRet (native.claimNext ());
55395618 return ;
0 commit comments