@@ -292,9 +292,7 @@ std::string ExistentialTransform::createExistentialSpecializedFunctionName() {
292292 int Idx = IdxIt.first ;
293293 Mangler.setArgumentExistentialToGeneric (Idx);
294294 }
295- auto MangledName = Mangler.mangle ();
296- assert (!F->getModule ().hasFunction (MangledName));
297- return MangledName;
295+ return Mangler.mangle ();
298296}
299297
300298// / Convert all existential argument types to generic argument type.
@@ -642,41 +640,47 @@ void ExistentialTransform::populateThunkBody() {
642640// / its inline strategy as always inline.
643641void ExistentialTransform::createExistentialSpecializedFunction () {
644642 std::string Name = createExistentialSpecializedFunctionName ();
645- SILLinkage linkage = getSpecializedLinkage (F, F->getLinkage ());
646643
647- // / Create devirtualized function type.
644+ // / Create devirtualized function type and populate ArgToGenericTypeMap .
648645 auto NewFTy = createExistentialSpecializedFunctionType ();
649646
650- auto NewFGenericSig = NewFTy->getInvocationGenericSignature ();
651- auto NewFGenericEnv = NewFGenericSig->getGenericEnvironment ();
652-
653647 // / 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 (
655659 linkage, Name, NewFTy, NewFGenericEnv, F->getLocation (), F->isBare (),
656660 F->isTransparent (), F->isSerialized (), IsNotDynamic, F->getEntryCount (),
657661 F->isThunk (), F->getClassSubclassScope (), F->getInlineStrategy (),
658662 F->getEffectsKind (), nullptr , F->getDebugScope ());
659- // / Set the semantics attributes for the new function.
660- for (auto &Attr : F->getSemanticsAttrs ())
661- NewF->addSemanticsAttr (Attr);
662663
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);
667667
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 (
670674 NewFGenericSig,
671675 [&](SubstitutableType *type) -> Type {
672676 return NewFGenericEnv->mapTypeIntoContext (type);
673677 },
674678 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+ }
680684 // / Step 2: Create the thunk with always_inline and populate its body.
681685 populateThunkBody ();
682686
0 commit comments