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 () << " \n The 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