Index: include/llvm/IR/LLVMContext.h =================================================================== --- include/llvm/IR/LLVMContext.h +++ include/llvm/IR/LLVMContext.h @@ -318,6 +318,11 @@ /// \brief Access the object which manages optimization bisection for failure /// analysis. OptBisect &getOptBisect(); + + /// \brief Set the object which manages optimization bisection for failure + /// analysis. + void setOptBisect(OptBisect&); + private: // Module needs access to the add/removeModule methods. friend class Module; Index: include/llvm/IR/OptBisect.h =================================================================== --- include/llvm/IR/OptBisect.h +++ include/llvm/IR/OptBisect.h @@ -36,6 +36,8 @@ /// through LLVMContext. OptBisect(); + virtual ~OptBisect() = default; + /// Checks the bisect limit to determine if the specified pass should run. /// /// This function will immediate return true if bisection is disabled. If the @@ -51,8 +53,8 @@ template bool shouldRunPass(const Pass *P, const UnitT &U); -private: - bool checkPass(const StringRef PassName, const StringRef TargetDesc); +protected: + virtual bool checkPass(const StringRef PassName, const StringRef TargetDesc); bool BisectEnabled = false; unsigned LastBisectNum = 0; Index: lib/IR/LLVMContext.cpp =================================================================== --- lib/IR/LLVMContext.cpp +++ lib/IR/LLVMContext.cpp @@ -336,6 +336,10 @@ return pImpl->getOptBisect(); } +void LLVMContext::setOptBisect(OptBisect& OB) { + pImpl->setOptBisect(OB); +} + const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const { return pImpl->DiagHandler.get(); } Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -1355,9 +1355,15 @@ /// Destroy the ConstantArrays if they are not used. void dropTriviallyDeadConstantArrays(); + OptBisect *OptBisector = nullptr; + /// \brief Access the object which manages optimization bisection for failure /// analysis. OptBisect &getOptBisect(); + + /// \brief Set the object which manages optimization bisection for failure + /// analysis. + void setOptBisect(OptBisect&); }; } // end namespace llvm Index: lib/IR/LLVMContextImpl.cpp =================================================================== --- lib/IR/LLVMContextImpl.cpp +++ lib/IR/LLVMContextImpl.cpp @@ -234,5 +234,11 @@ static ManagedStatic OptBisector; OptBisect &LLVMContextImpl::getOptBisect() { + if (!OptBisector) + OptBisector = &(*::OptBisector); return *OptBisector; } + +void LLVMContextImpl::setOptBisect(OptBisect& OB) { + OptBisector = &OB; +} Index: unittests/IR/LegacyPassManagerTest.cpp =================================================================== --- unittests/IR/LegacyPassManagerTest.cpp +++ unittests/IR/LegacyPassManagerTest.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/OptBisect.h" #include "llvm/Pass.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -396,6 +397,73 @@ delete M; } + // Skips or runs optional passes. + struct CustomOptBisect : public OptBisect { + bool Skip; + + CustomOptBisect(bool Skip) : Skip(Skip) { + BisectEnabled = true; + } + + bool checkPass(const llvm::StringRef PassName, const llvm::StringRef TargetDesc) { + return !Skip; + } + }; + + // Optional module pass. + struct ModuleOpt: public ModulePass { + char run = 0; + static char ID; + ModuleOpt() : ModulePass(ID) { } + bool runOnModule(Module &M) override { + if (!skipModule(M)) + run++; + return false; + } + }; + char ModuleOpt::ID=0; + + TEST(PassManager, CustomOptBisect) { + LLVMContext Context0; + LLVMContext Context1; + LLVMContext Context2; + CustomOptBisect SkipOptionalPasses(true); + CustomOptBisect RunOptionalPasses(false); + + Module M0("custom-opt-bisect", Context0); + Module M1("custom-opt-bisect", Context1); + Module M2("custom-opt-bisect2", Context2); + struct ModuleOpt *mOpt0 = new ModuleOpt(); + struct ModuleOpt *mOpt1 = new ModuleOpt(); + struct ModuleOpt *mOpt2 = new ModuleOpt(); + + mOpt0->run = mOpt1->run = mOpt2->run = 0; + + legacy::PassManager Passes0; + legacy::PassManager Passes1; + legacy::PassManager Passes2; + + Passes0.add(mOpt0); + Passes1.add(mOpt1); + Passes2.add(mOpt2); + + Context1.setOptBisect(SkipOptionalPasses); + Context2.setOptBisect(RunOptionalPasses); + + Passes0.run(M0); + Passes1.run(M1); + Passes2.run(M2); + + // By default optional passes are run. + EXPECT_EQ(1, mOpt0->run); + + // The first context skips optional passes. + EXPECT_EQ(0, mOpt1->run); + + // The second context runs optional passes. + EXPECT_EQ(1, mOpt2->run); + } + Module *makeLLVMModule(LLVMContext &Context) { // Module Construction Module *mod = new Module("test-mem", Context);