Skip to content

Commit 958dd97

Browse files
committed
Prevent FunctionSignatureOptimization from rerunning on its own thunk.
This is a bug fix that just bails out of FSO, which is exactly what we should be doing in this case anyway. This issue will be exposed in stdlib builds once I fix another bug in the passmanager. Once the pass pipeline restart works as intended, we will perform FSO on `F`, then devirtualization will discover a new reference to `F`, causing it to be pushed back on the function pass pipeline.
1 parent d61a80a commit 958dd97

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,7 @@ FunctionSignatureTransformDescriptor::createOptimizedSILFunctionName() {
190190
Mangler.setReturnValueOwnedToUnowned();
191191
}
192192

193-
auto MangledName = Mangler.mangle();
194-
assert(!F->getModule().hasFunction(MangledName));
195-
196-
return MangledName;
193+
return Mangler.mangle();
197194
}
198195

199196
/// Collect all archetypes used by a function.
@@ -483,6 +480,11 @@ void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
483480
SILFunction *F = TransformDescriptor.OriginalFunction;
484481
SILModule &M = F->getModule();
485482
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+
486488
SILLinkage linkage = getSpecializedLinkage(F, F->getLinkage());
487489

488490
LLVM_DEBUG(llvm::dbgs() << " -> create specialized function " << Name
@@ -617,6 +619,19 @@ bool FunctionSignatureTransform::run(bool hasCaller) {
617619
bool Changed = false;
618620
SILFunction *F = TransformDescriptor.OriginalFunction;
619621

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+
620635
if (!hasCaller && canBeCalledIndirectly(F->getRepresentation())) {
621636
LLVM_DEBUG(llvm::dbgs() << " function has no caller -> abort\n");
622637
return false;

lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,9 +1191,8 @@ class COWArrayOptPass : public SILFunctionTransform {
11911191
for (auto *L : Loops)
11921192
HasChanged |= COWArrayOpt(RCIA, L, DA).run();
11931193

1194-
if (HasChanged) {
1195-
invalidateAnalysis(SILAnalysis::InvalidationKind::CallsAndInstructions);
1196-
}
1194+
if (HasChanged)
1195+
invalidateAnalysis(SILAnalysis::InvalidationKind::CallsAndInstructions);
11971196
}
11981197

11991198
};

0 commit comments

Comments
 (0)