Files
swift-mirror/include/swift/SILOptimizer/PassManager/Transforms.h
Michael Gottesman f35a2a3cf8 [sil-opt] Only notify the pass manager of newly added functions in SILOptFunctionBuilder.
To do so this commit does a few different things:

1. I changed SILOptFunctionBuilder to notify the pass manager's logging
functionality when new functions are added to the module and to notify analyses
as well. NOTE: This on purpose does not put the new function on the pass manager
worklist since we do not want to by mistake introduce a large amount of
re-optimizations. Such a thing should be explicit.

2. I eliminated SILModuleTransform::notifyAddFunction. This just performed the
operations from 1. Now that SILOptFunctionBuilder performs this operation for
us, it is not needed.

3. I changed SILFunctionTransform::notifyAddFunction to just add the function to
the passmanager worklist. It does not need to notify the pass manager's logging
or analyses that a new function was added to the module since
SILOptFunctionBuilder now performs that operation. Given its reduced
functionality, I changed the name to addFunctionToPassManagerWorklist(...). The
name is a little long/verbose, but this is a feature since one should think
before getting the pass manager to rerun transforms on a function. Also, giving
it a longer name calls out the operation in the code visually, giving this
operation more prominance when reading code. NOTE: I did the rename using
Xcode's refactoring functionality!

rdar://42301529
2018-08-06 18:27:24 -07:00

176 lines
5.5 KiB
C++

//===--- Transforms.h - Swift Transformations ------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SILOPTIMIZER_PASSMANAGER_TRANSFORMS_H
#define SWIFT_SILOPTIMIZER_PASSMANAGER_TRANSFORMS_H
#include "swift/SIL/Notifications.h"
#include "swift/SILOptimizer/PassManager/PassManager.h"
namespace swift {
class SILModule;
class SILFunction;
class PrettyStackTraceSILFunctionTransform;
/// The base class for all SIL-level transformations.
class SILTransform : public DeleteNotificationHandler {
public:
/// The kind of transformation passes we use.
enum class TransformKind {
Function,
Module,
};
/// Stores the kind of derived class.
const TransformKind Kind;
protected:
// The pass manager that runs this pass.
SILPassManager* PM;
// The pass kind (used by the pass manager).
PassKind passKind = PassKind::invalidPassKind;
public:
/// C'tor. \p K indicates the kind of derived class.
SILTransform(SILTransform::TransformKind K) : Kind(K), PM(0) {}
/// D'tor.
virtual ~SILTransform() = default;
/// Returns the kind of derived class.
TransformKind getKind() const { return Kind; }
/// Returns the pass kind.
PassKind getPassKind() const {
assert(passKind != PassKind::invalidPassKind);
return passKind;
}
/// Sets the pass kind. This should only be done in the add-functions of
/// the pass manager.
void setPassKind(PassKind newPassKind) {
assert(passKind == PassKind::invalidPassKind);
passKind = newPassKind;
}
/// Inject the pass manager running this pass.
void injectPassManager(SILPassManager *PMM) { PM = PMM; }
SILPassManager *getPassManager() const { return PM; }
irgen::IRGenModule *getIRGenModule() {
auto *Mod = PM->getIRGenModule();
assert(Mod && "Expecting a valid module");
return Mod;
}
/// Get the transform's (command-line) tag.
llvm::StringRef getTag() { return PassKindTag(getPassKind()); }
/// Get the transform's name as a C++ identifier.
llvm::StringRef getID() { return PassKindID(getPassKind()); }
protected:
/// \brief Searches for an analysis of type T in the list of registered
/// analysis. If the analysis is not found, the program terminates.
template<typename T>
T* getAnalysis() { return PM->getAnalysis<T>(); }
const SILOptions &getOptions() { return PM->getOptions(); }
};
/// A transformation that operates on functions.
class SILFunctionTransform : public SILTransform {
friend class PrettyStackTraceSILFunctionTransform;
SILFunction *F;
public:
/// C'tor.
SILFunctionTransform() : SILTransform(TransformKind::Function), F(0) {}
/// The entry point to the transformation.
virtual void run() = 0;
static bool classof(const SILTransform *S) {
return S->getKind() == TransformKind::Function;
}
void injectFunction(SILFunction *Func) { F = Func; }
/// \brief Notify the pass manager of a function \p F that needs to be
/// processed by the function passes and the analyses.
///
/// If not null, the function \p DerivedFrom is the function from which \p F
/// is derived. This is used to limit the number of new functions which are
/// derived from a common base function, e.g. due to specialization.
/// The number should be small anyway, but bugs in optimizations could cause
/// an infinite loop in the passmanager.
void addFunctionToPassManagerWorklist(SILFunction *F,
SILFunction *DerivedFrom) {
PM->addFunctionToWorklist(F, DerivedFrom);
}
/// \brief Reoptimize the current function by restarting the pass
/// pipeline on it.
void restartPassPipeline() { PM->restartWithCurrentFunction(this); }
SILFunction *getFunction() { return F; }
void invalidateAnalysis(SILAnalysis::InvalidationKind K) {
PM->invalidateAnalysis(F, K);
}
};
/// A transformation that operates on modules.
class SILModuleTransform : public SILTransform {
SILModule *M;
public:
/// C'tor.
SILModuleTransform() : SILTransform(TransformKind::Module), M(0) {}
/// The entry point to the transformation.
virtual void run() = 0;
static bool classof(const SILTransform *S) {
return S->getKind() == TransformKind::Module;
}
void injectModule(SILModule *Mod) { M = Mod; }
SILModule *getModule() { return M; }
/// Invalidate all analysis data for the whole module.
void invalidateAll() {
PM->invalidateAllAnalysis();
}
/// Invalidate only the function \p F, using invalidation information \p K.
void invalidateAnalysis(SILFunction *F, SILAnalysis::InvalidationKind K) {
PM->invalidateAnalysis(F, K);
}
/// Invalidate the analysis data for witness- and vtables.
void invalidateFunctionTables() {
PM->invalidateFunctionTables();
}
/// Inform the pass manager that we are going to delete a function.
void notifyWillDeleteFunction(SILFunction *F) {
PM->notifyWillDeleteFunction(F);
}
};
} // end namespace swift
#endif