16
16
// ===----------------------------------------------------------------------===//
17
17
18
18
#include " GenKeyPath.h"
19
- #include " swift/AST/ExtInfo.h"
20
19
#include " swift/AST/ASTContext.h"
21
20
#include " swift/AST/ASTMangler.h"
22
21
#include " swift/AST/DiagnosticsIRGen.h"
22
+ #include " swift/AST/ExtInfo.h"
23
23
#include " swift/AST/GenericEnvironment.h"
24
24
#include " swift/AST/IRGenOptions.h"
25
25
#include " swift/AST/ParameterList.h"
53
53
#include " llvm/ADT/MapVector.h"
54
54
#include " llvm/ADT/SmallBitVector.h"
55
55
#include " llvm/ADT/TinyPtrVector.h"
56
+ #include " llvm/Analysis/ValueTracking.h"
56
57
#include " llvm/IR/Constant.h"
57
58
#include " llvm/IR/Constants.h"
58
59
#include " llvm/IR/DIBuilder.h"
@@ -3258,7 +3259,9 @@ void IRGenSILFunction::visitExistentialMetatypeInst(
3258
3259
static void emitApplyArgument (IRGenSILFunction &IGF,
3259
3260
SILValue arg,
3260
3261
SILType paramType,
3261
- Explosion &out) {
3262
+ Explosion &out,
3263
+ SILInstruction *apply = nullptr ,
3264
+ unsigned idx = 0 ) {
3262
3265
bool isSubstituted = (arg->getType () != paramType);
3263
3266
3264
3267
// For indirect arguments, we just need to pass a pointer.
@@ -3282,7 +3285,24 @@ static void emitApplyArgument(IRGenSILFunction &IGF,
3282
3285
3283
3286
// Fast path: avoid an unnecessary temporary explosion.
3284
3287
if (!isSubstituted) {
3288
+ bool canForwardLoadToIndirect = false ;
3289
+ auto *load = dyn_cast<LoadInst>(arg);
3290
+ [&]() {
3291
+ if (apply && load && apply->getParent () == load->getParent ()) {
3292
+ for (auto it = std::next (load->getIterator ()), e = apply->getIterator ();
3293
+ it != e; ++it) {
3294
+ if (isa<LoadInst>(&(*it))) {
3295
+ continue ;
3296
+ }
3297
+ return ;
3298
+ }
3299
+ canForwardLoadToIndirect = true ;
3300
+ }
3301
+ }();
3285
3302
IGF.getLoweredExplosion (arg, out);
3303
+ if (canForwardLoadToIndirect) {
3304
+ IGF.setForwardableArgument (idx);
3305
+ }
3286
3306
return ;
3287
3307
}
3288
3308
@@ -3710,6 +3730,8 @@ void IRGenSILFunction::visitFullApplySite(FullApplySite site) {
3710
3730
// Lower the SIL arguments to IR arguments.
3711
3731
3712
3732
// Turn the formal SIL parameters into IR-gen things.
3733
+ clearForwardableArguments ();
3734
+
3713
3735
for (auto index : indices (args)) {
3714
3736
if (origConv.hasIndirectSILErrorResults () &&
3715
3737
index == origConv.getNumIndirectSILResults ()) {
@@ -3718,7 +3740,7 @@ void IRGenSILFunction::visitFullApplySite(FullApplySite site) {
3718
3740
continue ;
3719
3741
}
3720
3742
emitApplyArgument (*this , args[index], emission->getParameterType (index),
3721
- llArgs);
3743
+ llArgs, site. getInstruction (), index );
3722
3744
}
3723
3745
3724
3746
auto &calleeFP = emission->getCallee ().getFunctionPointer ();
@@ -3744,6 +3766,9 @@ void IRGenSILFunction::visitFullApplySite(FullApplySite site) {
3744
3766
Explosion result;
3745
3767
emission->emitToExplosion (result, false );
3746
3768
3769
+ // We might have set forwardable arguments. Clear it for the next round.
3770
+ clearForwardableArguments ();
3771
+
3747
3772
// For a simple apply, just bind the apply result to the result of the call.
3748
3773
if (auto apply = dyn_cast<ApplyInst>(i)) {
3749
3774
setLoweredExplosion (apply, result);
@@ -5336,12 +5361,72 @@ void IRGenSILFunction::visitLoadInst(swift::LoadInst *i) {
5336
5361
setLoweredExplosion (i, lowered);
5337
5362
}
5338
5363
5364
+ static Address canForwardIndirectResultAlloca (const TypeInfo &TI,
5365
+ StoreInst *store,
5366
+ Explosion &argSrc,
5367
+ llvm::Instruction * &insertPt) {
5368
+ // Check that the store stores the result of and apply instruction immediately
5369
+ // preceeding the store.
5370
+ auto *apply = dyn_cast<ApplyInst>(store->getSrc ());
5371
+ auto *allocStack = dyn_cast<AllocStackInst>(store->getDest ());
5372
+ if (!apply || !allocStack || apply->getParent () != store->getParent () ||
5373
+ std::next (apply->getIterator ()) != store->getIterator ())
5374
+ return Address ();
5375
+
5376
+ auto explosionSize = TI.getSchema ().size ();
5377
+ if (argSrc.size () < 1 || explosionSize < 4 )
5378
+ return Address ();
5379
+
5380
+ auto *load = dyn_cast<llvm::LoadInst>(*argSrc.begin ());
5381
+ if (!load)
5382
+ return Address ();
5383
+ auto *gep = dyn_cast<llvm::GetElementPtrInst>(load->getPointerOperand ());
5384
+ if (!gep)
5385
+ return Address ();
5386
+
5387
+ auto *alloca = dyn_cast<llvm::AllocaInst>(getUnderlyingObject (gep));
5388
+ if (!alloca)
5389
+ return Address ();
5390
+
5391
+ // Check all the other loads.
5392
+ for (size_t i = 1 , e = explosionSize; i != e; ++i) {
5393
+ auto *load = dyn_cast<llvm::LoadInst>(*(argSrc.begin () + i));
5394
+ if (!load)
5395
+ return Address ();
5396
+ auto *alloca2 = dyn_cast<llvm::AllocaInst>(
5397
+ getUnderlyingObject (load->getPointerOperand ()));
5398
+ if (!alloca2 || alloca2 != alloca)
5399
+ return Address ();
5400
+ }
5401
+
5402
+ // Set insertPt to the first load such that we are within the lifetime of the
5403
+ // alloca marked by the lifetime intrinsic.
5404
+ insertPt = load;
5405
+
5406
+ return TI.getAddressForPointer (alloca);
5407
+ }
5408
+
5339
5409
void IRGenSILFunction::visitStoreInst (swift::StoreInst *i) {
5340
5410
Explosion source = getLoweredExplosion (i->getSrc ());
5341
5411
Address dest = getLoweredAddress (i->getDest ());
5342
5412
SILType objType = i->getSrc ()->getType ().getObjectType ();
5343
-
5344
5413
const auto &typeInfo = cast<LoadableTypeInfo>(getTypeInfo (objType));
5414
+
5415
+
5416
+ llvm::Instruction *insertPt = nullptr ;
5417
+ auto forwardAddr = canForwardIndirectResultAlloca (typeInfo, i, source,
5418
+ insertPt);
5419
+ if (forwardAddr.isValid ()) {
5420
+ const auto &addrTI = getTypeInfo (i->getDest ()->getType ());
5421
+ // Set the insert point to the first load instruction. We need to be with
5422
+ // the lifetime of the alloca.
5423
+ IRBuilder::SavedInsertionPointRAII insertRAII (this ->Builder , insertPt);
5424
+ addrTI.initializeWithTake (*this , dest, forwardAddr, i->getDest ()->getType (),
5425
+ false );
5426
+ (void )source.claimAll ();
5427
+ return ;
5428
+ }
5429
+
5345
5430
switch (i->getOwnershipQualifier ()) {
5346
5431
case StoreOwnershipQualifier::Unqualified:
5347
5432
case StoreOwnershipQualifier::Init:
0 commit comments