aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2013-11-22 12:11:02 +0000
committerChandler Carruth <chandlerc@gmail.com>2013-11-22 12:11:02 +0000
commitf2edc07571ae376ea97ae963b6ac0fb8e762ec2e (patch)
tree671314151099af98f983cba02f2940585316e615
parent71ec5a64ddb3a37ac3347f1f3b9e93e8bd22d1ef (diff)
downloadllvm-f2edc07571ae376ea97ae963b6ac0fb8e762ec2e.zip
llvm-f2edc07571ae376ea97ae963b6ac0fb8e762ec2e.tar.gz
llvm-f2edc07571ae376ea97ae963b6ac0fb8e762ec2e.tar.bz2
[PM] Teach the analysis managers to pass themselves as arguments to the
run methods of the analysis passes. Also generalizes and re-uses the SFINAE for transformation passes so that users can write an analysis pass and only accept an analysis manager if that is useful to their pass. This completes the plumbing to make an analysis manager available through every pass's run method if desired so that passes no longer need to be constructed around them. llvm-svn: 195451
-rw-r--r--llvm/include/llvm/IR/PassManager.h66
-rw-r--r--llvm/lib/IR/PassManager.cpp4
-rw-r--r--llvm/unittests/IR/PassManagerTest.cpp2
3 files changed, 54 insertions, 18 deletions
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
index 3ec4f6c..111d373 100644
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/include/llvm/IR/PassManager.h
@@ -169,12 +169,13 @@ template <typename IRUnitT, typename AnalysisManagerT> struct PassConcept {
/// \brief SFINAE metafunction for computing whether \c PassT has a run method
/// accepting an \c AnalysisManagerT.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
+template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
+ typename ResultT>
class PassRunAcceptsAnalysisManager {
typedef char SmallType;
struct BigType { char a, b; };
- template <typename T, PreservedAnalyses (T::*)(IRUnitT, AnalysisManagerT *)>
+ template <typename T, ResultT (T::*)(IRUnitT, AnalysisManagerT *)>
struct Checker;
template <typename T> static SmallType f(Checker<T, &T::run> *);
@@ -191,7 +192,7 @@ public:
/// \c run method also accepts an \c AnalysisManagerT*, we pass it along.
template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
- IRUnitT, AnalysisManagerT, PassT>::Value>
+ IRUnitT, AnalysisManagerT, PassT, PreservedAnalyses>::Value>
struct PassModel;
/// \brief Specialization of \c PassModel for passes that accept an analyis
@@ -312,14 +313,16 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT,
///
/// This concept is parameterized over the IR unit that it can run over and
/// produce an analysis result.
-template <typename IRUnitT> struct AnalysisPassConcept {
+template <typename IRUnitT, typename AnalysisManagerT>
+struct AnalysisPassConcept {
virtual ~AnalysisPassConcept() {}
virtual AnalysisPassConcept *clone() = 0;
/// \brief Method to run this analysis over a unit of IR.
/// \returns The analysis result object to be queried by users, the caller
/// takes ownership.
- virtual AnalysisResultConcept<IRUnitT> *run(IRUnitT IR) = 0;
+ virtual AnalysisResultConcept<IRUnitT> *run(IRUnitT IR,
+ AnalysisManagerT *AM) = 0;
};
/// \brief Wrapper to model the analysis pass concept.
@@ -327,8 +330,40 @@ template <typename IRUnitT> struct AnalysisPassConcept {
/// Can wrap any type which implements a suitable \c run method. The method
/// must accept the IRUnitT as an argument and produce an object which can be
/// wrapped in a \c AnalysisResultModel.
-template <typename IRUnitT, typename PassT>
-struct AnalysisPassModel : AnalysisPassConcept<IRUnitT> {
+template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
+ bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
+ IRUnitT, AnalysisManagerT, PassT,
+ typename PassT::Result>::Value > struct AnalysisPassModel;
+
+/// \brief Specialization of \c AnalysisPassModel which passes an
+/// \c AnalysisManager to PassT's run method.
+template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
+struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT,
+ true> : AnalysisPassConcept<IRUnitT,
+ AnalysisManagerT> {
+ AnalysisPassModel(PassT Pass) : Pass(llvm_move(Pass)) {}
+ virtual AnalysisPassModel *clone() { return new AnalysisPassModel(Pass); }
+
+ // FIXME: Replace PassT::Result with type traits when we use C++11.
+ typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
+ ResultModelT;
+
+ /// \brief The model delegates to the \c PassT::run method.
+ ///
+ /// The return is wrapped in an \c AnalysisResultModel.
+ virtual ResultModelT *run(IRUnitT IR, AnalysisManagerT *AM) {
+ return new ResultModelT(Pass.run(IR, AM));
+ }
+
+ PassT Pass;
+};
+
+/// \brief Specialization of \c AnalysisPassModel which does not pass an
+/// \c AnalysisManager to PassT's run method.
+template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
+struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT,
+ false> : AnalysisPassConcept<IRUnitT,
+ AnalysisManagerT> {
AnalysisPassModel(PassT Pass) : Pass(llvm_move(Pass)) {}
virtual AnalysisPassModel *clone() { return new AnalysisPassModel(Pass); }
@@ -339,7 +374,7 @@ struct AnalysisPassModel : AnalysisPassConcept<IRUnitT> {
/// \brief The model delegates to the \c PassT::run method.
///
/// The return is wrapped in an \c AnalysisResultModel.
- virtual ResultModelT *run(IRUnitT IR) {
+ virtual ResultModelT *run(IRUnitT IR, AnalysisManagerT *) {
return new ResultModelT(Pass.run(IR));
}
@@ -436,7 +471,8 @@ public:
assert(!ModuleAnalysisPasses.count(PassT::ID()) &&
"Registered the same analysis pass twice!");
ModuleAnalysisPasses[PassT::ID()] =
- new detail::AnalysisPassModel<Module *, PassT>(llvm_move(Pass));
+ new detail::AnalysisPassModel<Module *, ModuleAnalysisManager, PassT>(
+ llvm_move(Pass));
}
/// \brief Invalidate a specific analysis pass for an IR module.
@@ -463,8 +499,8 @@ private:
void invalidateImpl(void *PassID, Module *M);
/// \brief Map type from module analysis pass ID to pass concept pointer.
- typedef DenseMap<void *,
- polymorphic_ptr<detail::AnalysisPassConcept<Module *> > >
+ typedef DenseMap<void *, polymorphic_ptr<detail::AnalysisPassConcept<
+ Module *, ModuleAnalysisManager> > >
ModuleAnalysisPassMapT;
/// \brief Collection of module analysis passes, indexed by ID.
@@ -511,8 +547,8 @@ public:
template <typename PassT> void registerPass(PassT Pass) {
assert(!FunctionAnalysisPasses.count(PassT::ID()) &&
"Registered the same analysis pass twice!");
- FunctionAnalysisPasses[PassT::ID()] =
- new detail::AnalysisPassModel<Function *, PassT>(llvm_move(Pass));
+ FunctionAnalysisPasses[PassT::ID()] = new detail::AnalysisPassModel<
+ Function *, FunctionAnalysisManager, PassT>(llvm_move(Pass));
}
/// \brief Invalidate a specific analysis pass for an IR module.
@@ -551,8 +587,8 @@ private:
void invalidateImpl(void *PassID, Function *F);
/// \brief Map type from function analysis pass ID to pass concept pointer.
- typedef DenseMap<void *,
- polymorphic_ptr<detail::AnalysisPassConcept<Function *> > >
+ typedef DenseMap<void *, polymorphic_ptr<detail::AnalysisPassConcept<
+ Function *, FunctionAnalysisManager> > >
FunctionAnalysisPassMapT;
/// \brief Collection of function analysis passes, indexed by ID.
diff --git a/llvm/lib/IR/PassManager.cpp b/llvm/lib/IR/PassManager.cpp
index f2d0cd9..fe16adc 100644
--- a/llvm/lib/IR/PassManager.cpp
+++ b/llvm/lib/IR/PassManager.cpp
@@ -47,7 +47,7 @@ ModuleAnalysisManager::getResultImpl(void *PassID, Module *M) {
ModuleAnalysisPasses.find(PassID);
assert(PI != ModuleAnalysisPasses.end() &&
"Analysis passes must be registered prior to being queried!");
- RI->second = PI->second->run(M);
+ RI->second = PI->second->run(M, this);
}
return *RI->second;
@@ -115,7 +115,7 @@ FunctionAnalysisManager::getResultImpl(void *PassID, Function *F) {
assert(PI != FunctionAnalysisPasses.end() &&
"Analysis passes must be registered prior to being queried!");
FunctionAnalysisResultListT &ResultList = FunctionAnalysisResultLists[F];
- ResultList.push_back(std::make_pair(PassID, PI->second->run(F)));
+ ResultList.push_back(std::make_pair(PassID, PI->second->run(F, this)));
RI->second = llvm::prior(ResultList.end());
}
diff --git a/llvm/unittests/IR/PassManagerTest.cpp b/llvm/unittests/IR/PassManagerTest.cpp
index b0d4cbe..8115da8 100644
--- a/llvm/unittests/IR/PassManagerTest.cpp
+++ b/llvm/unittests/IR/PassManagerTest.cpp
@@ -32,7 +32,7 @@ public:
TestAnalysisPass(int &Runs) : Runs(Runs) {}
/// \brief Run the analysis pass over the function and return a result.
- Result run(Function *F) {
+ Result run(Function *F, FunctionAnalysisManager *AM) {
++Runs;
int Count = 0;
for (Function::iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; ++BBI)