summaryrefslogtreecommitdiff
path: root/include/llvm/IR/PassManager.h
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2013-11-21 02:11:31 +0000
committerChandler Carruth <chandlerc@gmail.com>2013-11-21 02:11:31 +0000
commit7fac06c4233ea2769fc1b6ed4bb1d23ce538a89f (patch)
tree00caa42760cd364ffdea4fc08ca1707b44f5370c /include/llvm/IR/PassManager.h
parent7b98dd33fd9489e6cd88920a209a824b01c56207 (diff)
downloadllvm-7fac06c4233ea2769fc1b6ed4bb1d23ce538a89f.tar.gz
llvm-7fac06c4233ea2769fc1b6ed4bb1d23ce538a89f.tar.bz2
llvm-7fac06c4233ea2769fc1b6ed4bb1d23ce538a89f.tar.xz
[PM] Add a module analysis pass proxy for the function analysis manager.
This proxy will fill the role of proxying invalidation events down IR unit layers so that when a module changes we correctly invalidate function analyses. Currently this is a very coarse solution -- any change blows away the entire thing -- but the next step is to make invalidation handling more nuanced so that we can propagate specific amounts of invalidation from one layer to the next. The test is extended to place a module pass between two function pass managers each of which have preserved function analyses which get correctly invalidated by the module pass that might have changed what functions are even in the module. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195304 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/IR/PassManager.h')
-rw-r--r--include/llvm/IR/PassManager.h143
1 files changed, 111 insertions, 32 deletions
diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h
index 3fccdf4e3f..368ebaeb17 100644
--- a/include/llvm/IR/PassManager.h
+++ b/include/llvm/IR/PassManager.h
@@ -305,38 +305,6 @@ private:
std::vector<polymorphic_ptr<FunctionPassConcept> > Passes;
};
-/// \brief Trivial adaptor that maps from a module to its functions.
-///
-/// Designed to allow composition of a FunctionPass(Manager) and a
-/// ModulePassManager.
-template <typename FunctionPassT>
-class ModuleToFunctionPassAdaptor {
-public:
- explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass)
- : Pass(llvm_move(Pass)) {}
-
- /// \brief Runs the function pass across every function in the module.
- PreservedAnalyses run(Module *M) {
- PreservedAnalyses PA = PreservedAnalyses::all();
- for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
- PreservedAnalyses PassPA = Pass.run(I);
- PA.intersect(llvm_move(PassPA));
- }
- return PA;
- }
-
-private:
- FunctionPassT Pass;
-};
-
-/// \brief A function to deduce a function pass type and wrap it in the
-/// templated adaptor.
-template <typename FunctionPassT>
-ModuleToFunctionPassAdaptor<FunctionPassT>
-createModuleToFunctionPassAdaptor(FunctionPassT Pass) {
- return ModuleToFunctionPassAdaptor<FunctionPassT>(llvm_move(Pass));
-}
-
/// \brief A module analysis pass manager with lazy running and caching of
/// results.
class ModuleAnalysisManager {
@@ -476,6 +444,17 @@ public:
/// PreservedAnalyses set.
void invalidate(Function *F, const PreservedAnalyses &PA);
+ /// \brief Returns true if the analysis manager has an empty results cache.
+ bool empty() const;
+
+ /// \brief Clear the function analysis result cache.
+ ///
+ /// This routine allows cleaning up when the set of functions itself has
+ /// potentially changed, and thus we can't even look up a a result and
+ /// invalidate it directly. Notably, this does *not* call invalidate
+ /// functions as there is nothing to be done for them.
+ void clear();
+
private:
/// \brief Get a function pass result, running the pass if necessary.
const detail::AnalysisResultConcept<Function> &getResultImpl(void *PassID,
@@ -522,4 +501,104 @@ private:
FunctionAnalysisResultMapT FunctionAnalysisResults;
};
+/// \brief A module analysis which acts as a proxy for a function analysis
+/// manager.
+///
+/// This primarily proxies invalidation information from the module analysis
+/// manager and module pass manager to a function analysis manager. You should
+/// never use a function analysis manager from within (transitively) a module
+/// pass manager unless your parent module pass has received a proxy result
+/// object for it.
+///
+/// FIXME: It might be really nice to "enforce" this (softly) by making this
+/// proxy the API path to access a function analysis manager within a module
+/// pass.
+class FunctionAnalysisModuleProxy {
+public:
+ typedef Module IRUnitT;
+ class Result;
+
+ static void *ID() { return (void *)&PassID; }
+
+ FunctionAnalysisModuleProxy(FunctionAnalysisManager &FAM) : FAM(FAM) {}
+
+ /// \brief Run the analysis pass and create our proxy result object.
+ ///
+ /// This doesn't do any interesting work, it is primarily used to insert our
+ /// proxy result object into the module analysis cache so that we can proxy
+ /// invalidation to the function analysis manager.
+ ///
+ /// In debug builds, it will also assert that the analysis manager is empty
+ /// as no queries should arrive at the function analysis manager prior to
+ /// this analysis being requested.
+ Result run(Module *M);
+
+private:
+ static char PassID;
+
+ FunctionAnalysisManager &FAM;
+};
+
+/// \brief The result proxy object for the \c FunctionAnalysisModuleProxy.
+///
+/// See its documentation for more information.
+class FunctionAnalysisModuleProxy::Result {
+public:
+ Result(FunctionAnalysisManager &FAM) : FAM(FAM) {}
+ ~Result();
+
+ /// \brief Handler for invalidation of the module.
+ bool invalidate(Module *M);
+
+private:
+ FunctionAnalysisManager &FAM;
+};
+
+/// \brief Trivial adaptor that maps from a module to its functions.
+///
+/// Designed to allow composition of a FunctionPass(Manager) and a
+/// ModulePassManager. Note that if this pass is constructed with a pointer to
+/// a \c ModuleAnalysisManager it will run the \c FunctionAnalysisModuleProxy
+/// analysis prior to running the function pass over the module to enable a \c
+/// FunctionAnalysisManager to be used within this run safely.
+template <typename FunctionPassT>
+class ModuleToFunctionPassAdaptor {
+public:
+ explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass,
+ ModuleAnalysisManager *MAM = 0)
+ : Pass(llvm_move(Pass)), MAM(MAM) {}
+
+ /// \brief Runs the function pass across every function in the module.
+ PreservedAnalyses run(Module *M) {
+ if (MAM)
+ // Pull in the analysis proxy so that the function analysis manager is
+ // appropriately set up.
+ (void)MAM->getResult<FunctionAnalysisModuleProxy>(M);
+
+ PreservedAnalyses PA = PreservedAnalyses::all();
+ for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
+ PreservedAnalyses PassPA = Pass.run(I);
+ PA.intersect(llvm_move(PassPA));
+ }
+ return PA;
+ }
+
+private:
+ FunctionPassT Pass;
+ ModuleAnalysisManager *MAM;
+};
+
+/// \brief A function to deduce a function pass type and wrap it in the
+/// templated adaptor.
+///
+/// \param MAM is an optional \c ModuleAnalysisManager which (if provided) will
+/// be queried for a \c FunctionAnalysisModuleProxy to enable the function
+/// pass(es) to safely interact with a \c FunctionAnalysisManager.
+template <typename FunctionPassT>
+ModuleToFunctionPassAdaptor<FunctionPassT>
+createModuleToFunctionPassAdaptor(FunctionPassT Pass,
+ ModuleAnalysisManager *MAM = 0) {
+ return ModuleToFunctionPassAdaptor<FunctionPassT>(llvm_move(Pass), MAM);
+}
+
}