@@ -292,9 +292,7 @@ std::string ExistentialTransform::createExistentialSpecializedFunctionName() {
292
292
int Idx = IdxIt.first ;
293
293
Mangler.setArgumentExistentialToGeneric (Idx);
294
294
}
295
- auto MangledName = Mangler.mangle ();
296
- assert (!F->getModule ().hasFunction (MangledName));
297
- return MangledName;
295
+ return Mangler.mangle ();
298
296
}
299
297
300
298
// / Convert all existential argument types to generic argument type.
@@ -642,41 +640,47 @@ void ExistentialTransform::populateThunkBody() {
642
640
// / its inline strategy as always inline.
643
641
void ExistentialTransform::createExistentialSpecializedFunction () {
644
642
std::string Name = createExistentialSpecializedFunctionName ();
645
- SILLinkage linkage = getSpecializedLinkage (F, F->getLinkage ());
646
643
647
- // / Create devirtualized function type.
644
+ // / Create devirtualized function type and populate ArgToGenericTypeMap .
648
645
auto NewFTy = createExistentialSpecializedFunctionType ();
649
646
650
- auto NewFGenericSig = NewFTy->getInvocationGenericSignature ();
651
- auto NewFGenericEnv = NewFGenericSig->getGenericEnvironment ();
652
-
653
647
// / Step 1: Create the new protocol constrained generic function.
654
- NewF = FunctionBuilder.createFunction (
648
+ if (auto *CachedFn = F->getModule ().lookUpFunction (Name)) {
649
+ // The specialized body still exists (because it is now called directly),
650
+ // but the thunk has been dead-code eliminated.
651
+ assert (CachedFn->getLoweredFunctionType () == NewFTy);
652
+ NewF = CachedFn;
653
+ } else {
654
+ auto NewFGenericSig = NewFTy->getInvocationGenericSignature ();
655
+ auto NewFGenericEnv = NewFGenericSig->getGenericEnvironment ();
656
+ SILLinkage linkage = getSpecializedLinkage (F, F->getLinkage ());
657
+
658
+ NewF = FunctionBuilder.createFunction (
655
659
linkage, Name, NewFTy, NewFGenericEnv, F->getLocation (), F->isBare (),
656
660
F->isTransparent (), F->isSerialized (), IsNotDynamic, F->getEntryCount (),
657
661
F->isThunk (), F->getClassSubclassScope (), F->getInlineStrategy (),
658
662
F->getEffectsKind (), nullptr , F->getDebugScope ());
659
- // / Set the semantics attributes for the new function.
660
- for (auto &Attr : F->getSemanticsAttrs ())
661
- NewF->addSemanticsAttr (Attr);
662
663
663
- // / Set Unqualified ownership, if any.
664
- if (!F->hasOwnership ()) {
665
- NewF->setOwnershipEliminated ();
666
- }
664
+ // / Set the semantics attributes for the new function.
665
+ for (auto &Attr : F->getSemanticsAttrs ())
666
+ NewF->addSemanticsAttr (Attr);
667
667
668
- // / Step 1a: Populate the body of NewF.
669
- SubstitutionMap Subs = SubstitutionMap::get (
668
+ // / Set Unqualified ownership, if any.
669
+ if (!F->hasOwnership ()) {
670
+ NewF->setOwnershipEliminated ();
671
+ }
672
+ // / Step 1a: Populate the body of NewF.
673
+ SubstitutionMap Subs = SubstitutionMap::get (
670
674
NewFGenericSig,
671
675
[&](SubstitutableType *type) -> Type {
672
676
return NewFGenericEnv->mapTypeIntoContext (type);
673
677
},
674
678
LookUpConformanceInModule (F->getModule ().getSwiftModule ()));
675
- ExistentialSpecializerCloner cloner (F, NewF, Subs, ArgumentDescList,
676
- ArgToGenericTypeMap,
677
- ExistentialArgDescriptor);
678
- cloner.cloneAndPopulateFunction ();
679
-
679
+ ExistentialSpecializerCloner cloner (F, NewF, Subs, ArgumentDescList,
680
+ ArgToGenericTypeMap,
681
+ ExistentialArgDescriptor);
682
+ cloner.cloneAndPopulateFunction ();
683
+ }
680
684
// / Step 2: Create the thunk with always_inline and populate its body.
681
685
populateThunkBody ();
682
686
0 commit comments