#ifndef LLVM_ANALYSIS_CGSCCPASSMANAGER_H
#define LLVM_ANALYSIS_CGSCCPASSMANAGER_H
#include "llvm/ADT/MapVector.h"
#include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <utility>
namespace llvm {
class Function;
class Value;
template <typename T, unsigned int N> class SmallPriorityWorklist;
struct CGSCCUpdateResult;
class Module;
#define DEBUG_TYPE "cgscc"
extern template class AllAnalysesOn<LazyCallGraph::SCC>;
extern template class AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>;
using CGSCCAnalysisManager =
AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>;
template <>
PreservedAnalyses
PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
CGSCCUpdateResult &>::run(LazyCallGraph::SCC &InitialC,
CGSCCAnalysisManager &AM,
LazyCallGraph &G, CGSCCUpdateResult &UR);
extern template class PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager,
LazyCallGraph &, CGSCCUpdateResult &>;
using CGSCCPassManager =
PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
CGSCCUpdateResult &>;
template <typename AnalysisT>
struct RequireAnalysisPass<AnalysisT, LazyCallGraph::SCC, CGSCCAnalysisManager,
LazyCallGraph &, CGSCCUpdateResult &>
: PassInfoMixin<RequireAnalysisPass<AnalysisT, LazyCallGraph::SCC,
CGSCCAnalysisManager, LazyCallGraph &,
CGSCCUpdateResult &>> {
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
LazyCallGraph &CG, CGSCCUpdateResult &) {
(void)AM.template getResult<AnalysisT>(C, CG);
return PreservedAnalyses::all();
}
void printPipeline(raw_ostream &OS,
function_ref<StringRef(StringRef)> MapClassName2PassName) {
auto ClassName = AnalysisT::name();
auto PassName = MapClassName2PassName(ClassName);
OS << "require<" << PassName << ">";
}
};
using CGSCCAnalysisManagerModuleProxy =
InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>;
template <> class CGSCCAnalysisManagerModuleProxy::Result {
public:
explicit Result(CGSCCAnalysisManager &InnerAM, LazyCallGraph &G)
: InnerAM(&InnerAM), G(&G) {}
CGSCCAnalysisManager &getManager() { return *InnerAM; }
bool invalidate(Module &M, const PreservedAnalyses &PA,
ModuleAnalysisManager::Invalidator &Inv);
private:
CGSCCAnalysisManager *InnerAM;
LazyCallGraph *G;
};
template <>
CGSCCAnalysisManagerModuleProxy::Result
CGSCCAnalysisManagerModuleProxy::run(Module &M, ModuleAnalysisManager &AM);
extern template class InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>;
extern template class OuterAnalysisManagerProxy<
ModuleAnalysisManager, LazyCallGraph::SCC, LazyCallGraph &>;
using ModuleAnalysisManagerCGSCCProxy =
OuterAnalysisManagerProxy<ModuleAnalysisManager, LazyCallGraph::SCC,
LazyCallGraph &>;
struct CGSCCUpdateResult {
SmallPriorityWorklist<LazyCallGraph::RefSCC *, 1> &RCWorklist;
SmallPriorityWorklist<LazyCallGraph::SCC *, 1> &CWorklist;
SmallPtrSetImpl<LazyCallGraph::RefSCC *> &InvalidatedRefSCCs;
SmallPtrSetImpl<LazyCallGraph::SCC *> &InvalidatedSCCs;
LazyCallGraph::SCC *UpdatedC;
PreservedAnalyses CrossSCCPA;
SmallDenseSet<std::pair<LazyCallGraph::Node *, LazyCallGraph::SCC *>, 4>
&InlinedInternalEdges;
SmallMapVector<Value *, WeakTrackingVH, 16> IndirectVHs;
};
class ModuleToPostOrderCGSCCPassAdaptor
: public PassInfoMixin<ModuleToPostOrderCGSCCPassAdaptor> {
public:
using PassConceptT =
detail::PassConcept<LazyCallGraph::SCC, CGSCCAnalysisManager,
LazyCallGraph &, CGSCCUpdateResult &>;
explicit ModuleToPostOrderCGSCCPassAdaptor(std::unique_ptr<PassConceptT> Pass)
: Pass(std::move(Pass)) {}
ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
: Pass(std::move(Arg.Pass)) {}
friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
ModuleToPostOrderCGSCCPassAdaptor &RHS) {
std::swap(LHS.Pass, RHS.Pass);
}
ModuleToPostOrderCGSCCPassAdaptor &
operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
swap(*this, RHS);
return *this;
}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
void printPipeline(raw_ostream &OS,
function_ref<StringRef(StringRef)> MapClassName2PassName) {
OS << "cgscc(";
Pass->printPipeline(OS, MapClassName2PassName);
OS << ")";
}
static bool isRequired() { return true; }
private:
std::unique_ptr<PassConceptT> Pass;
};
template <typename CGSCCPassT>
ModuleToPostOrderCGSCCPassAdaptor
createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT &&Pass) {
using PassModelT = detail::PassModel<LazyCallGraph::SCC, CGSCCPassT,
PreservedAnalyses, CGSCCAnalysisManager,
LazyCallGraph &, CGSCCUpdateResult &>;
return ModuleToPostOrderCGSCCPassAdaptor(
std::unique_ptr<ModuleToPostOrderCGSCCPassAdaptor::PassConceptT>(
new PassModelT(std::forward<CGSCCPassT>(Pass))));
}
class FunctionAnalysisManagerCGSCCProxy
: public AnalysisInfoMixin<FunctionAnalysisManagerCGSCCProxy> {
public:
class Result {
public:
explicit Result() : FAM(nullptr) {}
explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
void updateFAM(FunctionAnalysisManager &FAM) { this->FAM = &FAM; }
FunctionAnalysisManager &getManager() {
assert(FAM);
return *FAM;
}
bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
CGSCCAnalysisManager::Invalidator &Inv);
private:
FunctionAnalysisManager *FAM;
};
Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &);
private:
friend AnalysisInfoMixin<FunctionAnalysisManagerCGSCCProxy>;
static AnalysisKey Key;
};
extern template class OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>;
using CGSCCAnalysisManagerFunctionProxy =
OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>;
LazyCallGraph::SCC &updateCGAndAnalysisManagerForFunctionPass(
LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
FunctionAnalysisManager &FAM);
LazyCallGraph::SCC &updateCGAndAnalysisManagerForCGSCCPass(
LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
FunctionAnalysisManager &FAM);
class CGSCCToFunctionPassAdaptor
: public PassInfoMixin<CGSCCToFunctionPassAdaptor> {
public:
using PassConceptT = detail::PassConcept<Function, FunctionAnalysisManager>;
explicit CGSCCToFunctionPassAdaptor(std::unique_ptr<PassConceptT> Pass,
bool EagerlyInvalidate, bool NoRerun)
: Pass(std::move(Pass)), EagerlyInvalidate(EagerlyInvalidate),
NoRerun(NoRerun) {}
CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
: Pass(std::move(Arg.Pass)), EagerlyInvalidate(Arg.EagerlyInvalidate),
NoRerun(Arg.NoRerun) {}
friend void swap(CGSCCToFunctionPassAdaptor &LHS,
CGSCCToFunctionPassAdaptor &RHS) {
std::swap(LHS.Pass, RHS.Pass);
}
CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) {
swap(*this, RHS);
return *this;
}
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
LazyCallGraph &CG, CGSCCUpdateResult &UR);
void printPipeline(raw_ostream &OS,
function_ref<StringRef(StringRef)> MapClassName2PassName) {
OS << "function";
if (EagerlyInvalidate)
OS << "<eager-inv>";
OS << "(";
Pass->printPipeline(OS, MapClassName2PassName);
OS << ")";
}
static bool isRequired() { return true; }
private:
std::unique_ptr<PassConceptT> Pass;
bool EagerlyInvalidate;
bool NoRerun;
};
template <typename FunctionPassT>
CGSCCToFunctionPassAdaptor
createCGSCCToFunctionPassAdaptor(FunctionPassT &&Pass,
bool EagerlyInvalidate = false,
bool NoRerun = false) {
using PassModelT =
detail::PassModel<Function, FunctionPassT, PreservedAnalyses,
FunctionAnalysisManager>;
return CGSCCToFunctionPassAdaptor(
std::unique_ptr<CGSCCToFunctionPassAdaptor::PassConceptT>(
new PassModelT(std::forward<FunctionPassT>(Pass))),
EagerlyInvalidate, NoRerun);
}
class ShouldNotRunFunctionPassesAnalysis
: public AnalysisInfoMixin<ShouldNotRunFunctionPassesAnalysis> {
public:
static AnalysisKey Key;
struct Result {};
Result run(Function &F, FunctionAnalysisManager &FAM) { return Result(); }
};
class DevirtSCCRepeatedPass : public PassInfoMixin<DevirtSCCRepeatedPass> {
public:
using PassConceptT =
detail::PassConcept<LazyCallGraph::SCC, CGSCCAnalysisManager,
LazyCallGraph &, CGSCCUpdateResult &>;
explicit DevirtSCCRepeatedPass(std::unique_ptr<PassConceptT> Pass,
int MaxIterations)
: Pass(std::move(Pass)), MaxIterations(MaxIterations) {}
PreservedAnalyses run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM,
LazyCallGraph &CG, CGSCCUpdateResult &UR);
void printPipeline(raw_ostream &OS,
function_ref<StringRef(StringRef)> MapClassName2PassName) {
OS << "devirt<" << MaxIterations << ">(";
Pass->printPipeline(OS, MapClassName2PassName);
OS << ")";
}
private:
std::unique_ptr<PassConceptT> Pass;
int MaxIterations;
};
template <typename CGSCCPassT>
DevirtSCCRepeatedPass createDevirtSCCRepeatedPass(CGSCCPassT &&Pass,
int MaxIterations) {
using PassModelT = detail::PassModel<LazyCallGraph::SCC, CGSCCPassT,
PreservedAnalyses, CGSCCAnalysisManager,
LazyCallGraph &, CGSCCUpdateResult &>;
return DevirtSCCRepeatedPass(
std::unique_ptr<DevirtSCCRepeatedPass::PassConceptT>(
new PassModelT(std::forward<CGSCCPassT>(Pass))),
MaxIterations);
}
#undef DEBUG_TYPE
}
#endif