[PM] Switch new pass manager from polymorphic_ptr to unique_ptr now that

it is available. Also make the move semantics sufficiently correct to
tolerate move-only passes, as the PassManagers *are* move-only passes.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203391 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chandler Carruth 2014-03-09 11:49:53 +00:00
parent fee1963538
commit 15903b7dc5
4 changed files with 67 additions and 69 deletions

View File

@ -39,12 +39,13 @@
#define LLVM_IR_PASS_MANAGER_H #define LLVM_IR_PASS_MANAGER_H
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/polymorphic_ptr.h"
#include "llvm/IR/Function.h" #include "llvm/IR/Function.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/Support/type_traits.h" #include "llvm/Support/type_traits.h"
#include <list> #include <list>
#include <memory>
#include <vector> #include <vector>
namespace llvm { namespace llvm {
@ -158,7 +159,6 @@ namespace detail {
template <typename IRUnitT, typename AnalysisManagerT> struct PassConcept { template <typename IRUnitT, typename AnalysisManagerT> struct PassConcept {
// Boiler plate necessary for the container of derived classes. // Boiler plate necessary for the container of derived classes.
virtual ~PassConcept() {} virtual ~PassConcept() {}
virtual PassConcept *clone() = 0;
/// \brief The polymorphic API which runs the pass over a given IR entity. /// \brief The polymorphic API which runs the pass over a given IR entity.
/// ///
@ -205,7 +205,6 @@ template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
struct PassModel<IRUnitT, AnalysisManagerT, PassT, struct PassModel<IRUnitT, AnalysisManagerT, PassT,
true> : PassConcept<IRUnitT, AnalysisManagerT> { true> : PassConcept<IRUnitT, AnalysisManagerT> {
PassModel(PassT Pass) : Pass(std::move(Pass)) {} PassModel(PassT Pass) : Pass(std::move(Pass)) {}
PassModel *clone() override { return new PassModel(Pass); }
PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override {
return Pass.run(IR, AM); return Pass.run(IR, AM);
} }
@ -219,7 +218,6 @@ template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
struct PassModel<IRUnitT, AnalysisManagerT, PassT, struct PassModel<IRUnitT, AnalysisManagerT, PassT,
false> : PassConcept<IRUnitT, AnalysisManagerT> { false> : PassConcept<IRUnitT, AnalysisManagerT> {
PassModel(PassT Pass) : Pass(std::move(Pass)) {} PassModel(PassT Pass) : Pass(std::move(Pass)) {}
PassModel *clone() override { return new PassModel(Pass); }
PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override {
return Pass.run(IR); return Pass.run(IR);
} }
@ -233,7 +231,6 @@ struct PassModel<IRUnitT, AnalysisManagerT, PassT,
/// to. /// to.
template <typename IRUnitT> struct AnalysisResultConcept { template <typename IRUnitT> struct AnalysisResultConcept {
virtual ~AnalysisResultConcept() {} virtual ~AnalysisResultConcept() {}
virtual AnalysisResultConcept *clone() = 0;
/// \brief Method to try and mark a result as invalid. /// \brief Method to try and mark a result as invalid.
/// ///
@ -281,9 +278,6 @@ template <typename IRUnitT, typename PassT, typename ResultT>
struct AnalysisResultModel<IRUnitT, PassT, ResultT, struct AnalysisResultModel<IRUnitT, PassT, ResultT,
false> : AnalysisResultConcept<IRUnitT> { false> : AnalysisResultConcept<IRUnitT> {
AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
AnalysisResultModel *clone() override {
return new AnalysisResultModel(Result);
}
/// \brief The model bases invalidation solely on being in the preserved set. /// \brief The model bases invalidation solely on being in the preserved set.
// //
@ -303,9 +297,6 @@ template <typename IRUnitT, typename PassT, typename ResultT>
struct AnalysisResultModel<IRUnitT, PassT, ResultT, struct AnalysisResultModel<IRUnitT, PassT, ResultT,
true> : AnalysisResultConcept<IRUnitT> { true> : AnalysisResultConcept<IRUnitT> {
AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
AnalysisResultModel *clone() override {
return new AnalysisResultModel(Result);
}
/// \brief The model delegates to the \c ResultT method. /// \brief The model delegates to the \c ResultT method.
bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) override { bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) override {
@ -322,13 +313,12 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT,
template <typename IRUnitT, typename AnalysisManagerT> template <typename IRUnitT, typename AnalysisManagerT>
struct AnalysisPassConcept { struct AnalysisPassConcept {
virtual ~AnalysisPassConcept() {} virtual ~AnalysisPassConcept() {}
virtual AnalysisPassConcept *clone() = 0;
/// \brief Method to run this analysis over a unit of IR. /// \brief Method to run this analysis over a unit of IR.
/// \returns The analysis result object to be queried by users, the caller /// \returns A unique_ptr to the analysis result object to be queried by
/// takes ownership. /// users.
virtual AnalysisResultConcept<IRUnitT> *run(IRUnitT IR, virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>>
AnalysisManagerT *AM) = 0; run(IRUnitT IR, AnalysisManagerT *AM) = 0;
}; };
/// \brief Wrapper to model the analysis pass concept. /// \brief Wrapper to model the analysis pass concept.
@ -348,7 +338,6 @@ struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT,
true> : AnalysisPassConcept<IRUnitT, true> : AnalysisPassConcept<IRUnitT,
AnalysisManagerT> { AnalysisManagerT> {
AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
virtual AnalysisPassModel *clone() { return new AnalysisPassModel(Pass); }
// FIXME: Replace PassT::Result with type traits when we use C++11. // FIXME: Replace PassT::Result with type traits when we use C++11.
typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
@ -357,8 +346,9 @@ struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT,
/// \brief The model delegates to the \c PassT::run method. /// \brief The model delegates to the \c PassT::run method.
/// ///
/// The return is wrapped in an \c AnalysisResultModel. /// The return is wrapped in an \c AnalysisResultModel.
virtual ResultModelT *run(IRUnitT IR, AnalysisManagerT *AM) { std::unique_ptr<AnalysisResultConcept<IRUnitT>>
return new ResultModelT(Pass.run(IR, AM)); run(IRUnitT IR, AnalysisManagerT *AM) override {
return make_unique<ResultModelT>(Pass.run(IR, AM));
} }
PassT Pass; PassT Pass;
@ -371,7 +361,6 @@ struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT,
false> : AnalysisPassConcept<IRUnitT, false> : AnalysisPassConcept<IRUnitT,
AnalysisManagerT> { AnalysisManagerT> {
AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
AnalysisPassModel *clone() override { return new AnalysisPassModel(Pass); }
// FIXME: Replace PassT::Result with type traits when we use C++11. // FIXME: Replace PassT::Result with type traits when we use C++11.
typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
@ -380,8 +369,9 @@ struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT,
/// \brief The model delegates to the \c PassT::run method. /// \brief The model delegates to the \c PassT::run method.
/// ///
/// The return is wrapped in an \c AnalysisResultModel. /// The return is wrapped in an \c AnalysisResultModel.
ResultModelT *run(IRUnitT IR, AnalysisManagerT *) override { std::unique_ptr<AnalysisResultConcept<IRUnitT>>
return new ResultModelT(Pass.run(IR)); run(IRUnitT IR, AnalysisManagerT *) override {
return make_unique<ResultModelT>(Pass.run(IR));
} }
PassT Pass; PassT Pass;
@ -393,8 +383,6 @@ class ModuleAnalysisManager;
class ModulePassManager { class ModulePassManager {
public: public:
explicit ModulePassManager() {}
/// \brief Run all of the module passes in this module pass manager over /// \brief Run all of the module passes in this module pass manager over
/// a module. /// a module.
/// ///
@ -403,7 +391,7 @@ public:
PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM = 0); PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM = 0);
template <typename ModulePassT> void addPass(ModulePassT Pass) { template <typename ModulePassT> void addPass(ModulePassT Pass) {
Passes.push_back(new ModulePassModel<ModulePassT>(std::move(Pass))); Passes.emplace_back(new ModulePassModel<ModulePassT>(std::move(Pass)));
} }
static StringRef name() { return "ModulePassManager"; } static StringRef name() { return "ModulePassManager"; }
@ -415,20 +403,19 @@ private:
struct ModulePassModel struct ModulePassModel
: detail::PassModel<Module *, ModuleAnalysisManager, PassT> { : detail::PassModel<Module *, ModuleAnalysisManager, PassT> {
ModulePassModel(PassT Pass) ModulePassModel(PassT Pass)
: detail::PassModel<Module *, ModuleAnalysisManager, PassT>(Pass) {} : detail::PassModel<Module *, ModuleAnalysisManager, PassT>(
std::move(Pass)) {}
}; };
std::vector<polymorphic_ptr<ModulePassConcept> > Passes; std::vector<std::unique_ptr<ModulePassConcept>> Passes;
}; };
class FunctionAnalysisManager; class FunctionAnalysisManager;
class FunctionPassManager { class FunctionPassManager {
public: public:
explicit FunctionPassManager() {}
template <typename FunctionPassT> void addPass(FunctionPassT Pass) { template <typename FunctionPassT> void addPass(FunctionPassT Pass) {
Passes.push_back(new FunctionPassModel<FunctionPassT>(std::move(Pass))); Passes.emplace_back(new FunctionPassModel<FunctionPassT>(std::move(Pass)));
} }
PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM = 0); PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM = 0);
@ -443,10 +430,11 @@ private:
struct FunctionPassModel struct FunctionPassModel
: detail::PassModel<Function *, FunctionAnalysisManager, PassT> { : detail::PassModel<Function *, FunctionAnalysisManager, PassT> {
FunctionPassModel(PassT Pass) FunctionPassModel(PassT Pass)
: detail::PassModel<Function *, FunctionAnalysisManager, PassT>(Pass) {} : detail::PassModel<Function *, FunctionAnalysisManager, PassT>(
std::move(Pass)) {}
}; };
std::vector<polymorphic_ptr<FunctionPassConcept> > Passes; std::vector<std::unique_ptr<FunctionPassConcept>> Passes;
}; };
namespace detail { namespace detail {
@ -519,7 +507,7 @@ public:
assert(!AnalysisPasses.count(PassT::ID()) && assert(!AnalysisPasses.count(PassT::ID()) &&
"Registered the same analysis pass twice!"); "Registered the same analysis pass twice!");
typedef detail::AnalysisPassModel<IRUnitT, DerivedT, PassT> PassModelT; typedef detail::AnalysisPassModel<IRUnitT, DerivedT, PassT> PassModelT;
AnalysisPasses[PassT::ID()] = new PassModelT(std::move(Pass)); AnalysisPasses[PassT::ID()].reset(new PassModelT(std::move(Pass)));
} }
/// \brief Invalidate a specific analysis pass for an IR module. /// \brief Invalidate a specific analysis pass for an IR module.
@ -558,7 +546,7 @@ protected:
private: private:
/// \brief Map type from module analysis pass ID to pass concept pointer. /// \brief Map type from module analysis pass ID to pass concept pointer.
typedef DenseMap<void *, polymorphic_ptr<PassConceptT> > AnalysisPassMapT; typedef DenseMap<void *, std::unique_ptr<PassConceptT>> AnalysisPassMapT;
/// \brief Collection of module analysis passes, indexed by ID. /// \brief Collection of module analysis passes, indexed by ID.
AnalysisPassMapT AnalysisPasses; AnalysisPassMapT AnalysisPasses;
@ -593,7 +581,7 @@ private:
/// \brief Map type from module analysis pass ID to pass result concept pointer. /// \brief Map type from module analysis pass ID to pass result concept pointer.
typedef DenseMap<void *, typedef DenseMap<void *,
polymorphic_ptr<detail::AnalysisResultConcept<Module *> > > std::unique_ptr<detail::AnalysisResultConcept<Module *>>>
ModuleAnalysisResultMapT; ModuleAnalysisResultMapT;
/// \brief Cache of computed module analysis results for this module. /// \brief Cache of computed module analysis results for this module.
@ -642,8 +630,8 @@ private:
/// erases. Provides both the pass ID and concept pointer such that it is /// erases. Provides both the pass ID and concept pointer such that it is
/// half of a bijection and provides storage for the actual result concept. /// half of a bijection and provides storage for the actual result concept.
typedef std::list<std::pair< typedef std::list<std::pair<
void *, polymorphic_ptr<detail::AnalysisResultConcept<Function *> > > > void *, std::unique_ptr<detail::AnalysisResultConcept<Function *>>>>
FunctionAnalysisResultListT; FunctionAnalysisResultListT;
/// \brief Map type from function pointer to our custom list type. /// \brief Map type from function pointer to our custom list type.
typedef DenseMap<Function *, FunctionAnalysisResultListT> typedef DenseMap<Function *, FunctionAnalysisResultListT>
@ -826,7 +814,7 @@ private:
template <typename FunctionPassT> template <typename FunctionPassT>
ModuleToFunctionPassAdaptor<FunctionPassT> ModuleToFunctionPassAdaptor<FunctionPassT>
createModuleToFunctionPassAdaptor(FunctionPassT Pass) { createModuleToFunctionPassAdaptor(FunctionPassT Pass) {
return ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)); return std::move(ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)));
} }
} }

View File

@ -45,12 +45,12 @@ ModuleAnalysisManager::getResultImpl(void *PassID, Module *M) {
ModuleAnalysisResultMapT::iterator RI; ModuleAnalysisResultMapT::iterator RI;
bool Inserted; bool Inserted;
std::tie(RI, Inserted) = ModuleAnalysisResults.insert(std::make_pair( std::tie(RI, Inserted) = ModuleAnalysisResults.insert(std::make_pair(
PassID, polymorphic_ptr<detail::AnalysisResultConcept<Module *> >())); PassID, std::unique_ptr<detail::AnalysisResultConcept<Module *>>()));
// If we don't have a cached result for this module, look up the pass and run // If we don't have a cached result for this module, look up the pass and run
// it to produce a result, which we then add to the cache. // it to produce a result, which we then add to the cache.
if (Inserted) if (Inserted)
RI->second = lookupPass(PassID).run(M, this); RI->second = std::move(lookupPass(PassID).run(M, this));
return *RI->second; return *RI->second;
} }
@ -122,7 +122,7 @@ FunctionAnalysisManager::getResultImpl(void *PassID, Function *F) {
// run it to produce a result, which we then add to the cache. // run it to produce a result, which we then add to the cache.
if (Inserted) { if (Inserted) {
FunctionAnalysisResultListT &ResultList = FunctionAnalysisResultLists[F]; FunctionAnalysisResultListT &ResultList = FunctionAnalysisResultLists[F];
ResultList.push_back(std::make_pair(PassID, lookupPass(PassID).run(F, this))); ResultList.emplace_back(PassID, lookupPass(PassID).run(F, this));
RI->second = std::prev(ResultList.end()); RI->second = std::prev(ResultList.end());
} }

View File

@ -101,7 +101,7 @@ static bool parseFunctionPassPipeline(FunctionPassManager &FPM,
PipelineText = PipelineText.substr(1); PipelineText = PipelineText.substr(1);
// Add the nested pass manager with the appropriate adaptor. // Add the nested pass manager with the appropriate adaptor.
FPM.addPass(NestedFPM); FPM.addPass(std::move(NestedFPM));
} else { } else {
// Otherwise try to parse a pass name. // Otherwise try to parse a pass name.
size_t End = PipelineText.find_first_of(",)"); size_t End = PipelineText.find_first_of(",)");
@ -138,7 +138,7 @@ static bool parseModulePassPipeline(ModulePassManager &MPM,
PipelineText = PipelineText.substr(1); PipelineText = PipelineText.substr(1);
// Now add the nested manager as a module pass. // Now add the nested manager as a module pass.
MPM.addPass(NestedMPM); MPM.addPass(std::move(NestedMPM));
} else if (PipelineText.startswith("function(")) { } else if (PipelineText.startswith("function(")) {
FunctionPassManager NestedFPM; FunctionPassManager NestedFPM;
@ -151,7 +151,7 @@ static bool parseModulePassPipeline(ModulePassManager &MPM,
PipelineText = PipelineText.substr(1); PipelineText = PipelineText.substr(1);
// Add the nested pass manager with the appropriate adaptor. // Add the nested pass manager with the appropriate adaptor.
MPM.addPass(createModuleToFunctionPassAdaptor(NestedFPM)); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(NestedFPM)));
} else { } else {
// Otherwise try to parse a pass name. // Otherwise try to parse a pass name.
size_t End = PipelineText.find_first_of(",)"); size_t End = PipelineText.find_first_of(",)");
@ -185,7 +185,7 @@ bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) || if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) ||
!PipelineText.empty()) !PipelineText.empty())
return false; return false;
MPM.addPass(createModuleToFunctionPassAdaptor(FPM)); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
return true; return true;
} }
@ -201,7 +201,7 @@ bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) || if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) ||
!PipelineText.empty()) !PipelineText.empty())
return false; return false;
MPM.addPass(createModuleToFunctionPassAdaptor(FPM)); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
return true; return true;
} }

View File

@ -207,59 +207,69 @@ TEST_F(PassManagerTest, Basic) {
ModulePassManager MPM; ModulePassManager MPM;
// Count the runs over a Function. // Count the runs over a Function.
FunctionPassManager FPM1;
int FunctionPassRunCount1 = 0; int FunctionPassRunCount1 = 0;
int AnalyzedInstrCount1 = 0; int AnalyzedInstrCount1 = 0;
int AnalyzedFunctionCount1 = 0; int AnalyzedFunctionCount1 = 0;
FPM1.addPass(TestFunctionPass(FunctionPassRunCount1, AnalyzedInstrCount1, {
AnalyzedFunctionCount1)); FunctionPassManager FPM;
MPM.addPass(createModuleToFunctionPassAdaptor(FPM1)); FPM.addPass(TestFunctionPass(FunctionPassRunCount1, AnalyzedInstrCount1,
AnalyzedFunctionCount1));
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
// Count the runs over a module. // Count the runs over a module.
int ModulePassRunCount = 0; int ModulePassRunCount = 0;
MPM.addPass(TestModulePass(ModulePassRunCount)); MPM.addPass(TestModulePass(ModulePassRunCount));
// Count the runs over a Function in a separate manager. // Count the runs over a Function in a separate manager.
FunctionPassManager FPM2;
int FunctionPassRunCount2 = 0; int FunctionPassRunCount2 = 0;
int AnalyzedInstrCount2 = 0; int AnalyzedInstrCount2 = 0;
int AnalyzedFunctionCount2 = 0; int AnalyzedFunctionCount2 = 0;
FPM2.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2, {
AnalyzedFunctionCount2)); FunctionPassManager FPM;
MPM.addPass(createModuleToFunctionPassAdaptor(FPM2)); FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
AnalyzedFunctionCount2));
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
// A third function pass manager but with only preserving intervening passes // A third function pass manager but with only preserving intervening passes
// and with a function pass that invalidates exactly one analysis. // and with a function pass that invalidates exactly one analysis.
MPM.addPass(TestPreservingModulePass()); MPM.addPass(TestPreservingModulePass());
FunctionPassManager FPM3;
int FunctionPassRunCount3 = 0; int FunctionPassRunCount3 = 0;
int AnalyzedInstrCount3 = 0; int AnalyzedInstrCount3 = 0;
int AnalyzedFunctionCount3 = 0; int AnalyzedFunctionCount3 = 0;
FPM3.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3, {
AnalyzedFunctionCount3)); FunctionPassManager FPM;
FPM3.addPass(TestInvalidationFunctionPass("f")); FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
MPM.addPass(createModuleToFunctionPassAdaptor(FPM3)); AnalyzedFunctionCount3));
FPM.addPass(TestInvalidationFunctionPass("f"));
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
// A fourth function pass manager but with a minimal intervening passes. // A fourth function pass manager but with a minimal intervening passes.
MPM.addPass(TestMinPreservingModulePass()); MPM.addPass(TestMinPreservingModulePass());
FunctionPassManager FPM4;
int FunctionPassRunCount4 = 0; int FunctionPassRunCount4 = 0;
int AnalyzedInstrCount4 = 0; int AnalyzedInstrCount4 = 0;
int AnalyzedFunctionCount4 = 0; int AnalyzedFunctionCount4 = 0;
FPM4.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4, {
AnalyzedFunctionCount4)); FunctionPassManager FPM;
MPM.addPass(createModuleToFunctionPassAdaptor(FPM4)); FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
AnalyzedFunctionCount4));
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
// A fifth function pass manager but which uses only cached results. // A fifth function pass manager but which uses only cached results.
FunctionPassManager FPM5;
int FunctionPassRunCount5 = 0; int FunctionPassRunCount5 = 0;
int AnalyzedInstrCount5 = 0; int AnalyzedInstrCount5 = 0;
int AnalyzedFunctionCount5 = 0; int AnalyzedFunctionCount5 = 0;
FPM5.addPass(TestInvalidationFunctionPass("f")); {
FPM5.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5, FunctionPassManager FPM;
AnalyzedFunctionCount5, FPM.addPass(TestInvalidationFunctionPass("f"));
/*OnlyUseCachedResults=*/true)); FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
MPM.addPass(createModuleToFunctionPassAdaptor(FPM5)); AnalyzedFunctionCount5,
/*OnlyUseCachedResults=*/true));
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
MPM.run(M.get(), &MAM); MPM.run(M.get(), &MAM);