SIL optimizations: Implement the new API for analysis invalidation.

There are now separate functions for function addition and deletion instead of InvalidationKind::Function.
Also, there is a new function for witness/vtable invalidations.

rdar://problem/29311657
This commit is contained in:
Erik Eckstein
2017-03-14 10:51:50 -07:00
parent ef4b5e1efe
commit a0079ba5be
31 changed files with 309 additions and 166 deletions

View File

@@ -263,15 +263,24 @@ public:
/// Encodes the memory behavior query as a MemBehaviorKeyTy. /// Encodes the memory behavior query as a MemBehaviorKeyTy.
MemBehaviorKeyTy toMemoryBehaviorKey(SILValue V1, SILValue V2, RetainObserveKind K); MemBehaviorKeyTy toMemoryBehaviorKey(SILValue V1, SILValue V2, RetainObserveKind K);
virtual void invalidate(SILAnalysis::InvalidationKind K) override { virtual void invalidate() override {
AliasCache.clear(); AliasCache.clear();
MemoryBehaviorCache.clear(); MemoryBehaviorCache.clear();
} }
virtual void invalidate(SILFunction *, virtual void invalidate(SILFunction *,
SILAnalysis::InvalidationKind K) override { SILAnalysis::InvalidationKind K) override {
invalidate(K); invalidate();
} }
/// Notify the analysis about a newly created function.
virtual void notifyAddFunction(SILFunction *F) override { }
/// Notify the analysis about a function which will be deleted from the
/// module.
virtual void notifyDeleteFunction(SILFunction *F) override { }
virtual void invalidateFunctionTables() override { }
}; };

View File

@@ -55,13 +55,6 @@ namespace swift {
/// has been modified. /// has been modified.
Branches = 0x4, Branches = 0x4,
/// The pass delete or created new functions.
///
/// The intent behind this is so that analyses that cache
/// SILFunction* to be able to be invalidated and later
/// recomputed so that they are not holding dangling pointers.
Functions = 0x8,
/// Convenience states: /// Convenience states:
FunctionBody = Calls | Branches | Instructions, FunctionBody = Calls | Branches | Instructions,
@@ -69,7 +62,7 @@ namespace swift {
BranchesAndInstructions = Branches | Instructions, BranchesAndInstructions = Branches | Instructions,
Everything = Functions | Calls | Branches | Instructions, Everything = Calls | Branches | Instructions,
}; };
/// A list of the known analysis. /// A list of the known analysis.
@@ -112,22 +105,20 @@ namespace swift {
bool isLocked() { return invalidationLock; } bool isLocked() { return invalidationLock; }
/// Invalidate all information in this analysis. /// Invalidate all information in this analysis.
virtual void invalidate(InvalidationKind K) {} virtual void invalidate() = 0;
/// Invalidate all of the information for a specific function. /// Invalidate all of the information for a specific function.
virtual void invalidate(SILFunction *F, InvalidationKind K) {} virtual void invalidate(SILFunction *F, InvalidationKind K) = 0;
/// Invalidate all of the information for a specific function. Also, we
/// know that this function is a dead function and going to be deleted from
/// the module.
virtual void invalidateForDeadFunction(SILFunction *F, InvalidationKind K) {
// Call the normal invalidate function unless overridden by specific
// analysis.
invalidate(F, K);
}
/// Notify the analysis about a newly created function. /// Notify the analysis about a newly created function.
virtual void notifyAnalysisOfFunction(SILFunction *F) {} virtual void notifyAddFunction(SILFunction *F) = 0;
/// Notify the analysis about a function which will be deleted from the
/// module.
virtual void notifyDeleteFunction(SILFunction *F) = 0;
/// Notify the analysis about changed witness or vtables.
virtual void invalidateFunctionTables() = 0;
/// Verify the state of this analysis. /// Verify the state of this analysis.
virtual void verify() const {} virtual void verify() const {}
@@ -190,19 +181,13 @@ namespace swift {
return it.second; return it.second;
} }
virtual void invalidate(SILAnalysis::InvalidationKind K) override { /// Invalidate all information in this analysis.
if (!shouldInvalidate(K)) return; virtual void invalidate() override {
for (auto D : Storage)
delete D.second;
Storage.clear(); Storage.clear();
} }
virtual void invalidate(SILFunction *F, /// Helper function to remove the analysis data for a function.
SILAnalysis::InvalidationKind K) override { void invalidateFunction(SILFunction *F) {
if (!shouldInvalidate(K)) return;
auto &it = Storage.FindAndConstruct(F); auto &it = Storage.FindAndConstruct(F);
if (it.second) { if (it.second) {
delete it.second; delete it.second;
@@ -210,6 +195,25 @@ namespace swift {
} }
} }
/// Invalidate all of the information for a specific function.
virtual void invalidate(SILFunction *F,
SILAnalysis::InvalidationKind K) override {
if (shouldInvalidate(K))
invalidateFunction(F);
}
/// Notify the analysis about a newly created function.
virtual void notifyAddFunction(SILFunction *F) override { }
/// Notify the analysis about a function which will be deleted from the
/// module.
virtual void notifyDeleteFunction(SILFunction *F) override {
invalidateFunction(F);
}
/// Notify the analysis about changed witness or vtables.
virtual void invalidateFunctionTables() override { }
FunctionAnalysisBase() {} FunctionAnalysisBase() {}
virtual ~FunctionAnalysisBase() { virtual ~FunctionAnalysisBase() {
for (auto D : Storage) for (auto D : Storage)

View File

@@ -132,12 +132,25 @@ public:
return S->getKind() == AnalysisKind::BasicCallee; return S->getKind() == AnalysisKind::BasicCallee;
} }
virtual void invalidate(SILAnalysis::InvalidationKind K) { /// Invalidate all information in this analysis.
if (K & InvalidationKind::Functions) virtual void invalidate() override {
Cache.reset(); Cache.reset();
} }
virtual void invalidate(SILFunction *F, InvalidationKind K) { invalidate(K); } /// Invalidate all of the information for a specific function.
virtual void invalidate(SILFunction *F, InvalidationKind K) override { }
/// Notify the analysis about a newly created function.
virtual void notifyAddFunction(SILFunction *F) override { }
/// Notify the analysis about a function which will be deleted from the
/// module.
virtual void notifyDeleteFunction(SILFunction *F) override { };
/// Notify the analysis about changed witness or vtables.
virtual void invalidateFunctionTables() override {
Cache.reset();
}
CalleeList getCalleeList(FullApplySite FAS) { CalleeList getCalleeList(FullApplySite FAS) {
if (!Cache) if (!Cache)

View File

@@ -121,11 +121,17 @@ public:
return S->getKind() == AnalysisKind::Caller; return S->getKind() == AnalysisKind::Caller;
} }
virtual void notifyAnalysisOfFunction(SILFunction *F) { /// Invalidate all information in this analysis.
RecomputeFunctionList.insert(F); virtual void invalidate() override {
FuncInfos.clear();
RecomputeFunctionList.clear();
for (auto &F : Mod) {
RecomputeFunctionList.insert(&F);
}
} }
virtual void invalidate(SILFunction *F, InvalidationKind K) { /// Invalidate all of the information for a specific function.
virtual void invalidate(SILFunction *F, InvalidationKind K) override {
// Should we invalidate based on the invalidation kind. // Should we invalidate based on the invalidation kind.
bool shouldInvalidate = K & InvalidationKind::CallsAndInstructions; bool shouldInvalidate = K & InvalidationKind::CallsAndInstructions;
if (!shouldInvalidate) if (!shouldInvalidate)
@@ -138,23 +144,20 @@ public:
RecomputeFunctionList.insert(F); RecomputeFunctionList.insert(F);
} }
virtual void invalidateForDeadFunction(SILFunction *F, InvalidationKind K) { /// Notify the analysis about a newly created function.
virtual void notifyAddFunction(SILFunction *F) override {
RecomputeFunctionList.insert(F);
}
/// Notify the analysis about a function which will be deleted from the
/// module.
virtual void notifyDeleteFunction(SILFunction *F) override {
invalidateExistingCalleeRelation(F); invalidateExistingCalleeRelation(F);
RecomputeFunctionList.remove(F); RecomputeFunctionList.remove(F);
} }
virtual void invalidate(InvalidationKind K) { /// Notify the analysis about changed witness or vtables.
// Should we invalidate based on the invalidation kind. virtual void invalidateFunctionTables() override { }
bool shouldInvalidate = K & InvalidationKind::Calls;
if (!shouldInvalidate)
return;
FuncInfos.clear();
RecomputeFunctionList.clear();
for (auto &F : Mod) {
RecomputeFunctionList.insert(&F);
}
}
const FunctionInfo &getCallerInfo(SILFunction *F) { const FunctionInfo &getCallerInfo(SILFunction *F) {
// Recompute every function in the invalidated function list and empty the // Recompute every function in the invalidated function list and empty the

View File

@@ -44,10 +44,24 @@ public:
return S->getKind() == AnalysisKind::ClassHierarchy; return S->getKind() == AnalysisKind::ClassHierarchy;
} }
virtual void invalidate(SILAnalysis::InvalidationKind K) { /// Invalidate all information in this analysis.
// Nothing can invalidate the ClassHierarchyAnalysis! virtual void invalidate() override {
// Nothing can invalidate, because types are static and cannot be changed
// during the SIL pass pipeline.
} }
/// Invalidate all of the information for a specific function.
virtual void invalidate(SILFunction *F, InvalidationKind K) override { }
/// Notify the analysis about a newly created function.
virtual void notifyAddFunction(SILFunction *F) override { }
/// Notify the analysis about a function which will be deleted from the
/// module.
virtual void notifyDeleteFunction(SILFunction *F) override { }
/// Notify the analysis about changed witness or vtables.
virtual void invalidateFunctionTables() override { }
/// Returns a list of the known direct subclasses of a class \p C in /// Returns a list of the known direct subclasses of a class \p C in
/// the current module. /// the current module.
@@ -87,10 +101,6 @@ public:
return ProtocolImplementationsCache.count(C); return ProtocolImplementationsCache.count(C);
} }
virtual void invalidate(SILFunction *F, SILAnalysis::InvalidationKind K) {
invalidate(K);
}
private: private:
/// Compute inheritance properties. /// Compute inheritance properties.
void init(); void init();

View File

@@ -34,6 +34,22 @@ public:
/// Returns true if destruction of T may store to memory. /// Returns true if destruction of T may store to memory.
bool mayStoreToMemoryOnDestruction(SILType T); bool mayStoreToMemoryOnDestruction(SILType T);
/// No invalidation is needed.
virtual void invalidate() override { }
/// No invalidation is needed.
virtual void invalidate(SILFunction *F, InvalidationKind K) override { }
/// Notify the analysis about a newly created function.
virtual void notifyAddFunction(SILFunction *F) override { }
/// Notify the analysis about a function which will be deleted from the
/// module.
virtual void notifyDeleteFunction(SILFunction *F) override { }
/// Notify the analysis about changed witness or vtables.
virtual void invalidateFunctionTables() override { }
protected: protected:
bool cacheResult(CanType Type, bool Result); bool cacheResult(CanType Type, bool Result);
bool isSafeType(CanType Ty); bool isSafeType(CanType Ty);

View File

@@ -791,10 +791,24 @@ public:
/// node, the pointers do not alias. /// node, the pointers do not alias.
bool canPointToSameMemory(SILValue V1, SILValue V2); bool canPointToSameMemory(SILValue V1, SILValue V2);
virtual void invalidate(InvalidationKind K) override; /// Invalidate all information in this analysis.
virtual void invalidate() override;
/// Invalidate all of the information for a specific function.
virtual void invalidate(SILFunction *F, InvalidationKind K) override; virtual void invalidate(SILFunction *F, InvalidationKind K) override;
/// Notify the analysis about a newly created function.
virtual void notifyAddFunction(SILFunction *F) override { }
/// Notify the analysis about a function which will be deleted from the
/// module.
virtual void notifyDeleteFunction(SILFunction *F) override {
invalidate(F, InvalidationKind::Nothing);
}
/// Notify the analysis about changed witness or vtables.
virtual void invalidateFunctionTables() override { }
virtual void handleDeleteNotification(ValueBase *I) override; virtual void handleDeleteNotification(ValueBase *I) override;
virtual bool needsNotifications() override { return true; } virtual bool needsNotifications() override { return true; }

View File

@@ -379,11 +379,23 @@ public:
/// Get the side-effects of a call site. /// Get the side-effects of a call site.
void getEffects(FunctionEffects &ApplyEffects, FullApplySite FAS); void getEffects(FunctionEffects &ApplyEffects, FullApplySite FAS);
/// No invalidation is needed. See comment for SideEffectAnalysis. /// Invalidate all information in this analysis.
virtual void invalidate(InvalidationKind K) override; virtual void invalidate() override;
/// No invalidation is needed. See comment for SideEffectAnalysis. /// Invalidate all of the information for a specific function.
virtual void invalidate(SILFunction *F, InvalidationKind K) override; virtual void invalidate(SILFunction *F, InvalidationKind K) override;
/// Notify the analysis about a newly created function.
virtual void notifyAddFunction(SILFunction *F) override { }
/// Notify the analysis about a function which will be deleted from the
/// module.
virtual void notifyDeleteFunction(SILFunction *F) override {
invalidate(F, InvalidationKind::Nothing);
}
/// Notify the analysis about changed witness or vtables.
virtual void invalidateFunctionTables() override { }
}; };
} // end namespace swift } // end namespace swift

View File

@@ -33,6 +33,25 @@ public:
/// Return ProjectionPath to every leaf or intermediate node of the given type. /// Return ProjectionPath to every leaf or intermediate node of the given type.
const ProjectionPathList &getTypeExpansion(SILType B, SILModule *Mod); const ProjectionPathList &getTypeExpansion(SILType B, SILModule *Mod);
/// Invalidate all information in this analysis.
virtual void invalidate() override {
// Nothing can invalidate, because types are static and cannot be changed
// during the SIL pass pipeline.
}
/// Invalidate all of the information for a specific function.
virtual void invalidate(SILFunction *F, InvalidationKind K) override { }
/// Notify the analysis about a newly created function.
virtual void notifyAddFunction(SILFunction *F) override { }
/// Notify the analysis about a function which will be deleted from the
/// module.
virtual void notifyDeleteFunction(SILFunction *F) override { }
/// Notify the analysis about changed witness or vtables.
virtual void invalidateFunctionTables() override { }
}; };
} }

View File

@@ -140,14 +140,12 @@ public:
void clearRestartPipeline() { RestartPipeline = false; } void clearRestartPipeline() { RestartPipeline = false; }
bool shouldRestartPipeline() { return RestartPipeline; } bool shouldRestartPipeline() { return RestartPipeline; }
/// \brief Broadcast the invalidation of the module to all analysis. /// \brief Iterate over all analysis and invalidate them.
void invalidateAnalysis(SILAnalysis::InvalidationKind K) { void invalidateAllAnalysis() {
assert(K != SILAnalysis::InvalidationKind::Nothing && // Invalidate the analysis (unless they are locked)
"Invalidation call must invalidate some trait");
for (auto AP : Analysis) for (auto AP : Analysis)
if (!AP->isLocked()) if (!AP->isLocked())
AP->invalidate(K); AP->invalidate();
CurrentPassHasInvalidated = true; CurrentPassHasInvalidated = true;
@@ -167,7 +165,7 @@ public:
/// particular analysis has been done on the function. /// particular analysis has been done on the function.
void notifyAnalysisOfFunction(SILFunction *F) { void notifyAnalysisOfFunction(SILFunction *F) {
for (auto AP : Analysis) for (auto AP : Analysis)
AP->notifyAnalysisOfFunction(F); AP->notifyAddFunction(F);
} }
/// \brief Broadcast the invalidation of the function to all analysis. /// \brief Broadcast the invalidation of the function to all analysis.
@@ -183,15 +181,26 @@ public:
CompletedPassesMap[F].reset(); CompletedPassesMap[F].reset();
} }
/// \brief Broadcast the invalidation of the function to all analysis. /// \brief Iterate over all analysis and notify them of a change in witness-
/// And we also know this function is dead and will be removed from the /// or vtables.
/// module. void invalidateFunctionTables() {
void invalidateAnalysisForDeadFunction(SILFunction *F,
SILAnalysis::InvalidationKind K) {
// Invalidate the analysis (unless they are locked) // Invalidate the analysis (unless they are locked)
for (auto AP : Analysis) for (auto AP : Analysis)
if (!AP->isLocked()) if (!AP->isLocked())
AP->invalidateForDeadFunction(F, K); AP->invalidateFunctionTables();
CurrentPassHasInvalidated = true;
// Assume that all functions have changed. Clear all masks of all functions.
CompletedPassesMap.clear();
}
/// \brief Iterate over all analysis and notify them of a deleted function.
void notifyDeleteFunction(SILFunction *F) {
// Invalidate the analysis (unless they are locked)
for (auto AP : Analysis)
if (!AP->isLocked())
AP->notifyDeleteFunction(F);
CurrentPassHasInvalidated = true; CurrentPassHasInvalidated = true;
// Any change let all passes run again. // Any change let all passes run again.

View File

@@ -22,6 +22,7 @@
namespace swift { namespace swift {
class SILOptions; class SILOptions;
class SILTransform; class SILTransform;
class SILModuleTransform;
namespace irgen { namespace irgen {
class IRGenModule; class IRGenModule;
@@ -46,7 +47,7 @@ namespace swift {
/// \brief Detect and remove unreachable code. Diagnose provably unreachable /// \brief Detect and remove unreachable code. Diagnose provably unreachable
/// user code. /// user code.
void performSILDiagnoseUnreachable(SILModule *M); void performSILDiagnoseUnreachable(SILModule *M, SILModuleTransform *T);
/// \brief Remove dead functions from \p M. /// \brief Remove dead functions from \p M.
void performSILDeadFunctionElimination(SILModule *M); void performSILDeadFunctionElimination(SILModule *M);

View File

@@ -104,7 +104,7 @@ namespace swift {
/// derived from a common base function, e.g. due to specialization. /// derived from a common base function, e.g. due to specialization.
/// The number should be small anyway, but bugs in optimizations could cause /// The number should be small anyway, but bugs in optimizations could cause
/// an infinite loop in the passmanager. /// an infinite loop in the passmanager.
void notifyPassManagerOfFunction(SILFunction *F, SILFunction *DerivedFrom) { void notifyAddFunction(SILFunction *F, SILFunction *DerivedFrom) {
PM->addFunctionToWorklist(F, DerivedFrom); PM->addFunctionToWorklist(F, DerivedFrom);
PM->notifyAnalysisOfFunction(F); PM->notifyAnalysisOfFunction(F);
} }
@@ -146,10 +146,9 @@ namespace swift {
SILModule *getModule() { return M; } SILModule *getModule() { return M; }
/// Invalidate all of functions in the module, using invalidation /// Invalidate all analsysis data for the whole module.
/// information \p K. void invalidateAll() {
void invalidateAnalysis(SILAnalysis::InvalidationKind K) { PM->invalidateAllAnalysis();
PM->invalidateAnalysis(K);
} }
/// Invalidate only the function \p F, using invalidation information \p K. /// Invalidate only the function \p F, using invalidation information \p K.
@@ -157,11 +156,19 @@ namespace swift {
PM->invalidateAnalysis(F, K); PM->invalidateAnalysis(F, K);
} }
/// Invalidate only the function \p F, using invalidation information \p K. /// Invalidate the analysis data for witness- and vtables.
/// But we also know this function is going to be dead. void invalidateFunctionTables() {
void invalidateAnalysisForDeadFunction(SILFunction *F, PM->invalidateFunctionTables();
SILAnalysis::InvalidationKind K) { }
PM->invalidateAnalysisForDeadFunction(F, K);
/// Inform the pass manager of a deleted function.
void notifyDeleteFunction(SILFunction *F) {
PM->notifyDeleteFunction(F);
}
/// Inform the pass manager of an added function.
void notifyAddFunction(SILFunction *F) {
PM->notifyAnalysisOfFunction(F);
} }
}; };
} // end namespace swift } // end namespace swift

View File

@@ -1953,7 +1953,7 @@ bool EscapeAnalysis::canParameterEscape(FullApplySite FAS, int ParamIdx,
return false; return false;
} }
void EscapeAnalysis::invalidate(InvalidationKind K) { void EscapeAnalysis::invalidate() {
Function2Info.clear(); Function2Info.clear();
Allocator.DestroyAll(); Allocator.DestroyAll();
DEBUG(llvm::dbgs() << "invalidate all\n"); DEBUG(llvm::dbgs() << "invalidate all\n");

View File

@@ -515,7 +515,7 @@ void SideEffectAnalysis::getEffects(FunctionEffects &ApplyEffects, FullApplySite
} }
} }
void SideEffectAnalysis::invalidate(InvalidationKind K) { void SideEffectAnalysis::invalidate() {
Function2Info.clear(); Function2Info.clear();
Allocator.DestroyAll(); Allocator.DestroyAll();
DEBUG(llvm::dbgs() << "invalidate all\n"); DEBUG(llvm::dbgs() << "invalidate all\n");

View File

@@ -851,7 +851,7 @@ constructClonedFunction(PartialApplyInst *PAI, FunctionRefInst *FRI,
/// with a partial_apply of the new closure, fixing up reference counting as /// with a partial_apply of the new closure, fixing up reference counting as
/// necessary. Also, if the closure is cloned, the cloned function is added to /// necessary. Also, if the closure is cloned, the cloned function is added to
/// the worklist. /// the worklist.
static void static SILFunction *
processPartialApplyInst(PartialApplyInst *PAI, IndicesSet &PromotableIndices, processPartialApplyInst(PartialApplyInst *PAI, IndicesSet &PromotableIndices,
SmallVectorImpl<SILFunction*> &Worklist) { SmallVectorImpl<SILFunction*> &Worklist) {
SILModule &M = PAI->getModule(); SILModule &M = PAI->getModule();
@@ -934,6 +934,7 @@ processPartialApplyInst(PartialApplyInst *PAI, IndicesSet &PromotableIndices,
// TODO: If this is the last use of the closure, and if it has internal // TODO: If this is the last use of the closure, and if it has internal
// linkage, we should remove it from the SILModule now. // linkage, we should remove it from the SILModule now.
} }
return ClonedFn;
} }
static void static void
@@ -961,19 +962,6 @@ constructMapFromPartialApplyToPromotableIndices(SILFunction *F,
} }
} }
static void
processFunction(SILFunction *F, SmallVectorImpl<SILFunction*> &Worklist) {
// This is a map from each partial apply to a set of indices of promotable
// box variables.
PartialApplyIndicesMap IndicesMap;
constructMapFromPartialApplyToPromotableIndices(F, IndicesMap);
// Do the actual promotions; all promotions on a single partial_apply are
// handled together.
for (auto &IndicesPair : IndicesMap)
processPartialApplyInst(IndicesPair.first, IndicesPair.second, Worklist);
}
namespace { namespace {
class CapturePromotionPass : public SILModuleTransform { class CapturePromotionPass : public SILModuleTransform {
/// The entry point to the transformation. /// The entry point to the transformation.
@@ -983,17 +971,35 @@ class CapturePromotionPass : public SILModuleTransform {
processFunction(&F, Worklist); processFunction(&F, Worklist);
if (!Worklist.empty()) { if (!Worklist.empty()) {
invalidateAnalysis(SILAnalysis::InvalidationKind::Everything);
} }
while (!Worklist.empty()) while (!Worklist.empty())
processFunction(Worklist.pop_back_val(), Worklist); processFunction(Worklist.pop_back_val(), Worklist);
} }
void processFunction(SILFunction *F, SmallVectorImpl<SILFunction*> &Worklist);
StringRef getName() override { return "Capture Promotion"; } StringRef getName() override { return "Capture Promotion"; }
}; };
} // end anonymous namespace } // end anonymous namespace
void CapturePromotionPass::processFunction(SILFunction *F,
SmallVectorImpl<SILFunction*> &Worklist) {
// This is a map from each partial apply to a set of indices of promotable
// box variables.
PartialApplyIndicesMap IndicesMap;
constructMapFromPartialApplyToPromotableIndices(F, IndicesMap);
// Do the actual promotions; all promotions on a single partial_apply are
// handled together.
for (auto &IndicesPair : IndicesMap) {
PartialApplyInst *PAI = IndicesPair.first;
SILFunction *ClonedFn = processPartialApplyInst(PAI, IndicesPair.second,
Worklist);
notifyAddFunction(ClonedFn);
}
invalidateAnalysis(F, SILAnalysis::InvalidationKind::Everything);
}
SILTransform *swift::createCapturePromotion() { SILTransform *swift::createCapturePromotion() {
return new CapturePromotionPass(); return new CapturePromotionPass();

View File

@@ -416,7 +416,7 @@ bool CapturePropagation::optimizePartialApply(PartialApplyInst *PAI) {
SILFunction *NewF = specializeConstClosure(PAI, SubstF); SILFunction *NewF = specializeConstClosure(PAI, SubstF);
rewritePartialApply(PAI, NewF); rewritePartialApply(PAI, NewF);
notifyPassManagerOfFunction(NewF, SubstF); notifyAddFunction(NewF, SubstF);
return true; return true;
} }

View File

@@ -885,7 +885,7 @@ bool SILClosureSpecializerTransform::specialize(SILFunction *Caller,
// directly. // directly.
if (!NewF) { if (!NewF) {
NewF = ClosureSpecCloner::cloneFunction(CSDesc, NewFName); NewF = ClosureSpecCloner::cloneFunction(CSDesc, NewFName);
notifyPassManagerOfFunction(NewF, CSDesc.getApplyCallee()); notifyAddFunction(NewF, CSDesc.getApplyCallee());
} }
// Rewrite the call // Rewrite the call

View File

@@ -590,12 +590,15 @@ class DeadFunctionElimination : FunctionLivenessComputation {
} }
/// Removes all dead methods from vtables and witness tables. /// Removes all dead methods from vtables and witness tables.
void removeDeadEntriesFromTables() { bool removeDeadEntriesFromTables() {
bool changedTable = false;
for (SILVTable &vTable : Module->getVTableList()) { for (SILVTable &vTable : Module->getVTableList()) {
vTable.removeEntries_if([this](SILVTable::Entry &entry) -> bool { vTable.removeEntries_if([this, &changedTable]
(SILVTable::Entry &entry) -> bool {
if (!isAlive(entry.Implementation)) { if (!isAlive(entry.Implementation)) {
DEBUG(llvm::dbgs() << " erase dead vtable method " << DEBUG(llvm::dbgs() << " erase dead vtable method " <<
entry.Implementation->getName() << "\n"); entry.Implementation->getName() << "\n");
changedTable = true;
return true; return true;
} }
return false; return false;
@@ -606,10 +609,12 @@ class DeadFunctionElimination : FunctionLivenessComputation {
for (auto WI = WitnessTables.begin(), EI = WitnessTables.end(); WI != EI;) { for (auto WI = WitnessTables.begin(), EI = WitnessTables.end(); WI != EI;) {
SILWitnessTable *WT = &*WI; SILWitnessTable *WT = &*WI;
WI++; WI++;
WT->clearMethods_if([this](const SILWitnessTable::MethodWitness &MW) -> bool { WT->clearMethods_if([this, &changedTable]
(const SILWitnessTable::MethodWitness &MW) -> bool {
if (!isAlive(MW.Witness)) { if (!isAlive(MW.Witness)) {
DEBUG(llvm::dbgs() << " erase dead witness method " << DEBUG(llvm::dbgs() << " erase dead witness method " <<
MW.Witness->getName() << "\n"); MW.Witness->getName() << "\n");
changedTable = true;
return true; return true;
} }
return false; return false;
@@ -622,17 +627,19 @@ class DeadFunctionElimination : FunctionLivenessComputation {
WI != EI;) { WI != EI;) {
SILDefaultWitnessTable *WT = &*WI; SILDefaultWitnessTable *WT = &*WI;
WI++; WI++;
WT->clearMethods_if([this](SILFunction *MW) -> bool { WT->clearMethods_if([this, &changedTable](SILFunction *MW) -> bool {
if (!MW) if (!MW)
return false; return false;
if (!isAlive(MW)) { if (!isAlive(MW)) {
DEBUG(llvm::dbgs() << " erase dead default witness method " DEBUG(llvm::dbgs() << " erase dead default witness method "
<< MW->getName() << "\n"); << MW->getName() << "\n");
changedTable = true;
return true; return true;
} }
return false; return false;
}); });
} }
return changedTable;
} }
public: public:
@@ -645,7 +652,7 @@ public:
DEBUG(llvm::dbgs() << "running dead function elimination\n"); DEBUG(llvm::dbgs() << "running dead function elimination\n");
findAliveFunctions(); findAliveFunctions();
removeDeadEntriesFromTables(); bool changedTables = removeDeadEntriesFromTables();
// First drop all references so that we don't get problems with non-zero // First drop all references so that we don't get problems with non-zero
// reference counts of dead functions. // reference counts of dead functions.
@@ -670,16 +677,17 @@ public:
} }
// Last step: delete all dead functions. // Last step: delete all dead functions.
auto InvalidateEverything = SILAnalysis::InvalidationKind::Everything;
while (!DeadFunctions.empty()) { while (!DeadFunctions.empty()) {
SILFunction *F = DeadFunctions.back(); SILFunction *F = DeadFunctions.back();
DeadFunctions.pop_back(); DeadFunctions.pop_back();
DEBUG(llvm::dbgs() << " erase dead function " << F->getName() << "\n"); DEBUG(llvm::dbgs() << " erase dead function " << F->getName() << "\n");
NumDeadFunc++; NumDeadFunc++;
DFEPass->invalidateAnalysisForDeadFunction(F, InvalidateEverything); DFEPass->notifyDeleteFunction(F);
Module->eraseFunction(F); Module->eraseFunction(F);
} }
if (changedTables)
DFEPass->invalidateFunctionTables();
} }
}; };
@@ -839,8 +847,7 @@ public:
// Do not remove bodies of any functions that are alive. // Do not remove bodies of any functions that are alive.
if (!isAlive(F)) { if (!isAlive(F)) {
if (tryToConvertExternalDefinitionIntoDeclaration(F)) { if (tryToConvertExternalDefinitionIntoDeclaration(F)) {
DFEPass->invalidateAnalysisForDeadFunction(F, DFEPass->notifyDeleteFunction(F);
SILAnalysis::InvalidationKind::Everything);
if (F->getRefCount() == 0) if (F->getRefCount() == 0)
F->getModule().eraseFunction(F); F->getModule().eraseFunction(F);
} }

View File

@@ -719,7 +719,6 @@ void EagerSpecializerTransform::run() {
return; return;
// Process functions in any order. // Process functions in any order.
bool Changed = false;
for (auto &F : *getModule()) { for (auto &F : *getModule()) {
if (!F.shouldOptimize()) { if (!F.shouldOptimize()) {
DEBUG(dbgs() << " Cannot specialize function " << F.getName() DEBUG(dbgs() << " Cannot specialize function " << F.getName()
@@ -744,6 +743,7 @@ void EagerSpecializerTransform::run() {
auto AttrRequirements = SA->getRequirements(); auto AttrRequirements = SA->getRequirements();
ReInfoVec.emplace_back(&F, AttrRequirements); ReInfoVec.emplace_back(&F, AttrRequirements);
auto *NewFunc = eagerSpecialize(&F, *SA, ReInfoVec.back()); auto *NewFunc = eagerSpecialize(&F, *SA, ReInfoVec.back());
notifyAddFunction(NewFunc);
SpecializedFuncs.push_back(NewFunc); SpecializedFuncs.push_back(NewFunc);
@@ -755,6 +755,7 @@ void EagerSpecializerTransform::run() {
// TODO: Optimize the dispatch code to minimize the amount // TODO: Optimize the dispatch code to minimize the amount
// of checks. Use decision trees for this purpose. // of checks. Use decision trees for this purpose.
bool Changed = false;
for_each3(F.getSpecializeAttrs(), SpecializedFuncs, ReInfoVec, for_each3(F.getSpecializeAttrs(), SpecializedFuncs, ReInfoVec,
[&](const SILSpecializeAttr *SA, SILFunction *NewFunc, [&](const SILSpecializeAttr *SA, SILFunction *NewFunc,
const ReabstractionInfo &ReInfo) { const ReabstractionInfo &ReInfo) {
@@ -763,14 +764,14 @@ void EagerSpecializerTransform::run() {
EagerDispatch(&F, ReInfo).emitDispatchTo(NewFunc); EagerDispatch(&F, ReInfo).emitDispatchTo(NewFunc);
} }
}); });
// Invalidate everything since we delete calls as well as add new
// calls and branches.
if (Changed) {
invalidateAnalysis(&F, SILAnalysis::InvalidationKind::Everything);
}
// As specializations are created, the attributes should be removed. // As specializations are created, the attributes should be removed.
F.clearSpecializeAttrs(); F.clearSpecializeAttrs();
} }
// Invalidate everything since we delete calls as well as add new
// calls and branches.
if (Changed) {
invalidateAnalysis(SILAnalysis::InvalidationKind::Everything);
}
} }
SILTransform *swift::createEagerSpecializer() { SILTransform *swift::createEagerSpecializer() {

View File

@@ -934,7 +934,7 @@ class SILGlobalOptPass : public SILModuleTransform
void run() override { void run() override {
DominanceAnalysis *DA = PM->getAnalysis<DominanceAnalysis>(); DominanceAnalysis *DA = PM->getAnalysis<DominanceAnalysis>();
if (SILGlobalOpt(getModule(), DA).run()) { if (SILGlobalOpt(getModule(), DA).run()) {
invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody); invalidateAll();
} }
} }

View File

@@ -103,6 +103,8 @@ class GlobalPropertyOpt {
/// All found calls to get-property semantic functions. /// All found calls to get-property semantic functions.
std::vector<ApplyInst *> propertyCalls; std::vector<ApplyInst *> propertyCalls;
llvm::SetVector<SILFunction *> ChangedFunctions;
/// Contains entries with a false property value, which must be propagated /// Contains entries with a false property value, which must be propagated
/// to their dependencies. /// to their dependencies.
llvm::SmallVector<Entry *, 32> WorkList; llvm::SmallVector<Entry *, 32> WorkList;
@@ -223,13 +225,13 @@ class GlobalPropertyOpt {
void propagatePropertiesInGraph(); void propagatePropertiesInGraph();
bool replacePropertyCalls(); void replacePropertyCalls();
public: public:
GlobalPropertyOpt(SILModule &Module) : GlobalPropertyOpt(SILModule &Module) :
M(Module), ArrayType(nullptr) {} M(Module), ArrayType(nullptr) {}
bool run(); void run(SILModuleTransform *T);
}; };
/// Checks if an address value does escape. If \p acceptStore is false, then /// Checks if an address value does escape. If \p acceptStore is false, then
@@ -453,13 +455,15 @@ void GlobalPropertyOpt::propagatePropertiesInGraph() {
/// Replaces all get-property calls, which we can prove to be true, with /// Replaces all get-property calls, which we can prove to be true, with
/// true-literals. /// true-literals.
bool GlobalPropertyOpt::replacePropertyCalls() { void GlobalPropertyOpt::replacePropertyCalls() {
bool Changed = false;
for (ApplyInst *AI : propertyCalls) { for (ApplyInst *AI : propertyCalls) {
SILFunction *F = AI->getFunction();
// Don't optimize functions that are marked with the opt.never attribute. // Don't optimize functions that are marked with the opt.never attribute.
if (!AI->getFunction()->shouldOptimize()) if (!F->shouldOptimize())
continue; continue;
ChangedFunctions.insert(F);
SILValue array = AI->getArgument(0); SILValue array = AI->getArgument(0);
// Is the argument a native swift array? // Is the argument a native swift array?
@@ -481,14 +485,12 @@ bool GlobalPropertyOpt::replacePropertyCalls() {
semCall.removeCall(); semCall.removeCall();
NumPropertiesReplaced++; NumPropertiesReplaced++;
Changed = true;
} }
} }
return Changed;
} }
/// The main entry point to the optimization. /// The main entry point to the optimization.
bool GlobalPropertyOpt::run() { void GlobalPropertyOpt::run(SILModuleTransform *T) {
assert(WorkList.empty()); assert(WorkList.empty());
assert(FieldEntries.empty() && ValueEntries.empty()); assert(FieldEntries.empty() && ValueEntries.empty());
@@ -502,7 +504,12 @@ bool GlobalPropertyOpt::run() {
propagatePropertiesInGraph(); propagatePropertiesInGraph();
// Step 3: replace get-property calls with literals. // Step 3: replace get-property calls with literals.
return replacePropertyCalls(); replacePropertyCalls();
for (SILFunction *ChangedFn : ChangedFunctions) {
T->invalidateAnalysis(ChangedFn,
SILAnalysis::InvalidationKind::CallsAndInstructions);
}
} }
/// The module pass, which runs the optimization. /// The module pass, which runs the optimization.
@@ -513,11 +520,7 @@ class GlobalPropertyOptPass : public SILModuleTransform {
DEBUG(llvm::dbgs() << "** GlobalPropertyOpt **\n"); DEBUG(llvm::dbgs() << "** GlobalPropertyOpt **\n");
bool Changed = GlobalPropertyOpt(*M).run(); GlobalPropertyOpt(*M).run(this);
if (Changed) {
invalidateAnalysis(SILAnalysis::InvalidationKind::CallsAndInstructions);
}
} }
StringRef getName() override { return "GlobalPropertyOpt"; } StringRef getName() override { return "GlobalPropertyOpt"; }

View File

@@ -43,11 +43,12 @@ namespace {
class LetPropertiesOpt { class LetPropertiesOpt {
SILModule *Module; SILModule *Module;
bool HasChanged = false;
typedef SmallVector<SILInstruction *, 8> Instructions; typedef SmallVector<SILInstruction *, 8> Instructions;
typedef SmallVector<VarDecl *, 4> Properties; typedef SmallVector<VarDecl *, 4> Properties;
llvm::SetVector<SILFunction *> ChangedFunctions;
// Map each let property to a set of instructions accessing it. // Map each let property to a set of instructions accessing it.
llvm::MapVector<VarDecl *, Instructions> AccessMap; llvm::MapVector<VarDecl *, Instructions> AccessMap;
// Map each let property to the instruction sequence which initializes it. // Map each let property to the instruction sequence which initializes it.
@@ -69,7 +70,7 @@ class LetPropertiesOpt {
public: public:
LetPropertiesOpt(SILModule *M): Module(M) {} LetPropertiesOpt(SILModule *M): Module(M) {}
bool run(); void run(SILModuleTransform *T);
protected: protected:
bool isConstantLetProperty(VarDecl *Property); bool isConstantLetProperty(VarDecl *Property);
@@ -188,12 +189,14 @@ void LetPropertiesOpt::optimizeLetPropertyAccess(VarDecl *Property,
unsigned NumReplaced = 0; unsigned NumReplaced = 0;
for (auto Load: Loads) { for (auto Load: Loads) {
SILFunction *F = Load->getFunction();
// Look for any instructions accessing let properties. // Look for any instructions accessing let properties.
if (isa<RefElementAddrInst>(Load)) { if (isa<RefElementAddrInst>(Load)) {
// Copy the initializer into the function // Copy the initializer into the function
// Replace the access to a let property by the value // Replace the access to a let property by the value
// computed by this initializer. // computed by this initializer.
InstructionsCloner Cloner(*Load->getFunction(), Init, Load); InstructionsCloner Cloner(*F, Init, Load);
Cloner.clone(); Cloner.clone();
SILInstruction *I = &*std::prev(Load->getIterator()); SILInstruction *I = &*std::prev(Load->getIterator());
SILBuilderWithScope B(Load); SILBuilderWithScope B(Load);
@@ -208,12 +211,12 @@ void LetPropertiesOpt::optimizeLetPropertyAccess(VarDecl *Property,
User->eraseFromParent(); User->eraseFromParent();
++NumReplaced; ++NumReplaced;
} }
HasChanged = true; ChangedFunctions.insert(F);
} else if (isa<StructExtractInst>(Load)) { } else if (isa<StructExtractInst>(Load)) {
// Copy the initializer into the function // Copy the initializer into the function
// Replace the access to a let property by the value // Replace the access to a let property by the value
// computed by this initializer. // computed by this initializer.
InstructionsCloner Cloner(*Load->getFunction(), Init, Load); InstructionsCloner Cloner(*F, Init, Load);
Cloner.clone(); Cloner.clone();
SILInstruction *I = &*std::prev(Load->getIterator()); SILInstruction *I = &*std::prev(Load->getIterator());
Load->replaceAllUsesWith(I); Load->replaceAllUsesWith(I);
@@ -222,12 +225,12 @@ void LetPropertiesOpt::optimizeLetPropertyAccess(VarDecl *Property,
Load->eraseFromParent(); Load->eraseFromParent();
++NumReplaced; ++NumReplaced;
HasChanged = true; ChangedFunctions.insert(F);
} else if (isa<StructElementAddrInst>(Load)) { } else if (isa<StructElementAddrInst>(Load)) {
// Copy the initializer into the function // Copy the initializer into the function
// Replace the access to a let property by the value // Replace the access to a let property by the value
// computed by this initializer. // computed by this initializer.
InstructionsCloner Cloner(*Load->getFunction(), Init, Load); InstructionsCloner Cloner(*F, Init, Load);
Cloner.clone(); Cloner.clone();
SILInstruction *I = &*std::prev(Load->getIterator()); SILInstruction *I = &*std::prev(Load->getIterator());
SILBuilderWithScope B(Load); SILBuilderWithScope B(Load);
@@ -241,7 +244,7 @@ void LetPropertiesOpt::optimizeLetPropertyAccess(VarDecl *Property,
User->eraseFromParent(); User->eraseFromParent();
++NumReplaced; ++NumReplaced;
} }
HasChanged = true; ChangedFunctions.insert(F);
} }
} }
@@ -563,7 +566,7 @@ void LetPropertiesOpt::collectPropertyAccess(SILInstruction *I,
CannotRemove.insert(Property); CannotRemove.insert(Property);
} }
bool LetPropertiesOpt::run() { void LetPropertiesOpt::run(SILModuleTransform *T) {
// Collect property access information for the whole module. // Collect property access information for the whole module.
for (auto &F : *Module) { for (auto &F : *Module) {
// Take into account even those functions that should not be // Take into account even those functions that should not be
@@ -593,17 +596,18 @@ bool LetPropertiesOpt::run() {
optimizeLetPropertyAccess(Init.first, Init.second); optimizeLetPropertyAccess(Init.first, Init.second);
} }
return HasChanged; for (SILFunction *ChangedFn : ChangedFunctions) {
// Program flow is not changed by this pass.
T->invalidateAnalysis(ChangedFn,
SILAnalysis::InvalidationKind::Instructions);
}
} }
namespace { namespace {
class LetPropertiesOptPass : public SILModuleTransform class LetPropertiesOptPass : public SILModuleTransform
{ {
void run() override { void run() override {
if (LetPropertiesOpt(getModule()).run()) { LetPropertiesOpt(getModule()).run(this);
// Program flow is not changed by this pass.
invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
}
} }
StringRef getName() override { StringRef getName() override {

View File

@@ -1470,7 +1470,7 @@ void AddressLowering::runOnFunction(SILFunction *F) {
// Rewrite instructions with address-only operands or results. // Rewrite instructions with address-only operands or results.
rewriteFunction(pass); rewriteFunction(pass);
invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions); invalidateAnalysis(F, SILAnalysis::InvalidationKind::Instructions);
// Instructions that were explicitly marked dead should already have no // Instructions that were explicitly marked dead should already have no
// users. // users.

View File

@@ -727,7 +727,8 @@ static bool removeUnreachableBlocks(SILFunction &F, SILModule &M,
/// diagnose any user code after it as being unreachable. This pass happens /// diagnose any user code after it as being unreachable. This pass happens
/// before the definite initialization pass so that it doesn't see infeasible /// before the definite initialization pass so that it doesn't see infeasible
/// control flow edges. /// control flow edges.
static void performNoReturnFunctionProcessing(SILModule *M) { static void performNoReturnFunctionProcessing(SILModule *M,
SILModuleTransform *T) {
for (auto &Fn : *M) { for (auto &Fn : *M) {
DEBUG(llvm::errs() << "*** No return function processing: " DEBUG(llvm::errs() << "*** No return function processing: "
<< Fn.getName() << "\n"); << Fn.getName() << "\n");
@@ -737,10 +738,11 @@ static void performNoReturnFunctionProcessing(SILModule *M) {
// function. // function.
simplifyBlocksWithCallsToNoReturn(BB, nullptr); simplifyBlocksWithCallsToNoReturn(BB, nullptr);
} }
T->invalidateAnalysis(&Fn, SILAnalysis::InvalidationKind::FunctionBody);
} }
} }
void swift::performSILDiagnoseUnreachable(SILModule *M) { void swift::performSILDiagnoseUnreachable(SILModule *M, SILModuleTransform *T) {
for (auto &Fn : *M) { for (auto &Fn : *M) {
DEBUG(llvm::errs() << "*** Diagnose Unreachable processing: " DEBUG(llvm::errs() << "*** Diagnose Unreachable processing: "
<< Fn.getName() << "\n"); << Fn.getName() << "\n");
@@ -778,14 +780,16 @@ void swift::performSILDiagnoseUnreachable(SILModule *M) {
// Remove unreachable blocks. // Remove unreachable blocks.
removeUnreachableBlocks(Fn, *M, &State); removeUnreachableBlocks(Fn, *M, &State);
if (T)
T->invalidateAnalysis(&Fn, SILAnalysis::InvalidationKind::FunctionBody);
} }
} }
namespace { namespace {
class NoReturnFolding : public SILModuleTransform { class NoReturnFolding : public SILModuleTransform {
void run() override { void run() override {
performNoReturnFunctionProcessing(getModule()); performNoReturnFunctionProcessing(getModule(), this);
invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
} }
StringRef getName() override { return "NoReturnFolding"; } StringRef getName() override { return "NoReturnFolding"; }
@@ -800,8 +804,7 @@ SILTransform *swift::createNoReturnFolding() {
namespace { namespace {
class DiagnoseUnreachable : public SILModuleTransform { class DiagnoseUnreachable : public SILModuleTransform {
void run() override { void run() override {
performSILDiagnoseUnreachable(getModule()); performSILDiagnoseUnreachable(getModule(), this);
invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
} }
StringRef getName() override { return "Diagnose Unreachable"; } StringRef getName() override { return "Diagnose Unreachable"; }

View File

@@ -557,6 +557,8 @@ class MandatoryInlining : public SILModuleTransform {
for (auto FI = M->begin(), E = M->end(); FI != E; ) { for (auto FI = M->begin(), E = M->end(); FI != E; ) {
SILFunction &F = *FI++; SILFunction &F = *FI++;
invalidateAnalysis(&F, SILAnalysis::InvalidationKind::Everything);
if (F.getRefCount() != 0) continue; if (F.getRefCount() != 0) continue;
// Leave non-transparent functions alone. // Leave non-transparent functions alone.
@@ -572,12 +574,12 @@ class MandatoryInlining : public SILModuleTransform {
// even if not referenced inside SIL. // even if not referenced inside SIL.
if (F.getRepresentation() == SILFunctionTypeRepresentation::ObjCMethod) if (F.getRepresentation() == SILFunctionTypeRepresentation::ObjCMethod)
continue; continue;
notifyDeleteFunction(&F);
// Okay, just erase the function from the module. // Okay, just erase the function from the module.
M->eraseFunction(&F); M->eraseFunction(&F);
} }
invalidateAnalysis(SILAnalysis::InvalidationKind::Everything);
} }
StringRef getName() override { return "Mandatory Inlining"; } StringRef getName() override { return "Mandatory Inlining"; }

View File

@@ -115,7 +115,7 @@ bool Devirtualizer::devirtualizeAppliesInFunction(SILFunction &F,
// be beneficial to rerun some earlier passes on the current // be beneficial to rerun some earlier passes on the current
// function now that we've made these direct references visible. // function now that we've made these direct references visible.
if (CalleeFn->isDefinition() && CalleeFn->shouldOptimize()) if (CalleeFn->isDefinition() && CalleeFn->shouldOptimize())
notifyPassManagerOfFunction(CalleeFn, nullptr); notifyAddFunction(CalleeFn, nullptr);
} }
return Changed; return Changed;

View File

@@ -981,11 +981,11 @@ public:
// The old function must be a thunk now. // The old function must be a thunk now.
assert(F->isThunk() && "Old function should have been turned into a thunk"); assert(F->isThunk() && "Old function should have been turned into a thunk");
PM->invalidateAnalysis(F, SILAnalysis::InvalidationKind::Everything); invalidateAnalysis(SILAnalysis::InvalidationKind::Everything);
// Make sure the PM knows about this function. This will also help us // Make sure the PM knows about this function. This will also help us
// with self-recursion. // with self-recursion.
notifyPassManagerOfFunction(FST.getOptimizedFunction(), F); notifyAddFunction(FST.getOptimizedFunction(), F);
if (!OptForPartialApply) { if (!OptForPartialApply) {
// We have to restart the pipeline for this thunk in order to run the // We have to restart the pipeline for this thunk in order to run the

View File

@@ -112,7 +112,7 @@ bool GenericSpecializer::specializeAppliesInFunction(SILFunction &F) {
// (as opposed to returning a previous specialization), we need to notify // (as opposed to returning a previous specialization), we need to notify
// the pass manager so that the new functions get optimized. // the pass manager so that the new functions get optimized.
for (SILFunction *NewF : reverse(NewFunctions)) { for (SILFunction *NewF : reverse(NewFunctions)) {
notifyPassManagerOfFunction(NewF, Callee); notifyAddFunction(NewF, Callee);
} }
} }
} }

View File

@@ -44,7 +44,7 @@ class SILLinker : public SILModuleTransform {
SILModule &M = *getModule(); SILModule &M = *getModule();
for (auto &Fn : M) for (auto &Fn : M)
if (M.linkFunction(&Fn, SILModule::LinkingMode::LinkAll)) if (M.linkFunction(&Fn, SILModule::LinkingMode::LinkAll))
invalidateAnalysis(&Fn, SILAnalysis::InvalidationKind::Everything); invalidateAnalysis(&Fn, SILAnalysis::InvalidationKind::Everything);
} }
StringRef getName() override { return "SIL Linker"; } StringRef getName() override { return "SIL Linker"; }

View File

@@ -27,7 +27,7 @@ namespace {
class LoopRegionViewText : public SILModuleTransform { class LoopRegionViewText : public SILModuleTransform {
void run() override { void run() override {
invalidateAnalysis(SILAnalysis::InvalidationKind::Everything); invalidateAll();
LoopRegionAnalysis *LRA = PM->getAnalysis<LoopRegionAnalysis>(); LoopRegionAnalysis *LRA = PM->getAnalysis<LoopRegionAnalysis>();
for (auto &Fn : *getModule()) { for (auto &Fn : *getModule()) {
if (Fn.isExternalDeclaration()) continue; if (Fn.isExternalDeclaration()) continue;

View File

@@ -207,7 +207,7 @@ void removeUnwantedFunctions(SILModule *M, ArrayRef<std::string> MangledNames,
// After running this pass all of the functions we will remove // After running this pass all of the functions we will remove
// should consist only of one basic block terminated by // should consist only of one basic block terminated by
// UnreachableInst. // UnreachableInst.
performSILDiagnoseUnreachable(M); performSILDiagnoseUnreachable(M, nullptr);
// Now mark all of these functions as public and remove their bodies. // Now mark all of these functions as public and remove their bodies.
for (auto &F : DeadFunctions) { for (auto &F : DeadFunctions) {