Index: llvm/trunk/include/llvm/IR/LLVMContext.h =================================================================== --- llvm/trunk/include/llvm/IR/LLVMContext.h +++ llvm/trunk/include/llvm/IR/LLVMContext.h @@ -315,9 +315,16 @@ return OptionRegistry::instance().template get(); } - /// \brief Access the object which manages optimization bisection for failure - /// analysis. - OptPassGate &getOptPassGate(); + /// \brief Access the object which can disable optional passes and individual + /// optimizations at compile time. + OptPassGate &getOptPassGate() const; + + /// \brief Set the object which can disable optional passes and individual + /// optimizations at compile time. + /// + /// The lifetime of the object must be guaranteed to extend as long as the + /// LLVMContext is used by compilation. + void setOptPassGate(OptPassGate&); private: // Module needs access to the add/removeModule methods. Index: llvm/trunk/lib/IR/LLVMContext.cpp =================================================================== --- llvm/trunk/lib/IR/LLVMContext.cpp +++ llvm/trunk/lib/IR/LLVMContext.cpp @@ -332,10 +332,14 @@ pImpl->DiscardValueNames = Discard; } -OptPassGate &LLVMContext::getOptPassGate() { +OptPassGate &LLVMContext::getOptPassGate() const { return pImpl->getOptPassGate(); } +void LLVMContext::setOptPassGate(OptPassGate& OPG) { + pImpl->setOptPassGate(OPG); +} + const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const { return pImpl->DiagHandler.get(); } Index: llvm/trunk/lib/IR/LLVMContextImpl.h =================================================================== --- llvm/trunk/lib/IR/LLVMContextImpl.h +++ llvm/trunk/lib/IR/LLVMContextImpl.h @@ -1355,9 +1355,18 @@ /// Destroy the ConstantArrays if they are not used. void dropTriviallyDeadConstantArrays(); - /// \brief Access the object which manages optimization bisection for failure - /// analysis. - OptPassGate &getOptPassGate(); + mutable OptPassGate *OPG = nullptr; + + /// \brief Access the object which can disable optional passes and individual + /// optimizations at compile time. + OptPassGate &getOptPassGate() const; + + /// \brief Set the object which can disable optional passes and individual + /// optimizations at compile time. + /// + /// The lifetime of the object must be guaranteed to extend as long as the + /// LLVMContext is used by compilation. + void setOptPassGate(OptPassGate&); }; } // end namespace llvm Index: llvm/trunk/lib/IR/LLVMContextImpl.cpp =================================================================== --- llvm/trunk/lib/IR/LLVMContextImpl.cpp +++ llvm/trunk/lib/IR/LLVMContextImpl.cpp @@ -233,6 +233,12 @@ /// enabled in order to enable a consistent bisect count. static ManagedStatic OptBisector; -OptPassGate &LLVMContextImpl::getOptPassGate() { - return *OptBisector; +OptPassGate &LLVMContextImpl::getOptPassGate() const { + if (!OPG) + OPG = &(*OptBisector); + return *OPG; +} + +void LLVMContextImpl::setOptPassGate(OptPassGate& OPG) { + this->OPG = &OPG; } Index: llvm/trunk/unittests/IR/LegacyPassManagerTest.cpp =================================================================== --- llvm/trunk/unittests/IR/LegacyPassManagerTest.cpp +++ llvm/trunk/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,67 @@ delete M; } + // Skips or runs optional passes. + struct CustomOptPassGate : public OptPassGate { + bool Skip; + CustomOptPassGate(bool Skip) : Skip(Skip) { } + bool shouldRunPass(const Pass *P, const Module &U) { 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, CustomOptPassGate) { + LLVMContext Context0; + LLVMContext Context1; + LLVMContext Context2; + CustomOptPassGate SkipOptionalPasses(true); + CustomOptPassGate 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.setOptPassGate(SkipOptionalPasses); + Context2.setOptPassGate(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);