Skip to content

Commit a75a7f2

Browse files
committed
Re-instate: "SILPassManager: After a new function is pushed on the stack don't restart the pipeline on the old function."
This re-instates commit de96226 The problem of the infinite loop should be fixed by the previous fix in FunctionSignatureOpts. In addition this new commit implements a safety check to void such cases, even if buggy optimizations try to keep pushing new functions onto the work list.
1 parent 759a05e commit a75a7f2

File tree

9 files changed

+169
-175
lines changed

9 files changed

+169
-175
lines changed

include/swift/SILOptimizer/PassManager/PassManager.h

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,21 @@ class SILPassManager {
4242
/// A list of registered analysis.
4343
llvm::SmallVector<SILAnalysis *, 16> Analysis;
4444

45+
/// An entry in the FunctionWorkList.
46+
struct WorklistEntry {
47+
WorklistEntry(SILFunction *F) : F(F) { }
48+
49+
SILFunction *F;
50+
51+
/// The current position in the transform-list.
52+
unsigned PipelineIdx = 0;
53+
54+
/// How many times the pipeline was restarted for the function.
55+
unsigned NumRestarts = 0;
56+
};
57+
4558
/// The worklist of functions to be processed by function passes.
46-
std::vector<SILFunction *> FunctionWorklist;
59+
std::vector<WorklistEntry> FunctionWorklist;
4760

4861
// Name of the current optimization stage for diagnostics.
4962
std::string StageName;
@@ -62,6 +75,13 @@ class SILPassManager {
6275
/// A completed-passes mask for each function.
6376
llvm::DenseMap<SILFunction *, CompletedPasses> CompletedPassesMap;
6477

78+
/// Stores for each function the number of levels of specializations it is
79+
/// derived from an original function. E.g. if a function is a signature
80+
/// optimized specialization of a generic specialiation, it has level 2.
81+
/// This is used to avoid an infinite amount of functions pushed on the
82+
/// worklist (e.g. caused by a bug in a specializing optimization).
83+
llvm::DenseMap<SILFunction *, int> DerivationLevels;
84+
6585
/// Set to true when a pass invalidates an analysis.
6686
bool CurrentPassHasInvalidated = false;
6787

@@ -96,13 +116,6 @@ class SILPassManager {
96116
/// \brief Run one iteration of the optimization pipeline.
97117
void runOneIteration();
98118

99-
/// \brief Add a function to the function pass worklist.
100-
void addFunctionToWorklist(SILFunction *F) {
101-
assert(F && F->isDefinition() && F->shouldOptimize() &&
102-
"Expected optimizable function definition!");
103-
FunctionWorklist.push_back(F);
104-
}
105-
106119
/// \brief Restart the function pass pipeline on the same function
107120
/// that is currently being processed.
108121
void restartWithCurrentFunction(SILTransform *T);
@@ -124,11 +137,12 @@ class SILPassManager {
124137
CompletedPassesMap.clear();
125138
}
126139

127-
/// \brief Add the function to the function pass worklist.
128-
void notifyTransformationOfFunction(SILFunction *F) {
129-
addFunctionToWorklist(F);
130-
}
131-
140+
/// \brief Add the function \p F to the function pass worklist.
141+
/// If not null, the function \p DerivedFrom is the function from which \p F
142+
/// is derived. This is used to avoid an infinite amount of functions pushed
143+
/// on the worklist (e.g. caused by a bug in a specializing optimization).
144+
void addFunctionToWorklist(SILFunction *F, SILFunction *DerivedFrom);
145+
132146
/// \brief Iterate over all analysis and notify them of the function.
133147
/// This function does not necessarily have to be newly created function. It
134148
/// is the job of the analysis to make sure no extra work is done if the
@@ -211,9 +225,8 @@ class SILPassManager {
211225
/// the module.
212226
void runModulePass(SILModuleTransform *SMT);
213227

214-
/// Run the passes in \p FuncTransforms on the function \p F.
215-
void runPassesOnFunction(PassList FuncTransforms, SILFunction *F,
216-
bool runToCompletion);
228+
/// Run the pass \p SFT on the function \p F.
229+
void runPassOnFunction(SILFunctionTransform *SFT, SILFunction *F);
217230

218231
/// Run the passes in \p FuncTransforms. Return true
219232
/// if the pass manager requested to stop the execution

include/swift/SILOptimizer/PassManager/Transforms.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,16 @@ namespace swift {
9696

9797
void injectFunction(SILFunction *Func) { F = Func; }
9898

99-
/// \brief Notify the pass manager of a function that needs to be
99+
/// \brief Notify the pass manager of a function \p F that needs to be
100100
/// processed by the function passes and the analyses.
101-
void notifyPassManagerOfFunction(SILFunction *F) {
102-
PM->notifyTransformationOfFunction(F);
101+
///
102+
/// If not null, the function \p DerivedFrom is the function from which \p F
103+
/// is derived. This is used to limit the number of new functions which are
104+
/// derived from a common base function, e.g. due to specialization.
105+
/// The number should be small anyway, but bugs in optimizations could cause
106+
/// an infinite loop in the passmanager.
107+
void notifyPassManagerOfFunction(SILFunction *F, SILFunction *DerivedFrom) {
108+
PM->addFunctionToWorklist(F, DerivedFrom);
103109
PM->notifyAnalysisOfFunction(F);
104110
}
105111

lib/SILOptimizer/IPO/CapturePropagation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ bool CapturePropagation::optimizePartialApply(PartialApplyInst *PAI) {
312312
SILFunction *NewF = specializeConstClosure(PAI, SubstF);
313313
rewritePartialApply(PAI, NewF);
314314

315-
notifyPassManagerOfFunction(NewF);
315+
notifyPassManagerOfFunction(NewF, SubstF);
316316
return true;
317317
}
318318

lib/SILOptimizer/IPO/ClosureSpecializer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,7 @@ bool ClosureSpecializer::specialize(SILFunction *Caller,
843843
// directly.
844844
if (!NewF) {
845845
NewF = ClosureSpecCloner::cloneFunction(CSDesc, NewFName);
846-
SFT->notifyPassManagerOfFunction(NewF);
846+
SFT->notifyPassManagerOfFunction(NewF, CSDesc.getApplyCallee());
847847
}
848848

849849
// Rewrite the call

0 commit comments

Comments
 (0)