@@ -190,10 +190,7 @@ FunctionSignatureTransformDescriptor::createOptimizedSILFunctionName() {
190
190
Mangler.setReturnValueOwnedToUnowned ();
191
191
}
192
192
193
- auto MangledName = Mangler.mangle ();
194
- assert (!F->getModule ().hasFunction (MangledName));
195
-
196
- return MangledName;
193
+ return Mangler.mangle ();
197
194
}
198
195
199
196
// / Collect all archetypes used by a function.
@@ -483,6 +480,11 @@ void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
483
480
SILFunction *F = TransformDescriptor.OriginalFunction ;
484
481
SILModule &M = F->getModule ();
485
482
std::string Name = TransformDescriptor.createOptimizedSILFunctionName ();
483
+ // The transformed function must not already exist. This would indicate
484
+ // repeated application of FSO on the same function. That situation should be
485
+ // detected earlier by avoiding reoptimization of FSO thunks.
486
+ assert (!F->getModule ().hasFunction (Name));
487
+
486
488
SILLinkage linkage = getSpecializedLinkage (F, F->getLinkage ());
487
489
488
490
LLVM_DEBUG (llvm::dbgs () << " -> create specialized function " << Name
@@ -617,6 +619,19 @@ bool FunctionSignatureTransform::run(bool hasCaller) {
617
619
bool Changed = false ;
618
620
SILFunction *F = TransformDescriptor.OriginalFunction ;
619
621
622
+ // Never repeat the same function signature optimization on the same function.
623
+ // Multiple function signature optimizations are composed by successively
624
+ // optmizing the newly created functions. Each optimization creates a new
625
+ // level of thunk. Those should all be ultimately inlined away.
626
+ //
627
+ // This happens, for example, when a new reference to the original function is
628
+ // discovered during devirtualization. That will cause the original function
629
+ // (now and FSO thunk) to be pushed back on the function pass pipeline.
630
+ if (F->isThunk () == IsSignatureOptimizedThunk) {
631
+ LLVM_DEBUG (llvm::dbgs () << " FSO already performed on this thunk\n " );
632
+ return false ;
633
+ }
634
+
620
635
if (!hasCaller && canBeCalledIndirectly (F->getRepresentation ())) {
621
636
LLVM_DEBUG (llvm::dbgs () << " function has no caller -> abort\n " );
622
637
return false ;
0 commit comments