1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00
llvm-mirror/lib/IR/Pass.cpp
Bjorn Pettersson be875842f9 [PM] Avoid duplicates in the Used/Preserved/Required sets
The pass analysis uses "sets" implemented using a SmallVector type
to keep track of Used, Preserved, Required and RequiredTransitive
passes. When having nested analyses we could end up with duplicates
in those sets, as there was no checks to see if a pass already
existed in the "set" before pushing to the vectors. This idea with
this patch is to avoid such duplicates by avoiding pushing elements
that already is contained when adding elements to those sets.

To align with the above PMDataManager::collectRequiredAndUsedAnalyses
is changed to skip adding both the Required and RequiredTransitive
passes to its result vectors (since RequiredTransitive always is
a subset of Required we ended up with duplicates when traversing
both sets).

Main goal with this is to avoid spending time verifying the same
analysis mulitple times in PMDataManager::verifyPreservedAnalysis
when iterating over the Preserved "set". It is assumed that removing
duplicates from a "set" shouldn't have any other negative impact
(I have not seen any problems so far). If this ends up causing
problems one could do some uniqueness filtering of the vector being
traversed in verifyPreservedAnalysis instead.

Reviewed By: foad

Differential Revision: https://reviews.llvm.org/D94416
2021-01-20 13:55:18 +01:00

282 lines
8.3 KiB
C++

//===- 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/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/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) != 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;
}
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)
pushUnique(Preserved, PI->getTypeInfo());
return *this;
}
AnalysisUsage &AnalysisUsage::addRequiredID(const void *ID) {
pushUnique(Required, ID);
return *this;
}
AnalysisUsage &AnalysisUsage::addRequiredID(char &ID) {
pushUnique(Required, &ID);
return *this;
}
AnalysisUsage &AnalysisUsage::addRequiredTransitiveID(char &ID) {
pushUnique(Required, &ID);
pushUnique(RequiredTransitive, &ID);
return *this;
}