Skip to content

Commit d6b432a

Browse files
authored
Merge pull request #17056 from eeckstein/fix-closure-specializer-4.2
2 parents 02150f1 + 0f5625d commit d6b432a

File tree

2 files changed

+62
-6
lines changed

2 files changed

+62
-6
lines changed

lib/SILOptimizer/IPO/ClosureSpecializer.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,7 @@ void ClosureSpecCloner::populateCloned() {
784784
namespace {
785785

786786
class SILClosureSpecializerTransform : public SILFunctionTransform {
787-
void gatherCallSites(SILFunction *Caller,
787+
bool gatherCallSites(SILFunction *Caller,
788788
llvm::SmallVectorImpl<ClosureInfo*> &ClosureCandidates,
789789
llvm::DenseSet<FullApplySite> &MultipleClosureAI);
790790
bool specialize(SILFunction *Caller,
@@ -839,7 +839,7 @@ void SILClosureSpecializerTransform::run() {
839839
invalidateAnalysis(SILAnalysis::InvalidationKind::Everything);
840840
}
841841

842-
void SILClosureSpecializerTransform::gatherCallSites(
842+
bool SILClosureSpecializerTransform::gatherCallSites(
843843
SILFunction *Caller,
844844
llvm::SmallVectorImpl<ClosureInfo*> &ClosureCandidates,
845845
llvm::DenseSet<FullApplySite> &MultipleClosureAI) {
@@ -848,6 +848,8 @@ void SILClosureSpecializerTransform::gatherCallSites(
848848
// make sure that we do not handle call sites with multiple closure arguments.
849849
llvm::DenseSet<FullApplySite> VisitedAI;
850850

851+
bool CFGChanged = false;
852+
851853
// For each basic block BB in Caller...
852854
for (auto &BB : *Caller) {
853855

@@ -918,7 +920,7 @@ void SILClosureSpecializerTransform::gatherCallSites(
918920
// We could fix this by inserting new arguments more carefully, or
919921
// changing how we model dynamic Self altogether.
920922
if (mayBindDynamicSelf(ApplyCallee))
921-
return;
923+
return CFGChanged;
922924

923925
// Ok, we know that we can perform the optimization but not whether or
924926
// not the optimization is profitable. Find the index of the argument
@@ -991,12 +993,15 @@ void SILClosureSpecializerTransform::gatherCallSites(
991993
}
992994
if (CInfo) {
993995
ValueLifetimeAnalysis VLA(CInfo->Closure, UsePoints);
994-
VLA.computeFrontier(CInfo->LifetimeFrontier,
995-
ValueLifetimeAnalysis::AllowToModifyCFG);
996+
if (!VLA.computeFrontier(CInfo->LifetimeFrontier,
997+
ValueLifetimeAnalysis::AllowToModifyCFG)) {
998+
CFGChanged = true;
999+
}
9961000
ClosureCandidates.push_back(CInfo);
9971001
}
9981002
}
9991003
}
1004+
return CFGChanged;
10001005
}
10011006

10021007
bool SILClosureSpecializerTransform::specialize(SILFunction *Caller,
@@ -1008,7 +1013,9 @@ bool SILClosureSpecializerTransform::specialize(SILFunction *Caller,
10081013
// ApplyInsts. Check the profitability of specializing the closure argument.
10091014
llvm::SmallVector<ClosureInfo*, 8> ClosureCandidates;
10101015
llvm::DenseSet<FullApplySite> MultipleClosureAI;
1011-
gatherCallSites(Caller, ClosureCandidates, MultipleClosureAI);
1016+
if (gatherCallSites(Caller, ClosureCandidates, MultipleClosureAI)) {
1017+
invalidateAnalysis(SILAnalysis::InvalidationKind::Branches);
1018+
}
10121019

10131020
bool Changed = false;
10141021
for (auto *CInfo : ClosureCandidates) {
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -sil-verify-without-invalidation -enable-sil-verify-all -loop-unroll -closure-specialize %s
2+
3+
// Test if the ClosureSpecializer correctly invalidates the dominator tree
4+
// even if there are no functions specialized.
5+
// The test just checks if the compiler does not crash.
6+
// First running LoopUnroll creates the dominator tree, which should then be
7+
// invalidated by the ClosureSpecializer.
8+
// If this is not done correctly the verification will complain that the
9+
// dominator tree is not up to date.
10+
11+
import Builtin
12+
import Swift
13+
14+
sil @closure : $@convention(thin) () -> ()
15+
16+
sil @use_closure : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
17+
18+
sil hidden [noinline] @use_closure2 : $@convention(thin) (@owned @callee_owned () -> (), @owned @callee_owned () -> ()) -> () {
19+
bb0(%0 : $@callee_owned () -> (), %1 : $@callee_owned () -> ()):
20+
%2 = apply %0() : $@callee_owned () -> ()
21+
%3 = apply %1() : $@callee_owned () -> ()
22+
%4 = tuple ()
23+
return %3 : $()
24+
}
25+
26+
sil @insert_release_in_liferange_exit_block : $@convention(thin) () -> () {
27+
bb0:
28+
%2 = function_ref @closure : $@convention(thin) () -> ()
29+
%3 = partial_apply %2() : $@convention(thin) () -> ()
30+
%8 = function_ref @use_closure : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
31+
%5 = partial_apply %8(%3) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
32+
33+
// There is a critical edge from bb0 to bb2 which is broken by ValueLifetimeAnalysis.
34+
cond_br undef, bb2, bb1
35+
36+
bb1:
37+
strong_retain %3 : $@callee_owned () -> ()
38+
strong_retain %3 : $@callee_owned () -> ()
39+
%10 = function_ref @use_closure2 : $@convention(thin) (@owned @callee_owned () -> (), @owned @callee_owned () -> ()) -> ()
40+
41+
// Passing two closures actually prevents closure specialization.
42+
%17 = apply %10(%3, %3) : $@convention(thin) (@owned @callee_owned () -> (), @owned @callee_owned () -> ()) -> ()
43+
br bb2
44+
45+
bb2:
46+
strong_release %5 : $@callee_owned () -> ()
47+
%11 = tuple ()
48+
return %11 : $()
49+
}

0 commit comments

Comments
 (0)