Index: include/llvm/Analysis/CallGraphSCCPass.h =================================================================== --- include/llvm/Analysis/CallGraphSCCPass.h +++ include/llvm/Analysis/CallGraphSCCPass.h @@ -20,6 +20,7 @@ #ifndef LLVM_ANALYSIS_CALLGRAPHSCCPASS_H #define LLVM_ANALYSIS_CALLGRAPHSCCPASS_H +#include "llvm/ADT/Any.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Pass.h" #include @@ -77,10 +78,11 @@ /// always explicitly call the implementation here. void getAnalysisUsage(AnalysisUsage &Info) const override; + virtual std::string getDescription(Any IR) const override; protected: /// Optional passes call this function to check whether the pass should be /// skipped. This is the case when optimization bisect is over the limit. - bool skipSCC(CallGraphSCC &SCC) const; + bool skipSCC(const CallGraphSCC &SCC) const; }; /// CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on. @@ -108,7 +110,7 @@ iterator begin() const { return Nodes.begin(); } iterator end() const { return Nodes.end(); } - const CallGraph &getCallGraph() { return CG; } + const CallGraph &getCallGraph() const { return CG; } }; void initializeDummyCGSCCPassPass(PassRegistry &); Index: include/llvm/Analysis/LoopPass.h =================================================================== --- include/llvm/Analysis/LoopPass.h +++ include/llvm/Analysis/LoopPass.h @@ -14,6 +14,7 @@ #ifndef LLVM_ANALYSIS_LOOPPASS_H #define LLVM_ANALYSIS_LOOPPASS_H +#include "llvm/ADT/Any.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/IR/LegacyPassManagers.h" #include "llvm/Pass.h" @@ -86,6 +87,7 @@ /// associated analysis values can be deleted. virtual void deleteAnalysisLoop(Loop *L) {} + virtual std::string getDescription(Any IR) const override; protected: /// Optional passes call this function to check whether the pass should be /// skipped. This is the case when Attribute::OptimizeNone is set or when Index: include/llvm/Analysis/RegionPass.h =================================================================== --- include/llvm/Analysis/RegionPass.h +++ include/llvm/Analysis/RegionPass.h @@ -15,6 +15,7 @@ #ifndef LLVM_ANALYSIS_REGIONPASS_H #define LLVM_ANALYSIS_REGIONPASS_H +#include "llvm/ADT/Any.h" #include "llvm/Analysis/RegionInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/LegacyPassManagers.h" @@ -78,10 +79,11 @@ } //@} + virtual std::string getDescription(Any IR) const override; protected: /// Optional passes call this function to check whether the pass should be /// skipped. This is the case when optimization bisect is over the limit. - bool skipRegion(Region &R) const; + bool skipRegion(const Region &R) const; }; /// The pass manager to schedule RegionPasses. Index: include/llvm/IR/OptBisect.h =================================================================== --- include/llvm/IR/OptBisect.h +++ include/llvm/IR/OptBisect.h @@ -14,17 +14,12 @@ #ifndef LLVM_IR_OPTBISECT_H #define LLVM_IR_OPTBISECT_H +#include "llvm/ADT/Any.h" #include "llvm/ADT/StringRef.h" namespace llvm { class Pass; -class Module; -class Function; -class BasicBlock; -class Region; -class Loop; -class CallGraphSCC; /// Extensions to this class implement mechanisms to disable passes and /// individual optimizations at compile time. @@ -32,12 +27,7 @@ public: virtual ~OptPassGate() = default; - virtual bool shouldRunPass(const Pass *P, const Module &U) { return true; } - virtual bool shouldRunPass(const Pass *P, const Function &U) {return true; } - virtual bool shouldRunPass(const Pass *P, const BasicBlock &U) { return true; } - virtual bool shouldRunPass(const Pass *P, const Region &U) { return true; } - virtual bool shouldRunPass(const Pass *P, const Loop &U) { return true; } - virtual bool shouldRunPass(const Pass *P, const CallGraphSCC &U) { return true; } + virtual bool shouldRunPass(const Pass *P, Any IR) { return true; } }; /// This class implements a mechanism to disable passes and individual @@ -69,12 +59,7 @@ /// Most passes should not call these routines directly. Instead, they are /// called through helper routines provided by the pass base classes. For /// instance, function passes should call FunctionPass::skipFunction(). - bool shouldRunPass(const Pass *P, const Module &U) override; - bool shouldRunPass(const Pass *P, const Function &U) override; - bool shouldRunPass(const Pass *P, const BasicBlock &U) override; - bool shouldRunPass(const Pass *P, const Region &U) override; - bool shouldRunPass(const Pass *P, const Loop &U) override; - bool shouldRunPass(const Pass *P, const CallGraphSCC &U) override; + bool shouldRunPass(const Pass *P, Any IR) override; private: bool checkPass(const StringRef PassName, const StringRef TargetDesc); Index: include/llvm/Pass.h =================================================================== --- include/llvm/Pass.h +++ include/llvm/Pass.h @@ -28,6 +28,7 @@ #ifndef LLVM_PASS_H #define LLVM_PASS_H +#include "llvm/ADT/Any.h" #include "llvm/ADT/StringRef.h" #include @@ -95,6 +96,13 @@ /// Registration templates, but can be overloaded directly. virtual StringRef getPassName() const; + /// getDescription - Return a string containing the information about units + /// the pass acts upon. Using the Any type allows calls from IR to + /// get information about Analysis passes. + virtual std::string getDescription(Any IR) const { + llvm_unreachable("Not Implemented"); + } + /// getPassID - Return the PassID number that corresponds to this pass. AnalysisID getPassID() const { return PassID; @@ -241,10 +249,11 @@ /// Return what kind of Pass Manager can manage this pass. PassManagerType getPotentialPassManagerType() const override; + virtual std::string getDescription(Any IR) const override; protected: /// Optional passes call this function to check whether the pass should be /// skipped. This is the case when optimization bisect is over the limit. - bool skipModule(Module &M) const; + bool skipModule(const Module &M) const; }; //===----------------------------------------------------------------------===// @@ -298,6 +307,7 @@ /// Return what kind of Pass Manager can manage this pass. PassManagerType getPotentialPassManagerType() const override; + virtual std::string getDescription(Any IR) const override; protected: /// Optional passes call this function to check whether the pass should be /// skipped. This is the case when Attribute::OptimizeNone is set or when @@ -343,6 +353,7 @@ /// Return what kind of Pass Manager can manage this pass. PassManagerType getPotentialPassManagerType() const override; + virtual std::string getDescription(Any IR) const override; protected: /// Optional passes call this function to check whether the pass should be /// skipped. This is the case when Attribute::OptimizeNone is set or when Index: lib/Analysis/CallGraphSCCPass.cpp =================================================================== --- lib/Analysis/CallGraphSCCPass.cpp +++ lib/Analysis/CallGraphSCCPass.cpp @@ -15,6 +15,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/CallGraphSCCPass.h" +#include "llvm/ADT/Any.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SCCIterator.h" #include "llvm/ADT/Statistic.h" @@ -608,6 +609,25 @@ AU.addPreserved(); } +std::string CallGraphSCCPass::getDescription(Any IR) const { + const CallGraphSCC *SCC = any_cast(IR); + std::string Desc = "SCC ("; + bool First = true; + for (CallGraphNode *CGN : *SCC) { + if (First) + First = false; + else + Desc += ", "; + Function *F = CGN->getFunction(); + if (F) + Desc += F->getName(); + else + Desc += "<>"; + } + Desc += ")"; + return Desc; +} + //===----------------------------------------------------------------------===// // PrintCallGraphPass Implementation //===----------------------------------------------------------------------===// @@ -681,11 +701,11 @@ return new PrintCallGraphPass(Banner, OS); } -bool CallGraphSCCPass::skipSCC(CallGraphSCC &SCC) const { +bool CallGraphSCCPass::skipSCC(const CallGraphSCC &SCC) const { return !SCC.getCallGraph().getModule() .getContext() .getOptPassGate() - .shouldRunPass(this, SCC); + .shouldRunPass(this, &SCC); } char DummyCGSCCPass::ID = 0; Index: lib/Analysis/LoopPass.cpp =================================================================== --- lib/Analysis/LoopPass.cpp +++ lib/Analysis/LoopPass.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/Any.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/LoopAnalysisManager.h" #include "llvm/IR/Dominators.h" @@ -389,7 +390,7 @@ return false; // Check the opt bisect limit. LLVMContext &Context = F->getContext(); - if (!Context.getOptPassGate().shouldRunPass(this, *L)) + if (!Context.getOptPassGate().shouldRunPass(this, L)) return true; // Check for the OptimizeNone attribute. if (F->hasFnAttribute(Attribute::OptimizeNone)) { @@ -402,6 +403,11 @@ return false; } +std::string LoopPass::getDescription(Any IR) const { + assert(any_isa(IR)); + return "loop"; +} + char LCSSAVerificationPass::ID = 0; INITIALIZE_PASS(LCSSAVerificationPass, "lcssa-verification", "LCSSA Verifier", false, false) Index: lib/Analysis/RegionPass.cpp =================================================================== --- lib/Analysis/RegionPass.cpp +++ lib/Analysis/RegionPass.cpp @@ -12,6 +12,7 @@ // Most of this code has been COPIED from LoopPass.cpp // //===----------------------------------------------------------------------===// +#include "llvm/ADT/Any.h" #include "llvm/Analysis/RegionPass.h" #include "llvm/IR/OptBisect.h" #include "llvm/IR/PassTimingInfo.h" @@ -278,9 +279,9 @@ return new PrintRegionPass(Banner, O); } -bool RegionPass::skipRegion(Region &R) const { +bool RegionPass::skipRegion(const Region &R) const { Function &F = *R.getEntry()->getParent(); - if (!F.getContext().getOptPassGate().shouldRunPass(this, R)) + if (!F.getContext().getOptPassGate().shouldRunPass(this, &R)) return true; if (F.hasFnAttribute(Attribute::OptimizeNone)) { @@ -292,3 +293,8 @@ } return false; } + +std::string RegionPass::getDescription(Any IR) const { + assert(any_isa(IR)); + return "region"; +} Index: lib/IR/OptBisect.cpp =================================================================== --- lib/IR/OptBisect.cpp +++ lib/IR/OptBisect.cpp @@ -13,14 +13,8 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/OptBisect.h" +#include "llvm/ADT/Any.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Analysis/CallGraph.h" -#include "llvm/Analysis/CallGraphSCCPass.h" -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/RegionInfo.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" @@ -46,73 +40,8 @@ << "(" << PassNum << ") " << Name << " on " << TargetDesc << "\n"; } -static std::string getDescription(const Module &M) { - return "module (" + M.getName().str() + ")"; -} - -static std::string getDescription(const Function &F) { - return "function (" + F.getName().str() + ")"; -} - -static std::string getDescription(const BasicBlock &BB) { - return "basic block (" + BB.getName().str() + ") in function (" + - BB.getParent()->getName().str() + ")"; -} - -static std::string getDescription(const Loop &L) { - // FIXME: Move into LoopInfo so we can get a better description - // (and avoid a circular dependency between IR and Analysis). - return "loop"; -} - -static std::string getDescription(const Region &R) { - // FIXME: Move into RegionInfo so we can get a better description - // (and avoid a circular dependency between IR and Analysis). - return "region"; -} - -static std::string getDescription(const CallGraphSCC &SCC) { - // FIXME: Move into CallGraphSCCPass to avoid circular dependency between - // IR and Analysis. - std::string Desc = "SCC ("; - bool First = true; - for (CallGraphNode *CGN : SCC) { - if (First) - First = false; - else - Desc += ", "; - Function *F = CGN->getFunction(); - if (F) - Desc += F->getName(); - else - Desc += "<>"; - } - Desc += ")"; - return Desc; -} - -bool OptBisect::shouldRunPass(const Pass *P, const Module &U) { - return !BisectEnabled || checkPass(P->getPassName(), getDescription(U)); -} - -bool OptBisect::shouldRunPass(const Pass *P, const Function &U) { - return !BisectEnabled || checkPass(P->getPassName(), getDescription(U)); -} - -bool OptBisect::shouldRunPass(const Pass *P, const BasicBlock &U) { - return !BisectEnabled || checkPass(P->getPassName(), getDescription(U)); -} - -bool OptBisect::shouldRunPass(const Pass *P, const Region &U) { - return !BisectEnabled || checkPass(P->getPassName(), getDescription(U)); -} - -bool OptBisect::shouldRunPass(const Pass *P, const Loop &U) { - return !BisectEnabled || checkPass(P->getPassName(), getDescription(U)); -} - -bool OptBisect::shouldRunPass(const Pass *P, const CallGraphSCC &U) { - return !BisectEnabled || checkPass(P->getPassName(), getDescription(U)); +bool OptBisect::shouldRunPass(const Pass *P, Any IR) { + return !BisectEnabled || checkPass(P->getPassName(), P->getDescription(IR)); } bool OptBisect::checkPass(const StringRef PassName, Index: lib/IR/Pass.cpp =================================================================== --- lib/IR/Pass.cpp +++ lib/IR/Pass.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Pass.h" +#include "llvm/ADT/Any.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" @@ -55,8 +56,13 @@ return PMT_ModulePassManager; } -bool ModulePass::skipModule(Module &M) const { - return !M.getContext().getOptPassGate().shouldRunPass(this, M); +bool ModulePass::skipModule(const Module &M) const { + return !M.getContext().getOptPassGate().shouldRunPass(this, &M); +} + +std::string ModulePass::getDescription(Any IR) const { + const Module *M = any_cast(IR); + return "module (" + M->getName().str() + ")"; } bool Pass::mustPreserveAnalysisID(char &AID) const { @@ -155,7 +161,7 @@ } bool FunctionPass::skipFunction(const Function &F) const { - if (!F.getContext().getOptPassGate().shouldRunPass(this, F)) + if (!F.getContext().getOptPassGate().shouldRunPass(this, &F)) return true; if (F.hasFnAttribute(Attribute::OptimizeNone)) { @@ -166,6 +172,10 @@ return false; } +std::string FunctionPass::getDescription(Any IR) const { + const Function *F = any_cast(IR); + return "function (" + F->getName().str() + ")"; +} //===----------------------------------------------------------------------===// // BasicBlockPass Implementation // @@ -189,7 +199,7 @@ const Function *F = BB.getParent(); if (!F) return false; - if (!F->getContext().getOptPassGate().shouldRunPass(this, BB)) + if (!F->getContext().getOptPassGate().shouldRunPass(this, &BB)) return true; if (F->hasFnAttribute(Attribute::OptimizeNone)) { // Report this only once per function. @@ -220,6 +230,12 @@ return PI->createPass(); } +std::string BasicBlockPass::getDescription(Any IR) const { + const BasicBlock *BB = any_cast(IR); + return "basic block (" + BB->getName().str() + ") in function (" + + BB->getParent()->getName().str() + ")"; +} + //===----------------------------------------------------------------------===// // Analysis Group Implementation Code //===----------------------------------------------------------------------===// Index: unittests/IR/LegacyPassManagerTest.cpp =================================================================== --- unittests/IR/LegacyPassManagerTest.cpp +++ unittests/IR/LegacyPassManagerTest.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/LegacyPassManager.h" +#include "llvm/ADT/Any.h" #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopPass.h" @@ -400,7 +401,11 @@ struct CustomOptPassGate : public OptPassGate { bool Skip; CustomOptPassGate(bool Skip) : Skip(Skip) { } - bool shouldRunPass(const Pass *P, const Module &U) { return !Skip; } + bool shouldRunPass(const Pass *P, Any IR) { + if (P->getPassKind() == PT_Module) + return !Skip; + return OptPassGate::shouldRunPass(P, IR); + } }; // Optional module pass.