diff options
Diffstat (limited to 'llvm/lib/IR/Pass.cpp')
-rw-r--r-- | llvm/lib/IR/Pass.cpp | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/llvm/lib/IR/Pass.cpp b/llvm/lib/IR/Pass.cpp new file mode 100644 index 000000000000..699a7e17c0cb --- /dev/null +++ b/llvm/lib/IR/Pass.cpp @@ -0,0 +1,328 @@ +//===- Pass.cpp - LLVM Pass Infrastructure Implementation -----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the LLVM Pass infrastructure. It is primarily +// responsible with ensuring that passes are executed and batched together +// optimally. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Pass.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/IRPrintingPasses.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassNameParser.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/OptBisect.h" +#include "llvm/PassInfo.h" +#include "llvm/PassRegistry.h" +#include "llvm/PassSupport.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> + +using namespace llvm; + +#define DEBUG_TYPE "ir" + +//===----------------------------------------------------------------------===// +// Pass Implementation +// + +// Force out-of-line virtual method. +Pass::~Pass() { + delete Resolver; +} + +// Force out-of-line virtual method. +ModulePass::~ModulePass() = default; + +Pass *ModulePass::createPrinterPass(raw_ostream &OS, + const std::string &Banner) const { + return createPrintModulePass(OS, Banner); +} + +PassManagerType ModulePass::getPotentialPassManagerType() const { + return PMT_ModulePassManager; +} + +static std::string getDescription(const Module &M) { + return "module (" + M.getName().str() + ")"; +} + +bool ModulePass::skipModule(Module &M) const { + OptPassGate &Gate = M.getContext().getOptPassGate(); + return Gate.isEnabled() && !Gate.shouldRunPass(this, getDescription(M)); +} + +bool Pass::mustPreserveAnalysisID(char &AID) const { + return Resolver->getAnalysisIfAvailable(&AID, true) != nullptr; +} + +// dumpPassStructure - Implement the -debug-pass=Structure option +void Pass::dumpPassStructure(unsigned Offset) { + dbgs().indent(Offset*2) << getPassName() << "\n"; +} + +/// getPassName - Return a nice clean name for a pass. This usually +/// implemented in terms of the name that is registered by one of the +/// Registration templates, but can be overloaded directly. +StringRef Pass::getPassName() const { + AnalysisID AID = getPassID(); + const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(AID); + if (PI) + return PI->getPassName(); + return "Unnamed pass: implement Pass::getPassName()"; +} + +void Pass::preparePassManager(PMStack &) { + // By default, don't do anything. +} + +PassManagerType Pass::getPotentialPassManagerType() const { + // Default implementation. + return PMT_Unknown; +} + +void Pass::getAnalysisUsage(AnalysisUsage &) const { + // By default, no analysis results are used, all are invalidated. +} + +void Pass::releaseMemory() { + // By default, don't do anything. +} + +void Pass::verifyAnalysis() const { + // By default, don't do anything. +} + +void *Pass::getAdjustedAnalysisPointer(AnalysisID AID) { + return this; +} + +ImmutablePass *Pass::getAsImmutablePass() { + return nullptr; +} + +PMDataManager *Pass::getAsPMDataManager() { + return nullptr; +} + +void Pass::setResolver(AnalysisResolver *AR) { + assert(!Resolver && "Resolver is already set"); + Resolver = AR; +} + +// print - Print out the internal state of the pass. This is called by Analyze +// to print out the contents of an analysis. Otherwise it is not necessary to +// implement this method. +void Pass::print(raw_ostream &OS, const Module *) const { + OS << "Pass::print not implemented for pass: '" << getPassName() << "'!\n"; +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +// dump - call print(cerr); +LLVM_DUMP_METHOD void Pass::dump() const { + print(dbgs(), nullptr); +} +#endif + +//===----------------------------------------------------------------------===// +// ImmutablePass Implementation +// +// Force out-of-line virtual method. +ImmutablePass::~ImmutablePass() = default; + +void ImmutablePass::initializePass() { + // By default, don't do anything. +} + +//===----------------------------------------------------------------------===// +// FunctionPass Implementation +// + +Pass *FunctionPass::createPrinterPass(raw_ostream &OS, + const std::string &Banner) const { + return createPrintFunctionPass(OS, Banner); +} + +PassManagerType FunctionPass::getPotentialPassManagerType() const { + return PMT_FunctionPassManager; +} + +static std::string getDescription(const Function &F) { + return "function (" + F.getName().str() + ")"; +} + +bool FunctionPass::skipFunction(const Function &F) const { + OptPassGate &Gate = F.getContext().getOptPassGate(); + if (Gate.isEnabled() && !Gate.shouldRunPass(this, getDescription(F))) + return true; + + if (F.hasOptNone()) { + LLVM_DEBUG(dbgs() << "Skipping pass '" << getPassName() << "' on function " + << F.getName() << "\n"); + return true; + } + return false; +} + +//===----------------------------------------------------------------------===// +// BasicBlockPass Implementation +// + +Pass *BasicBlockPass::createPrinterPass(raw_ostream &OS, + const std::string &Banner) const { + return createPrintBasicBlockPass(OS, Banner); +} + +bool BasicBlockPass::doInitialization(Function &) { + // By default, don't do anything. + return false; +} + +bool BasicBlockPass::doFinalization(Function &) { + // By default, don't do anything. + return false; +} + +static std::string getDescription(const BasicBlock &BB) { + return "basic block (" + BB.getName().str() + ") in function (" + + BB.getParent()->getName().str() + ")"; +} + +bool BasicBlockPass::skipBasicBlock(const BasicBlock &BB) const { + const Function *F = BB.getParent(); + if (!F) + return false; + OptPassGate &Gate = F->getContext().getOptPassGate(); + if (Gate.isEnabled() && !Gate.shouldRunPass(this, getDescription(BB))) + return true; + if (F->hasOptNone()) { + // Report this only once per function. + if (&BB == &F->getEntryBlock()) + LLVM_DEBUG(dbgs() << "Skipping pass '" << getPassName() + << "' on function " << F->getName() << "\n"); + return true; + } + return false; +} + +PassManagerType BasicBlockPass::getPotentialPassManagerType() const { + return PMT_BasicBlockPassManager; +} + +const PassInfo *Pass::lookupPassInfo(const void *TI) { + return PassRegistry::getPassRegistry()->getPassInfo(TI); +} + +const PassInfo *Pass::lookupPassInfo(StringRef Arg) { + return PassRegistry::getPassRegistry()->getPassInfo(Arg); +} + +Pass *Pass::createPass(AnalysisID ID) { + const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(ID); + if (!PI) + return nullptr; + return PI->createPass(); +} + +//===----------------------------------------------------------------------===// +// Analysis Group Implementation Code +//===----------------------------------------------------------------------===// + +// RegisterAGBase implementation + +RegisterAGBase::RegisterAGBase(StringRef Name, const void *InterfaceID, + const void *PassID, bool isDefault) + : PassInfo(Name, InterfaceID) { + PassRegistry::getPassRegistry()->registerAnalysisGroup(InterfaceID, PassID, + *this, isDefault); +} + +//===----------------------------------------------------------------------===// +// PassRegistrationListener implementation +// + +// enumeratePasses - Iterate over the registered passes, calling the +// passEnumerate callback on each PassInfo object. +void PassRegistrationListener::enumeratePasses() { + PassRegistry::getPassRegistry()->enumerateWith(this); +} + +PassNameParser::PassNameParser(cl::Option &O) + : cl::parser<const PassInfo *>(O) { + PassRegistry::getPassRegistry()->addRegistrationListener(this); +} + +// This only gets called during static destruction, in which case the +// PassRegistry will have already been destroyed by llvm_shutdown(). So +// attempting to remove the registration listener is an error. +PassNameParser::~PassNameParser() = default; + +//===----------------------------------------------------------------------===// +// AnalysisUsage Class Implementation +// + +namespace { + +struct GetCFGOnlyPasses : public PassRegistrationListener { + using VectorType = AnalysisUsage::VectorType; + + VectorType &CFGOnlyList; + + GetCFGOnlyPasses(VectorType &L) : CFGOnlyList(L) {} + + void passEnumerate(const PassInfo *P) override { + if (P->isCFGOnlyPass()) + CFGOnlyList.push_back(P->getTypeInfo()); + } +}; + +} // end anonymous namespace + +// setPreservesCFG - This function should be called to by the pass, iff they do +// not: +// +// 1. Add or remove basic blocks from the function +// 2. Modify terminator instructions in any way. +// +// This function annotates the AnalysisUsage info object to say that analyses +// that only depend on the CFG are preserved by this pass. +void AnalysisUsage::setPreservesCFG() { + // Since this transformation doesn't modify the CFG, it preserves all analyses + // that only depend on the CFG (like dominators, loop info, etc...) + GetCFGOnlyPasses(Preserved).enumeratePasses(); +} + +AnalysisUsage &AnalysisUsage::addPreserved(StringRef Arg) { + const PassInfo *PI = Pass::lookupPassInfo(Arg); + // If the pass exists, preserve it. Otherwise silently do nothing. + if (PI) Preserved.push_back(PI->getTypeInfo()); + return *this; +} + +AnalysisUsage &AnalysisUsage::addRequiredID(const void *ID) { + Required.push_back(ID); + return *this; +} + +AnalysisUsage &AnalysisUsage::addRequiredID(char &ID) { + Required.push_back(&ID); + return *this; +} + +AnalysisUsage &AnalysisUsage::addRequiredTransitiveID(char &ID) { + Required.push_back(&ID); + RequiredTransitive.push_back(&ID); + return *this; +} |