#ifndef LLVM_CODEGEN_CODEGENPASSBUILDER_H
#define LLVM_CODEGEN_CODEGENPASSBUILDER_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/CFLAndersAliasAnalysis.h"
#include "llvm/Analysis/CFLSteensAliasAnalysis.h"
#include "llvm/Analysis/ScopedNoAliasAA.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
#include "llvm/CodeGen/ExpandReductions.h"
#include "llvm/CodeGen/MachinePassManager.h"
#include "llvm/CodeGen/PreISelIntrinsicLowering.h"
#include "llvm/CodeGen/ReplaceWithVeclib.h"
#include "llvm/CodeGen/UnreachableBlockElim.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/CGPassBuilderOption.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Scalar/ConstantHoisting.h"
#include "llvm/Transforms/Scalar/LoopPassManager.h"
#include "llvm/Transforms/Scalar/LoopStrengthReduce.h"
#include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h"
#include "llvm/Transforms/Scalar/MergeICmps.h"
#include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h"
#include "llvm/Transforms/Scalar/ScalarizeMaskedMemIntrin.h"
#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
#include "llvm/Transforms/Utils/LowerInvoke.h"
#include <cassert>
#include <type_traits>
#include <utility>
namespace llvm {
#define DUMMY_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
struct PASS_NAME : public PassInfoMixin<PASS_NAME> { \
template <typename... Ts> PASS_NAME(Ts &&...) {} \
PreservedAnalyses run(Function &, FunctionAnalysisManager &) { \
return PreservedAnalyses::all(); \
} \
};
#define DUMMY_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
struct PASS_NAME : public PassInfoMixin<PASS_NAME> { \
template <typename... Ts> PASS_NAME(Ts &&...) {} \
PreservedAnalyses run(Module &, ModuleAnalysisManager &) { \
return PreservedAnalyses::all(); \
} \
};
#define DUMMY_MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
struct PASS_NAME : public PassInfoMixin<PASS_NAME> { \
template <typename... Ts> PASS_NAME(Ts &&...) {} \
Error run(Module &, MachineFunctionAnalysisManager &) { \
return Error::success(); \
} \
PreservedAnalyses run(MachineFunction &, \
MachineFunctionAnalysisManager &) { \
llvm_unreachable("this api is to make new PM api happy"); \
} \
static AnalysisKey Key; \
};
#define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
struct PASS_NAME : public PassInfoMixin<PASS_NAME> { \
template <typename... Ts> PASS_NAME(Ts &&...) {} \
PreservedAnalyses run(MachineFunction &, \
MachineFunctionAnalysisManager &) { \
return PreservedAnalyses::all(); \
} \
static AnalysisKey Key; \
};
#include "MachinePassRegistry.def"
template <typename DerivedT> class CodeGenPassBuilder {
public:
explicit CodeGenPassBuilder(LLVMTargetMachine &TM, CGPassBuilderOption Opts,
PassInstrumentationCallbacks *PIC)
: TM(TM), Opt(Opts), PIC(PIC) {
if (Opt.EnableIPRA)
TM.Options.EnableIPRA = *Opt.EnableIPRA;
if (Opt.EnableGlobalISelAbort)
TM.Options.GlobalISelAbort = *Opt.EnableGlobalISelAbort;
if (!Opt.OptimizeRegAlloc)
Opt.OptimizeRegAlloc = getOptLevel() != CodeGenOpt::None;
}
Error buildPipeline(ModulePassManager &MPM, MachineFunctionPassManager &MFPM,
raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
CodeGenFileType FileType) const;
void registerModuleAnalyses(ModuleAnalysisManager &) const;
void registerFunctionAnalyses(FunctionAnalysisManager &) const;
void registerMachineFunctionAnalyses(MachineFunctionAnalysisManager &) const;
std::pair<StringRef, bool> getPassNameFromLegacyName(StringRef) const;
void registerAnalyses(MachineFunctionAnalysisManager &MFAM) const {
registerModuleAnalyses(*MFAM.MAM);
registerFunctionAnalyses(*MFAM.FAM);
registerMachineFunctionAnalyses(MFAM);
}
PassInstrumentationCallbacks *getPassInstrumentationCallbacks() const {
return PIC;
}
protected:
template <typename PassT> using has_key_t = decltype(PassT::Key);
template <typename PassT>
using is_module_pass_t = decltype(std::declval<PassT &>().run(
std::declval<Module &>(), std::declval<ModuleAnalysisManager &>()));
template <typename PassT>
using is_function_pass_t = decltype(std::declval<PassT &>().run(
std::declval<Function &>(), std::declval<FunctionAnalysisManager &>()));
class AddIRPass {
public:
AddIRPass(ModulePassManager &MPM, bool DebugPM, bool Check = true)
: MPM(MPM) {
if (Check)
AddingFunctionPasses = false;
}
~AddIRPass() {
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
template <typename PassT>
std::enable_if_t<is_detected<is_function_pass_t, PassT>::value>
operator()(PassT &&Pass) {
if (AddingFunctionPasses && !*AddingFunctionPasses)
AddingFunctionPasses = true;
FPM.addPass(std::forward<PassT>(Pass));
}
template <typename PassT>
std::enable_if_t<is_detected<is_module_pass_t, PassT>::value &&
!is_detected<is_function_pass_t, PassT>::value>
operator()(PassT &&Pass) {
assert((!AddingFunctionPasses || !*AddingFunctionPasses) &&
"could not add module pass after adding function pass");
MPM.addPass(std::forward<PassT>(Pass));
}
private:
ModulePassManager &MPM;
FunctionPassManager FPM;
Optional<bool> AddingFunctionPasses;
};
class AddMachinePass {
public:
AddMachinePass(MachineFunctionPassManager &PM) : PM(PM) {}
template <typename PassT> void operator()(PassT &&Pass) {
static_assert(
is_detected<has_key_t, PassT>::value,
"Machine function pass must define a static member variable `Key`.");
for (auto &C : BeforeCallbacks)
if (!C(&PassT::Key))
return;
PM.addPass(std::forward<PassT>(Pass));
for (auto &C : AfterCallbacks)
C(&PassT::Key);
}
template <typename PassT> void insertPass(AnalysisKey *ID, PassT Pass) {
AfterCallbacks.emplace_back(
[this, ID, Pass = std::move(Pass)](AnalysisKey *PassID) {
if (PassID == ID)
this->PM.addPass(std::move(Pass));
});
}
void disablePass(AnalysisKey *ID) {
BeforeCallbacks.emplace_back(
[ID](AnalysisKey *PassID) { return PassID != ID; });
}
MachineFunctionPassManager releasePM() { return std::move(PM); }
private:
MachineFunctionPassManager &PM;
SmallVector<llvm::unique_function<bool(AnalysisKey *)>, 4> BeforeCallbacks;
SmallVector<llvm::unique_function<void(AnalysisKey *)>, 4> AfterCallbacks;
};
LLVMTargetMachine &TM;
CGPassBuilderOption Opt;
PassInstrumentationCallbacks *PIC;
void registerTargetAnalysis(ModuleAnalysisManager &) const {}
void registerTargetAnalysis(FunctionAnalysisManager &) const {}
void registerTargetAnalysis(MachineFunctionAnalysisManager &) const {}
std::pair<StringRef, bool> getTargetPassNameFromLegacyName(StringRef) const {
return {"", false};
}
template <typename TMC> TMC &getTM() const { return static_cast<TMC &>(TM); }
CodeGenOpt::Level getOptLevel() const { return TM.getOptLevel(); }
bool isGlobalISelAbortEnabled() const {
return TM.Options.GlobalISelAbort == GlobalISelAbortMode::Enable;
}
bool reportDiagnosticWhenGlobalISelFallback() const {
return TM.Options.GlobalISelAbort == GlobalISelAbortMode::DisableWithDiag;
}
Error addInstSelector(AddMachinePass &) const {
return make_error<StringError>("addInstSelector is not overridden",
inconvertibleErrorCode());
}
void addILPOpts(AddMachinePass &) const {}
void addPreRegAlloc(AddMachinePass &) const {}
void addPreRewrite(AddMachinePass &) const {}
void addPostRewrite(AddMachinePass &) const {}
void addPostRegAlloc(AddMachinePass &) const {}
void addPreSched2(AddMachinePass &) const {}
void addPreEmitPass(AddMachinePass &) const {}
void addPreEmitPass2(AddMachinePass &) const {}
void addPreISel(AddIRPass &) const {
llvm_unreachable("addPreISel is not overridden");
}
Error addIRTranslator(AddMachinePass &) const {
return make_error<StringError>("addIRTranslator is not overridden",
inconvertibleErrorCode());
}
void addPreLegalizeMachineIR(AddMachinePass &) const {}
Error addLegalizeMachineIR(AddMachinePass &) const {
return make_error<StringError>("addLegalizeMachineIR is not overridden",
inconvertibleErrorCode());
}
void addPreRegBankSelect(AddMachinePass &) const {}
Error addRegBankSelect(AddMachinePass &) const {
return make_error<StringError>("addRegBankSelect is not overridden",
inconvertibleErrorCode());
}
void addPreGlobalInstructionSelect(AddMachinePass &) const {}
Error addGlobalInstructionSelect(AddMachinePass &) const {
return make_error<StringError>(
"addGlobalInstructionSelect is not overridden",
inconvertibleErrorCode());
}
void addISelPasses(AddIRPass &) const;
Error addCoreISelPasses(AddMachinePass &) const;
Error addMachinePasses(AddMachinePass &) const;
void addPassesToHandleExceptions(AddIRPass &) const;
void addIRPasses(AddIRPass &) const;
void addCodeGenPrepare(AddIRPass &) const;
void addISelPrepare(AddIRPass &) const;
void addMachineSSAOptimization(AddMachinePass &) const;
Error addFastRegAlloc(AddMachinePass &) const;
void addOptimizedRegAlloc(AddMachinePass &) const;
void addMachineLateOptimization(AddMachinePass &) const;
void addGCPasses(AddMachinePass &) const {}
void addBlockPlacement(AddMachinePass &) const;
using CreateMCStreamer =
std::function<Expected<std::unique_ptr<MCStreamer>>(MCContext &)>;
void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const {
llvm_unreachable("addAsmPrinter is not overridden");
}
void addTargetRegisterAllocator(AddMachinePass &, bool Optimized) const;
void addRegAllocPass(AddMachinePass &, bool Optimized) const;
Error addRegAssignmentFast(AddMachinePass &) const;
Error addRegAssignmentOptimized(AddMachinePass &) const;
private:
DerivedT &derived() { return static_cast<DerivedT &>(*this); }
const DerivedT &derived() const {
return static_cast<const DerivedT &>(*this);
}
};
template <typename Derived>
Error CodeGenPassBuilder<Derived>::buildPipeline(
ModulePassManager &MPM, MachineFunctionPassManager &MFPM,
raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
CodeGenFileType FileType) const {
AddIRPass addIRPass(MPM, Opt.DebugPM);
addISelPasses(addIRPass);
AddMachinePass addPass(MFPM);
if (auto Err = addCoreISelPasses(addPass))
return std::move(Err);
if (auto Err = derived().addMachinePasses(addPass))
return std::move(Err);
derived().addAsmPrinter(
addPass, [this, &Out, DwoOut, FileType](MCContext &Ctx) {
return this->TM.createMCStreamer(Out, DwoOut, FileType, Ctx);
});
addPass(FreeMachineFunctionPass());
return Error::success();
}
static inline AAManager registerAAAnalyses(CFLAAType UseCFLAA) {
AAManager AA;
switch (UseCFLAA) {
case CFLAAType::Steensgaard:
AA.registerFunctionAnalysis<CFLSteensAA>();
break;
case CFLAAType::Andersen:
AA.registerFunctionAnalysis<CFLAndersAA>();
break;
case CFLAAType::Both:
AA.registerFunctionAnalysis<CFLAndersAA>();
AA.registerFunctionAnalysis<CFLSteensAA>();
break;
default:
break;
}
AA.registerFunctionAnalysis<TypeBasedAA>();
AA.registerFunctionAnalysis<ScopedNoAliasAA>();
AA.registerFunctionAnalysis<BasicAA>();
return AA;
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::registerModuleAnalyses(
ModuleAnalysisManager &MAM) const {
#define MODULE_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \
MAM.registerPass([&] { return PASS_NAME CONSTRUCTOR; });
#include "MachinePassRegistry.def"
derived().registerTargetAnalysis(MAM);
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::registerFunctionAnalyses(
FunctionAnalysisManager &FAM) const {
FAM.registerPass([this] { return registerAAAnalyses(this->Opt.UseCFLAA); });
#define FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \
FAM.registerPass([&] { return PASS_NAME CONSTRUCTOR; });
#include "MachinePassRegistry.def"
derived().registerTargetAnalysis(FAM);
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::registerMachineFunctionAnalyses(
MachineFunctionAnalysisManager &MFAM) const {
#define MACHINE_FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \
MFAM.registerPass([&] { return PASS_NAME CONSTRUCTOR; });
#include "MachinePassRegistry.def"
derived().registerTargetAnalysis(MFAM);
}
template <typename Derived>
std::pair<StringRef, bool>
CodeGenPassBuilder<Derived>::getPassNameFromLegacyName(StringRef Name) const {
std::pair<StringRef, bool> Ret;
if (Name.empty())
return Ret;
#define FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
if (Name == NAME) \
Ret = {#PASS_NAME, false};
#define DUMMY_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
if (Name == NAME) \
Ret = {#PASS_NAME, false};
#define MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
if (Name == NAME) \
Ret = {#PASS_NAME, false};
#define DUMMY_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
if (Name == NAME) \
Ret = {#PASS_NAME, false};
#define MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
if (Name == NAME) \
Ret = {#PASS_NAME, true};
#define DUMMY_MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
if (Name == NAME) \
Ret = {#PASS_NAME, true};
#define MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
if (Name == NAME) \
Ret = {#PASS_NAME, true};
#define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
if (Name == NAME) \
Ret = {#PASS_NAME, true};
#include "llvm/CodeGen/MachinePassRegistry.def"
if (Ret.first.empty())
Ret = derived().getTargetPassNameFromLegacyName(Name);
if (Ret.first.empty())
report_fatal_error(Twine('\"') + Twine(Name) +
Twine("\" pass could not be found."));
return Ret;
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::addISelPasses(AddIRPass &addPass) const {
if (TM.useEmulatedTLS())
addPass(LowerEmuTLSPass());
addPass(PreISelIntrinsicLoweringPass());
derived().addIRPasses(addPass);
derived().addCodeGenPrepare(addPass);
addPassesToHandleExceptions(addPass);
derived().addISelPrepare(addPass);
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::addIRPasses(AddIRPass &addPass) const {
if (!Opt.DisableVerify)
addPass(VerifierPass());
if (getOptLevel() != CodeGenOpt::None && !Opt.DisableLSR) {
addPass(createFunctionToLoopPassAdaptor(
LoopStrengthReducePass(), true, Opt.DebugPM));
if (Opt.PrintLSR)
addPass(PrintFunctionPass(dbgs(), "\n\n*** Code after LSR ***\n"));
}
if (getOptLevel() != CodeGenOpt::None) {
if (!Opt.DisableMergeICmps)
addPass(MergeICmpsPass());
addPass(ExpandMemCmpPass());
}
addPass(GCLoweringPass());
addPass(ShadowStackGCLoweringPass());
addPass(LowerConstantIntrinsicsPass());
addPass(UnreachableBlockElimPass());
if (getOptLevel() != CodeGenOpt::None && !Opt.DisableConstantHoisting)
addPass(ConstantHoistingPass());
if (getOptLevel() != CodeGenOpt::None)
addPass(ReplaceWithVeclib());
if (getOptLevel() != CodeGenOpt::None && !Opt.DisablePartialLibcallInlining)
addPass(PartiallyInlineLibCallsPass());
addPass(EntryExitInstrumenterPass(true));
addPass(ScalarizeMaskedMemIntrinPass());
addPass(ExpandReductionsPass());
if (getOptLevel() != CodeGenOpt::None && !Opt.DisableSelectOptimize)
addPass(SelectOptimizePass());
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::addPassesToHandleExceptions(
AddIRPass &addPass) const {
const MCAsmInfo *MCAI = TM.getMCAsmInfo();
assert(MCAI && "No MCAsmInfo");
switch (MCAI->getExceptionHandlingType()) {
case ExceptionHandling::SjLj:
addPass(SjLjEHPreparePass());
LLVM_FALLTHROUGH;
case ExceptionHandling::DwarfCFI:
case ExceptionHandling::ARM:
case ExceptionHandling::AIX:
addPass(DwarfEHPass(getOptLevel()));
break;
case ExceptionHandling::WinEH:
addPass(WinEHPass());
addPass(DwarfEHPass(getOptLevel()));
break;
case ExceptionHandling::Wasm:
addPass(WinEHPass(false));
addPass(WasmEHPass());
break;
case ExceptionHandling::None:
addPass(LowerInvokePass());
addPass(UnreachableBlockElimPass());
break;
}
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::addCodeGenPrepare(AddIRPass &addPass) const {
if (getOptLevel() != CodeGenOpt::None && !Opt.DisableCGP)
addPass(CodeGenPreparePass());
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::addISelPrepare(AddIRPass &addPass) const {
derived().addPreISel(addPass);
addPass(SafeStackPass());
addPass(StackProtectorPass());
if (Opt.PrintISelInput)
addPass(PrintFunctionPass(dbgs(),
"\n\n*** Final LLVM Code input to ISel ***\n"));
if (!Opt.DisableVerify)
addPass(VerifierPass());
}
template <typename Derived>
Error CodeGenPassBuilder<Derived>::addCoreISelPasses(
AddMachinePass &addPass) const {
TM.setO0WantsFastISel(Opt.EnableFastISelOption.value_or(true));
enum class SelectorType { SelectionDAG, FastISel, GlobalISel };
SelectorType Selector;
if (Opt.EnableFastISelOption && *Opt.EnableFastISelOption == true)
Selector = SelectorType::FastISel;
else if ((Opt.EnableGlobalISelOption &&
*Opt.EnableGlobalISelOption == true) ||
(TM.Options.EnableGlobalISel &&
(!Opt.EnableGlobalISelOption ||
*Opt.EnableGlobalISelOption == false)))
Selector = SelectorType::GlobalISel;
else if (TM.getOptLevel() == CodeGenOpt::None && TM.getO0WantsFastISel())
Selector = SelectorType::FastISel;
else
Selector = SelectorType::SelectionDAG;
if (Selector == SelectorType::FastISel) {
TM.setFastISel(true);
TM.setGlobalISel(false);
} else if (Selector == SelectorType::GlobalISel) {
TM.setFastISel(false);
TM.setGlobalISel(true);
}
if (Selector == SelectorType::GlobalISel) {
if (auto Err = derived().addIRTranslator(addPass))
return std::move(Err);
derived().addPreLegalizeMachineIR(addPass);
if (auto Err = derived().addLegalizeMachineIR(addPass))
return std::move(Err);
derived().addPreRegBankSelect(addPass);
if (auto Err = derived().addRegBankSelect(addPass))
return std::move(Err);
derived().addPreGlobalInstructionSelect(addPass);
if (auto Err = derived().addGlobalInstructionSelect(addPass))
return std::move(Err);
addPass(ResetMachineFunctionPass(reportDiagnosticWhenGlobalISelFallback(),
isGlobalISelAbortEnabled()));
if (!isGlobalISelAbortEnabled())
if (auto Err = derived().addInstSelector(addPass))
return std::move(Err);
} else if (auto Err = derived().addInstSelector(addPass))
return std::move(Err);
addPass(FinalizeISelPass());
return Error::success();
}
template <typename Derived>
Error CodeGenPassBuilder<Derived>::addMachinePasses(
AddMachinePass &addPass) const {
if (getOptLevel() != CodeGenOpt::None) {
derived().addMachineSSAOptimization(addPass);
} else {
addPass(LocalStackSlotPass());
}
if (TM.Options.EnableIPRA)
addPass(RegUsageInfoPropagationPass());
derived().addPreRegAlloc(addPass);
if (*Opt.OptimizeRegAlloc) {
derived().addOptimizedRegAlloc(addPass);
} else {
if (auto Err = derived().addFastRegAlloc(addPass))
return Err;
}
derived().addPostRegAlloc(addPass);
addPass(RemoveRedundantDebugValuesPass());
if (getOptLevel() != CodeGenOpt::None) {
addPass(PostRAMachineSinkingPass());
addPass(ShrinkWrapPass());
}
addPass(PrologEpilogInserterPass());
if (getOptLevel() != CodeGenOpt::None)
derived().addMachineLateOptimization(addPass);
addPass(ExpandPostRAPseudosPass());
derived().addPreSched2(addPass);
if (Opt.EnableImplicitNullChecks)
addPass(ImplicitNullChecksPass());
if (getOptLevel() != CodeGenOpt::None &&
!TM.targetSchedulesPostRAScheduling()) {
if (Opt.MISchedPostRA)
addPass(PostMachineSchedulerPass());
else
addPass(PostRASchedulerPass());
}
derived().addGCPasses(addPass);
if (getOptLevel() != CodeGenOpt::None)
derived().addBlockPlacement(addPass);
addPass(FEntryInserterPass());
addPass(XRayInstrumentationPass());
addPass(PatchableFunctionPass());
derived().addPreEmitPass(addPass);
if (TM.Options.EnableIPRA)
addPass(RegUsageInfoCollectorPass());
addPass(FuncletLayoutPass());
addPass(StackMapLivenessPass());
addPass(LiveDebugValuesPass());
if (TM.Options.EnableMachineOutliner && getOptLevel() != CodeGenOpt::None &&
Opt.EnableMachineOutliner != RunOutliner::NeverOutline) {
bool RunOnAllFunctions =
(Opt.EnableMachineOutliner == RunOutliner::AlwaysOutline);
bool AddOutliner = RunOnAllFunctions || TM.Options.SupportsDefaultOutlining;
if (AddOutliner)
addPass(MachineOutlinerPass(RunOnAllFunctions));
}
derived().addPreEmitPass2(addPass);
return Error::success();
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::addMachineSSAOptimization(
AddMachinePass &addPass) const {
addPass(EarlyTailDuplicatePass());
addPass(OptimizePHIsPass());
addPass(StackColoringPass());
addPass(LocalStackSlotPass());
addPass(DeadMachineInstructionElimPass());
derived().addILPOpts(addPass);
addPass(EarlyMachineLICMPass());
addPass(MachineCSEPass());
addPass(MachineSinkingPass());
addPass(PeepholeOptimizerPass());
addPass(DeadMachineInstructionElimPass());
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::addTargetRegisterAllocator(
AddMachinePass &addPass, bool Optimized) const {
if (Optimized)
addPass(RAGreedyPass());
else
addPass(RAFastPass());
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::addRegAllocPass(AddMachinePass &addPass,
bool Optimized) const {
if (Opt.RegAlloc == RegAllocType::Default)
derived().addTargetRegisterAllocator(addPass, Optimized);
else if (Opt.RegAlloc == RegAllocType::Basic)
addPass(RABasicPass());
else if (Opt.RegAlloc == RegAllocType::Fast)
addPass(RAFastPass());
else if (Opt.RegAlloc == RegAllocType::Greedy)
addPass(RAGreedyPass());
else if (Opt.RegAlloc == RegAllocType::PBQP)
addPass(RAPBQPPass());
else
llvm_unreachable("unknonwn register allocator type");
}
template <typename Derived>
Error CodeGenPassBuilder<Derived>::addRegAssignmentFast(
AddMachinePass &addPass) const {
if (Opt.RegAlloc != RegAllocType::Default &&
Opt.RegAlloc != RegAllocType::Fast)
return make_error<StringError>(
"Must use fast (default) register allocator for unoptimized regalloc.",
inconvertibleErrorCode());
addRegAllocPass(addPass, false);
return Error::success();
}
template <typename Derived>
Error CodeGenPassBuilder<Derived>::addRegAssignmentOptimized(
AddMachinePass &addPass) const {
addRegAllocPass(addPass, true);
derived().addPreRewrite(addPass);
addPass(VirtRegRewriterPass());
addPass(StackSlotColoringPass());
return Error::success();
}
template <typename Derived>
Error CodeGenPassBuilder<Derived>::addFastRegAlloc(
AddMachinePass &addPass) const {
addPass(PHIEliminationPass());
addPass(TwoAddressInstructionPass());
return derived().addRegAssignmentFast(addPass);
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::addOptimizedRegAlloc(
AddMachinePass &addPass) const {
addPass(DetectDeadLanesPass());
addPass(ProcessImplicitDefsPass());
addPass(PHIEliminationPass());
if (Opt.EarlyLiveIntervals)
addPass(LiveIntervalsPass());
addPass(TwoAddressInstructionPass());
addPass(RegisterCoalescerPass());
addPass(RenameIndependentSubregsPass());
addPass(MachineSchedulerPass());
if (derived().addRegAssignmentOptimized(addPass)) {
derived().addPostRewrite(addPass);
addPass(MachineCopyPropagationPass());
addPass(MachineLICMPass());
}
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::addMachineLateOptimization(
AddMachinePass &addPass) const {
addPass(BranchFolderPass());
if (!TM.requiresStructuredCFG())
addPass(TailDuplicatePass());
addPass(MachineCopyPropagationPass());
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::addBlockPlacement(
AddMachinePass &addPass) const {
addPass(MachineBlockPlacementPass());
if (Opt.EnableBlockPlacementStats)
addPass(MachineBlockPlacementStatsPass());
}
}
#endif