11
11
//===----------------------------------------------------------------------===//
12
12
13
13
#define DEBUG_TYPE "capture-prop"
14
- #include "swift/AST/GenericEnvironment.h"
15
14
#include "swift/SILOptimizer/PassManager/Passes.h"
16
- #include "swift/SILOptimizer/Utils/Generics.h"
17
15
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
18
16
#include "swift/Demangling/Demangle.h"
19
17
#include "swift/SIL/Mangle.h"
20
18
#include "swift/SIL/SILCloner.h"
21
19
#include "swift/SIL/SILInstruction.h"
22
- #include "swift/SIL/TypeSubstCloner.h"
23
20
#include "swift/SILOptimizer/Analysis/ColdBlockInfo.h"
24
21
#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h"
25
22
#include "swift/SILOptimizer/PassManager/Transforms.h"
@@ -102,17 +99,16 @@ namespace {
102
99
/// caller, so the cloned function will have a mix of locations from different
103
100
/// functions.
104
101
class CapturePropagationCloner
105
- : public TypeSubstCloner <CapturePropagationCloner> {
106
- using SuperTy = TypeSubstCloner <CapturePropagationCloner>;
102
+ : public SILClonerWithScopes <CapturePropagationCloner> {
103
+ using SuperTy = SILClonerWithScopes <CapturePropagationCloner>;
107
104
friend class SILVisitor<CapturePropagationCloner>;
108
105
friend class SILCloner<CapturePropagationCloner>;
109
106
110
107
SILFunction *OrigF;
111
108
bool IsCloningConstant;
112
109
public:
113
- CapturePropagationCloner(SILFunction *OrigF, SILFunction *NewF,
114
- SubstitutionList Subs)
115
- : SuperTy(*NewF, *OrigF, Subs), OrigF(OrigF), IsCloningConstant(false) {}
110
+ CapturePropagationCloner(SILFunction *OrigF, SILFunction *NewF)
111
+ : SuperTy(*NewF), OrigF(OrigF), IsCloningConstant(false) {}
116
112
117
113
void cloneBlocks(OperandValueArrayRef Args);
118
114
@@ -223,20 +219,6 @@ void CapturePropagationCloner::cloneBlocks(
223
219
}
224
220
}
225
221
226
- CanSILFunctionType getPartialApplyInterfaceResultType(PartialApplyInst *PAI) {
227
- SILFunction *OrigF = PAI->getReferencedFunction();
228
- // The new partial_apply will no longer take any arguments--they are all
229
- // expressed as literals. So its callee signature will be the same as its
230
- // return signature.
231
- auto FTy = PAI->getType().castTo<SILFunctionType>();
232
- CanGenericSignature CanGenericSig;
233
- assert(!PAI->hasSubstitutions() || !hasArchetypes(PAI->getSubstitutions()));
234
- FTy = cast<SILFunctionType>(
235
- OrigF->mapTypeOutOfContext(FTy)->getCanonicalType());
236
- auto NewFTy = FTy;
237
- return NewFTy;
238
- }
239
-
240
222
/// Given a partial_apply instruction, create a specialized callee by removing
241
223
/// all constant arguments and adding constant literals to the specialized
242
224
/// function body.
@@ -261,16 +243,12 @@ SILFunction *CapturePropagation::specializeConstClosure(PartialApplyInst *PAI,
261
243
// The new partial_apply will no longer take any arguments--they are all
262
244
// expressed as literals. So its callee signature will be the same as its
263
245
// return signature.
264
- auto NewFTy = getPartialApplyInterfaceResultType(PAI);
265
- NewFTy = Lowering::adjustFunctionType(NewFTy,
266
- SILFunctionType::Representation::Thin);
267
-
268
- GenericEnvironment *GenericEnv = nullptr;
269
- if (NewFTy->getGenericSignature())
270
- GenericEnv = OrigF->getGenericEnvironment();
246
+ CanSILFunctionType NewFTy =
247
+ Lowering::adjustFunctionType(PAI->getType().castTo<SILFunctionType>(),
248
+ SILFunctionType::Representation::Thin);
271
249
SILFunction *NewF = OrigF->getModule().createFunction(
272
250
SILLinkage::Shared, Name, NewFTy,
273
- GenericEnv , OrigF->getLocation(), OrigF->isBare(),
251
+ OrigF->getGenericEnvironment() , OrigF->getLocation(), OrigF->isBare(),
274
252
OrigF->isTransparent(), Fragile, OrigF->isThunk(),
275
253
OrigF->getClassVisibility(), OrigF->getInlineStrategy(),
276
254
OrigF->getEffectsKind(),
@@ -281,28 +259,18 @@ SILFunction *CapturePropagation::specializeConstClosure(PartialApplyInst *PAI,
281
259
DEBUG(llvm::dbgs() << " Specialize callee as ";
282
260
NewF->printName(llvm::dbgs()); llvm::dbgs() << " " << NewFTy << "\n");
283
261
284
- DEBUG(if (PAI->hasSubstitutions()) {
285
- llvm::dbgs() << "CapturePropagation of generic partial_apply:\n";
286
- PAI->dumpInContext();
287
- });
288
- CapturePropagationCloner cloner(OrigF, NewF, PAI->getSubstitutions());
262
+ CapturePropagationCloner cloner(OrigF, NewF);
289
263
cloner.cloneBlocks(PAI->getArguments());
290
264
assert(OrigF->getDebugScope()->Parent != NewF->getDebugScope()->Parent);
291
265
return NewF;
292
266
}
293
267
294
268
void CapturePropagation::rewritePartialApply(PartialApplyInst *OrigPAI,
295
269
SILFunction *SpecialF) {
296
- DEBUG(llvm::dbgs() << "\n Rewriting a partial apply:\n";
297
- OrigPAI->dumpInContext(); llvm::dbgs() << " with special function: "
298
- << SpecialF->getName() << "\n";
299
- llvm::dbgs() << "\nThe function being rewritten is:\n";
300
- OrigPAI->getFunction()->dump());
301
-
302
270
SILBuilderWithScope Builder(OrigPAI);
303
271
auto FuncRef = Builder.createFunctionRef(OrigPAI->getLoc(), SpecialF);
304
- auto *T2TF = Builder.createThinToThickFunction(OrigPAI->getLoc(), FuncRef,
305
- OrigPAI->getType());
272
+ auto *T2TF = Builder.createThinToThickFunction(OrigPAI->getLoc(),
273
+ FuncRef, OrigPAI->getType());
306
274
OrigPAI->replaceAllUsesWith(T2TF);
307
275
recursivelyDeleteTriviallyDeadInstructions(OrigPAI, true);
308
276
DEBUG(llvm::dbgs() << " Rewrote caller:\n" << *T2TF);
@@ -343,16 +311,12 @@ static bool onlyContainsReturnOrThrowOfArg(SILBasicBlock *BB) {
343
311
344
312
/// Checks if \p Orig is a thunk which calls another function but without
345
313
/// passing the trailing \p numDeadParams dead parameters.
346
- /// If a generic specialization was performed for a generic capture,
347
- /// GenericSpecialized contains a tuple:
348
- /// (new specialized function, old function)
349
- static SILFunction *getSpecializedWithDeadParams(
350
- PartialApplyInst *PAI, SILFunction *Orig, int numDeadParams,
351
- std::pair<SILFunction *, SILFunction *> &GenericSpecialized) {
314
+ static SILFunction *getSpecializedWithDeadParams(SILFunction *Orig,
315
+ int numDeadParams) {
352
316
SILBasicBlock &EntryBB = *Orig->begin();
353
317
unsigned NumArgs = EntryBB.getNumArguments();
354
318
SILModule &M = Orig->getModule();
355
-
319
+
356
320
// Check if all dead parameters have trivial types. We don't support non-
357
321
// trivial types because it's very hard to find places where we can release
358
322
// those parameters (as a replacement for the removed partial_apply).
@@ -364,20 +328,20 @@ static SILFunction *getSpecializedWithDeadParams(
364
328
}
365
329
SILFunction *Specialized = nullptr;
366
330
SILValue RetValue;
367
-
331
+
368
332
// Check all instruction of the entry block.
369
333
for (SILInstruction &I : EntryBB) {
370
334
if (auto FAS = FullApplySite::isa(&I)) {
335
+
371
336
// Check if this is the call of the specialized function.
372
- // If the original partial_apply didn't have substitutions,
373
- // also the specialized function must be not generic.
374
- if (!PAI->hasSubstitutions() && FAS.hasSubstitutions())
337
+ // As the original function is not generic, also the specialized function
338
+ // must be not generic.
339
+ if (FAS.hasSubstitutions())
375
340
return nullptr;
376
-
377
341
// Is it the only call?
378
342
if (Specialized)
379
343
return nullptr;
380
-
344
+
381
345
Specialized = FAS.getReferencedFunction();
382
346
if (!Specialized)
383
347
return nullptr;
@@ -412,54 +376,29 @@ static SILFunction *getSpecializedWithDeadParams(
412
376
if (I.mayHaveSideEffects() || isa<TermInst>(&I))
413
377
return nullptr;
414
378
}
415
-
416
- GenericSpecialized = std::make_pair(nullptr, nullptr);
417
-
418
- if (PAI->hasSubstitutions()) {
419
- if (Specialized->isExternalDeclaration())
420
- return nullptr;
421
- // Perform a generic specialization of the Specialized function.
422
- ReabstractionInfo ReInfo(ApplySite(), Specialized, PAI->getSubstitutions(),
423
- /* ConvertIndirectToDirect */ false);
424
- GenericFuncSpecializer FuncSpecializer(Specialized,
425
- ReInfo.getClonerParamSubstitutions(),
426
- Specialized->isFragile(), ReInfo);
427
-
428
- SILFunction *GenericSpecializedFunc = FuncSpecializer.trySpecialization();
429
- if (!GenericSpecializedFunc)
430
- return nullptr;
431
- GenericSpecialized = std::make_pair(GenericSpecializedFunc, Specialized);
432
- return GenericSpecializedFunc;
433
- }
434
379
return Specialized;
435
380
}
436
381
437
382
bool CapturePropagation::optimizePartialApply(PartialApplyInst *PAI) {
383
+ // Check if the partial_apply has generic substitutions.
384
+ // FIXME: We could handle generic thunks if it's worthwhile.
385
+ if (PAI->hasSubstitutions())
386
+ return false;
387
+
438
388
SILFunction *SubstF = PAI->getReferencedFunction();
439
389
if (!SubstF)
440
390
return false;
441
391
if (SubstF->isExternalDeclaration())
442
392
return false;
443
393
444
- if (PAI->hasSubstitutions() && hasArchetypes(PAI->getSubstitutions())) {
445
- DEBUG(llvm::dbgs()
446
- << "CapturePropagation: cannot handle partial specialization "
447
- "of partial_apply:\n";
448
- PAI->dumpInContext());
449
- return false;
450
- }
451
-
394
+ assert(!SubstF->getLoweredFunctionType()->isPolymorphic() &&
395
+ "cannot specialize generic partial apply");
452
396
453
397
// First possibility: Is it a partial_apply where all partially applied
454
398
// arguments are dead?
455
- std::pair<SILFunction *, SILFunction *> GenericSpecialized;
456
- if (auto *NewFunc = getSpecializedWithDeadParams(
457
- PAI, SubstF, PAI->getNumArguments(), GenericSpecialized)) {
399
+ if (SILFunction *NewFunc = getSpecializedWithDeadParams(SubstF,
400
+ PAI->getNumArguments())) {
458
401
rewritePartialApply(PAI, NewFunc);
459
- if (GenericSpecialized.first) {
460
- // Notify the pass manager about the new function.
461
- notifyAddFunction(GenericSpecialized.first, GenericSpecialized.second);
462
- }
463
402
return true;
464
403
}
465
404
@@ -472,8 +411,7 @@ bool CapturePropagation::optimizePartialApply(PartialApplyInst *PAI) {
472
411
return false;
473
412
474
413
DEBUG(llvm::dbgs() << "Specializing closure for constant arguments:\n"
475
- << " " << SubstF->getName() << "\n"
476
- << *PAI);
414
+ << " " << SubstF->getName() << "\n" << *PAI);
477
415
++NumCapturesPropagated;
478
416
SILFunction *NewF = specializeConstClosure(PAI, SubstF);
479
417
rewritePartialApply(PAI, NewF);
0 commit comments