[llvm] [NewPM][CodeGen] add TargetPassConfig like API (PR #70906)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 1 00:39:34 PDT 2023
https://github.com/paperchalice created https://github.com/llvm/llvm-project/pull/70906
Add `TargetPassConfig` like API in `CodeGenBuilder`, most of them are copied from `TargetPassConfig.cpp` except GC related pass.
Part of #69879, blocked by #70904.
@arsenm Could you have a look here? Thanks!
>From ed726eb26e1012cdec12daa3fa4f4d26b46f24ed Mon Sep 17 00:00:00 2001
From: liujunchang <lgamma at 163.com>
Date: Wed, 1 Nov 2023 10:41:58 +0800
Subject: [PATCH] [NewPM][CodeGen] add TargetPassConfig like API
---
.../include/llvm/CodeGen/CodeGenPassBuilder.h | 429 +++++++++++++++---
llvm/include/llvm/Target/TargetMachine.h | 18 +-
2 files changed, 382 insertions(+), 65 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
index d7739e8bb597e4e..9f0887123195732 100644
--- a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
+++ b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
@@ -19,10 +19,12 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
+#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/ScopedNoAliasAA.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
#include "llvm/CodeGen/ExpandReductions.h"
+#include "llvm/CodeGen/ExpandVectorPredication.h"
#include "llvm/CodeGen/MachinePassManager.h"
#include "llvm/CodeGen/PreISelIntrinsicLowering.h"
#include "llvm/CodeGen/ReplaceWithVeclib.h"
@@ -36,6 +38,8 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/WithColor.h"
#include "llvm/Target/CGPassBuilderOption.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Scalar/ConstantHoisting.h"
@@ -45,7 +49,10 @@
#include "llvm/Transforms/Scalar/MergeICmps.h"
#include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h"
#include "llvm/Transforms/Scalar/ScalarizeMaskedMemIntrin.h"
+#include "llvm/Transforms/Scalar/TLSVariableHoist.h"
+#include "llvm/Transforms/Utils/CanonicalizeFreezeInLoops.h"
#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
+#include "llvm/Transforms/Utils/LowerGlobalDtors.h"
#include "llvm/Transforms/Utils/LowerInvoke.h"
#include <cassert>
#include <type_traits>
@@ -122,6 +129,26 @@ template <typename DerivedT> class CodeGenPassBuilder {
raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
CodeGenFileType FileType) const;
+ bool parseTargetMIRPass(MachineFunctionPassManager &MFPM,
+ StringRef Name) const {
+ llvm_unreachable("parseTargetMIRPass is not overridden");
+ }
+
+ bool parseMIRPass(MachineFunctionPassManager &MFPM, StringRef Name) const;
+
+ Error parseMIRPipeline(MachineFunctionPassManager &MFPM,
+ StringRef Text) const {
+ for (auto [LHS, RHS] = Text.split(','); RHS != "";
+ std::tie(LHS, RHS) = RHS.split(',')) {
+ if (parseMIRPass(MFPM, LHS) && derived().parseTargetMIRPass(MFPM, Text)) {
+ return createStringError(
+ std::make_error_code(std::errc::invalid_argument),
+ Twine('\"') + Twine(LHS) + Twine("\" pass could not be found."));
+ }
+ }
+ return Error::success();
+ }
+
void registerModuleAnalyses(ModuleAnalysisManager &) const;
void registerFunctionAnalyses(FunctionAnalysisManager &) const;
void registerMachineFunctionAnalyses(MachineFunctionAnalysisManager &) const;
@@ -134,7 +161,19 @@ template <typename DerivedT> class CodeGenPassBuilder {
}
PassInstrumentationCallbacks *getPassInstrumentationCallbacks() const {
- return PIC;
+ static PassInstrumentationCallbacks PseudoPIC;
+ return PIC ? PIC : &PseudoPIC;
+ }
+
+ /// Allow the target to enable a specific standard pass by default.
+ // TODO: implement it
+ template <typename PassT> void enablePass() {}
+
+ /// Allow the target to disable a specific standard pass by default.
+ template <typename PassT> void disablePass() {
+ DisabledPasses.insert(&PassT::Key);
+ getPassInstrumentationCallbacks()->registerShouldRunOptionalPassCallback(
+ [](StringRef P, Any IR) { return P != PassT::name(); });
}
protected:
@@ -195,7 +234,22 @@ template <typename DerivedT> class CodeGenPassBuilder {
// Function object to maintain state while adding codegen machine passes.
class AddMachinePass {
public:
- AddMachinePass(MachineFunctionPassManager &PM) : PM(PM) {}
+ AddMachinePass(const CodeGenPassBuilder &Builder,
+ MachineFunctionPassManager &PM, bool AddPrePostHook = false)
+ : AddPrePostHook(AddPrePostHook), Builder(Builder), PM(PM) {
+ BeforeCallbacks.emplace_back([this](AnalysisKey *) {
+ if (this->AddPrePostHook)
+ this->Builder.addMachinePrePasses(this->PM);
+ return true;
+ });
+
+ AfterCallbacks.emplace_back([this](AnalysisKey *, StringRef Name) {
+ if (this->AddPrePostHook) {
+ std::string Banner = "After " + Name.str();
+ this->Builder.addMachinePostPasses(this->PM, Banner);
+ }
+ });
+ }
template <typename PassT> void operator()(PassT &&Pass) {
static_assert(
@@ -206,41 +260,62 @@ template <typename DerivedT> class CodeGenPassBuilder {
return;
PM.addPass(std::forward<PassT>(Pass));
for (auto &C : AfterCallbacks)
- C(&PassT::Key);
+ C(&PassT::Key, PassT::name());
}
template <typename PassT> void insertPass(AnalysisKey *ID, PassT Pass) {
AfterCallbacks.emplace_back(
- [this, ID, Pass = std::move(Pass)](AnalysisKey *PassID) {
+ [this, ID, Pass = std::move(Pass)](AnalysisKey *PassID, StringRef) {
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); }
+ bool AddPrePostHook;
+
private:
+ const CodeGenPassBuilder &Builder;
MachineFunctionPassManager &PM;
SmallVector<llvm::unique_function<bool(AnalysisKey *)>, 4> BeforeCallbacks;
- SmallVector<llvm::unique_function<void(AnalysisKey *)>, 4> AfterCallbacks;
+ SmallVector<llvm::unique_function<void(AnalysisKey *, StringRef)>, 4>
+ AfterCallbacks;
};
+ // Find the FSProfile file name. The internal option takes the precedence
+ // before getting from TargetMachine.
+ std::string getFSProfileFile() const {
+ if (!Opt.FSProfileFile.empty())
+ return Opt.FSProfileFile;
+ const std::optional<PGOOptions> &PGOOpt = TM.getPGOOption();
+ if (PGOOpt == std::nullopt || PGOOpt->Action != PGOOptions::SampleUse)
+ return std::string();
+ return PGOOpt->ProfileFile;
+ }
+
+ // Find the Profile remapping file name. The internal option takes the
+ // precedence before getting from TargetMachine.
+ std::string getFSRemappingFile() const {
+ if (!Opt.FSRemappingFile.empty())
+ return Opt.FSRemappingFile;
+ const std::optional<PGOOptions> &PGOOpt = TM.getPGOOption();
+ if (PGOOpt == std::nullopt || PGOOpt->Action != PGOOptions::SampleUse)
+ return std::string();
+ return PGOOpt->ProfileRemappingFile;
+ }
+
+ DenseSet<AnalysisKey *> DisabledPasses;
LLVMTargetMachine &TM;
CGPassBuilderOption Opt;
PassInstrumentationCallbacks *PIC;
+ mutable bool DebugifyIsSafe = true;
+ mutable bool AddGCInfoPrinter = false;
/// Target override these hooks to parse target-specific analyses.
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); }
CodeGenOptLevel getOptLevel() const { return TM.getOptLevel(); }
@@ -308,6 +383,10 @@ template <typename DerivedT> class CodeGenPassBuilder {
/// immediately before machine code is emitted.
void addPreEmitPass(AddMachinePass &) const {}
+ /// This pass may be implemented by targets that want to run passes
+ /// immediately after basic block sections are assigned.
+ void addPostBBSections(AddMachinePass &) const {}
+
/// Targets may add passes immediately before machine code is emitted in this
/// callback. This is called even later than `addPreEmitPass`.
// FIXME: Rename `addPreEmitPass` to something more sensible given its actual
@@ -383,6 +462,15 @@ template <typename DerivedT> class CodeGenPassBuilder {
/// Fully developed targets will not generally override this.
Error addMachinePasses(AddMachinePass &) const;
+ /// Add single pass to pass manager from `llc -passes=` option
+ template <typename PassT>
+ void addMachinePass(MachineFunctionPassManager &MFPM, PassT &&Pass) const {
+ addMachinePrePasses(MFPM);
+ std::string Banner = "After " + PassT::name().str();
+ MFPM.addPass(std::forward<PassT>(Pass));
+ addMachinePostPasses(MFPM, Banner);
+ }
+
/// Add passes to lower exception handling for the code generator.
void addPassesToHandleExceptions(AddIRPass &) const;
@@ -413,6 +501,14 @@ template <typename DerivedT> class CodeGenPassBuilder {
/// are required for fast register allocation.
Error addFastRegAlloc(AddMachinePass &) const;
+ /// addPostFastRegAllocRewrite - Add passes to the optimized register
+ /// allocation pipeline after fast register allocation is complete.
+ Error addPostFastRegAllocRewrite(AddMachinePass &) const {
+ return make_error<StringError>(
+ "addPostFastRegAllocRewrite is not overridden",
+ inconvertibleErrorCode());
+ }
+
/// addOptimizedRegAlloc - Add passes related to register allocation.
/// LLVMTargetMachine provides standard regalloc passes for most targets.
void addOptimizedRegAlloc(AddMachinePass &) const;
@@ -420,14 +516,63 @@ template <typename DerivedT> class CodeGenPassBuilder {
/// Add passes that optimize machine instructions after register allocation.
void addMachineLateOptimization(AddMachinePass &) const;
- /// addGCPasses - Add late codegen passes that analyze code for garbage
+ /// registerGCPasses - Add late codegen passes that analyze code for garbage
/// collection. This should return true if GC info should be printed after
/// these passes.
- void addGCPasses(AddMachinePass &) const {}
+ bool registerGCPasses(MachineFunctionAnalysisManager &MFAM) const {
+ MFAM.registerPass([] { return GCMachineCodeAnalysisPass(); });
+ return true;
+ }
/// Add standard basic block placement passes.
void addBlockPlacement(AddMachinePass &) const;
+ /// Add a pass to print the machine function if printing is enabled.
+ void addPrintPass(AddMachinePass &addPass, const std::string &Banner) const {
+ if (Opt.PrintAfterISel)
+ addPass(MachineFunctionPrinterPass(dbgs(), Banner));
+ }
+
+ /// Add a pass to perform basic verification of the machine function if
+ /// verification is enabled.
+ void addVerifyPass(MachineFunctionPassManager &MFPM,
+ const std::string &Banner) const {
+ bool Verify = Opt.VerifyMachineCode.value_or(true);
+#ifdef EXPENSIVE_CHECKS
+ if (!Opt.VerifyMachineCode)
+ Verify = TM->isMachineVerifierClean();
+#endif
+ if (Verify)
+ MFPM.addPass(MachineVerifierPass(Banner));
+ }
+
+ void addVerifyPass(AddMachinePass &addPass, const std::string &Banner) const {
+ bool Verify = Opt.VerifyMachineCode.value_or(true);
+#ifdef EXPENSIVE_CHECKS
+ if (!Opt.VerifyMachineCode)
+ Verify = TM->isMachineVerifierClean();
+#endif
+ if (Verify)
+ addPass(MachineVerifierPass(Banner));
+ }
+
+ /// printAndVerify - Add a pass to dump then verify the machine function, if
+ /// those steps are enabled.
+ void printAndVerify(AddMachinePass &addPass,
+ const std::string &Banner) const {
+ addPrintPass(addPass, Banner);
+ addVerifyPass(addPass, Banner);
+ }
+
+ /// Add standard passes before a pass that's about to be added. For example,
+ /// the DebugifyMachineModulePass if it is enabled.
+ void addMachinePrePasses(MachineFunctionPassManager &MFPM) const;
+
+ /// Add standard passes after a pass that has just been added. For example,
+ /// the MachineVerifier if it is enabled.
+ void addMachinePostPasses(MachineFunctionPassManager &addPass,
+ const std::string &Banner) const;
+
using CreateMCStreamer =
std::function<Expected<std::unique_ptr<MCStreamer>>(MCContext &)>;
void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const {
@@ -445,10 +590,10 @@ template <typename DerivedT> class CodeGenPassBuilder {
/// regalloc pass.
void addRegAllocPass(AddMachinePass &, bool Optimized) const;
- /// Add core register alloator passes which do the actual register assignment
- /// and rewriting. \returns true if any passes were added.
- Error addRegAssignmentFast(AddMachinePass &) const;
- Error addRegAssignmentOptimized(AddMachinePass &) const;
+ /// Add core register allocator passes which do the actual register assignment
+ /// and rewriting. \returns Error::success() if any passes were added.
+ Error addRegAssignAndRewriteFast(AddMachinePass &addPass) const;
+ Error addRegAssignAndRewriteOptimized(AddMachinePass &addPass) const;
private:
DerivedT &derived() { return static_cast<DerivedT &>(*this); }
@@ -465,12 +610,14 @@ Error CodeGenPassBuilder<Derived>::buildPipeline(
AddIRPass addIRPass(MPM, Opt.DebugPM);
addISelPasses(addIRPass);
- AddMachinePass addPass(MFPM);
+ AddMachinePass addPass(*this, MFPM);
if (auto Err = addCoreISelPasses(addPass))
return std::move(Err);
+ addPass.AddPrePostHook = true;
if (auto Err = derived().addMachinePasses(addPass))
return std::move(Err);
+ addPass.AddPrePostHook = false;
derived().addAsmPrinter(
addPass, [this, &Out, DwoOut, FileType](MCContext &Ctx) {
@@ -503,18 +650,21 @@ void CodeGenPassBuilder<Derived>::registerModuleAnalyses(
ModuleAnalysisManager &MAM) const {
#define MODULE_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \
MAM.registerPass([&] { return PASS_NAME CONSTRUCTOR; });
-#include "MachinePassRegistry.def"
+#include "llvm/CodeGen/MachinePassRegistry.def"
derived().registerTargetAnalysis(MAM);
+ if (Opt.RequiresCodeGenSCCOrder)
+ MAM.registerPass([&] { return CallGraphAnalysis(); });
}
template <typename Derived>
void CodeGenPassBuilder<Derived>::registerFunctionAnalyses(
FunctionAnalysisManager &FAM) const {
- FAM.registerPass([this] { return registerAAAnalyses(); });
+ if (getOptLevel() != CodeGenOptLevel::None)
+ FAM.registerPass([this] { return registerAAAnalyses(); });
#define FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \
FAM.registerPass([&] { return PASS_NAME CONSTRUCTOR; });
-#include "MachinePassRegistry.def"
+#include "llvm/CodeGen/MachinePassRegistry.def"
derived().registerTargetAnalysis(FAM);
}
@@ -523,7 +673,9 @@ void CodeGenPassBuilder<Derived>::registerMachineFunctionAnalyses(
MachineFunctionAnalysisManager &MFAM) const {
#define MACHINE_FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \
MFAM.registerPass([&] { return PASS_NAME CONSTRUCTOR; });
-#include "MachinePassRegistry.def"
+#include "llvm/CodeGen/MachinePassRegistry.def"
+
+ AddGCInfoPrinter = derived().registerGCPasses(MFAM) && Opt.PrintGCInfo;
derived().registerTargetAnalysis(MFAM);
}
@@ -574,12 +726,47 @@ CodeGenPassBuilder<Derived>::getPassNameFromLegacyName(StringRef Name) const {
return Ret;
}
+template <typename DerivedT>
+bool llvm::CodeGenPassBuilder<DerivedT>::parseMIRPass(
+ MachineFunctionPassManager &MFPM, StringRef Name) const {
+#define ADD_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
+ if (Name == NAME) { \
+ { \
+ addMachinePass(MFPM, PASS_NAME CONSTRUCTOR); \
+ } \
+ return false; \
+ }
+#define MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
+ ADD_PASS(NAME, PASS_NAME, CONSTRUCTOR)
+#define MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
+ ADD_PASS(NAME, PASS_NAME, CONSTRUCTOR)
+#define DUMMY_MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
+ if (Name == NAME) { \
+ { \
+ addMachinePass(MFPM, PASS_NAME()); \
+ } \
+ return false; \
+ }
+#define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
+ if (Name == NAME) { \
+ { \
+ addMachinePass(MFPM, PASS_NAME()); \
+ } \
+ return false; \
+ }
+#include "llvm/CodeGen/MachinePassRegistry.def"
+#undef ADD_PASS
+ return true;
+}
+
template <typename Derived>
void CodeGenPassBuilder<Derived>::addISelPasses(AddIRPass &addPass) const {
if (TM.useEmulatedTLS())
addPass(LowerEmuTLSPass());
addPass(PreISelIntrinsicLoweringPass(TM));
+ addPass(createModuleToFunctionPassAdaptor(ExpandLargeDivRemPass()));
+ addPass(createModuleToFunctionPassAdaptor(ExpandLargeFpConvertPass()));
derived().addIRPasses(addPass);
derived().addCodeGenPrepare(addPass);
@@ -596,16 +783,18 @@ void CodeGenPassBuilder<Derived>::addIRPasses(AddIRPass &addPass) const {
if (!Opt.DisableVerify)
addPass(VerifierPass());
- // Run loop strength reduction before anything else.
- if (getOptLevel() != CodeGenOptLevel::None && !Opt.DisableLSR) {
- addPass(createFunctionToLoopPassAdaptor(
- LoopStrengthReducePass(), /*UseMemorySSA*/ true, Opt.DebugPM));
- // FIXME: use -stop-after so we could remove PrintLSR
- if (Opt.PrintLSR)
- addPass(PrintFunctionPass(dbgs(), "\n\n*** Code after LSR ***\n"));
- }
-
if (getOptLevel() != CodeGenOptLevel::None) {
+ // Run loop strength reduction before anything else.
+ if (!Opt.DisableLSR) {
+ addPass(createFunctionToLoopPassAdaptor(
+ CanonicalizeFreezeInLoopsPass(), /*UseMemorySSA*/ true, Opt.DebugPM));
+ addPass(createFunctionToLoopPassAdaptor(
+ LoopStrengthReducePass(), /*UseMemorySSA*/ true, Opt.DebugPM));
+ // FIXME: use -stop-after so we could remove PrintLSR
+ if (Opt.PrintLSR)
+ addPass(PrintFunctionPass(dbgs(), "\n\n*** Code after LSR ***\n"));
+ }
+
// The MergeICmpsPass tries to create memcmp calls by grouping sequences of
// loads and compares. ExpandMemCmpPass then tries to expand those calls
// into optimally-sized loads and compares. The transforms are enabled by a
@@ -621,6 +810,15 @@ void CodeGenPassBuilder<Derived>::addIRPasses(AddIRPass &addPass) const {
addPass(ShadowStackGCLoweringPass());
addPass(LowerConstantIntrinsicsPass());
+ if (AddGCInfoPrinter)
+ addPass(GCInfoPrinterPass(dbgs));
+
+ // For MachO, lower @llvm.global_dtors into @llvm.global_ctors with
+ // __cxa_atexit() calls to avoid emitting the deprecated __mod_term_func.
+ if (TM.getTargetTriple().isOSBinFormatMachO() &&
+ !Opt.DisableAtExitBasedGlobalDtorLowering)
+ addPass(LowerGlobalDtorsPass());
+
// Make sure that no unreachable blocks are instruction selected.
addPass(UnreachableBlockElimPass());
@@ -637,8 +835,10 @@ void CodeGenPassBuilder<Derived>::addIRPasses(AddIRPass &addPass) const {
!Opt.DisablePartialLibcallInlining)
addPass(PartiallyInlineLibCallsPass());
- // Instrument function entry and exit, e.g. with calls to mcount().
- addPass(EntryExitInstrumenterPass(/*PostInlining=*/true));
+ // Expand vector predication intrinsics into standard IR instructions.
+ // This pass has to run before ScalarizeMaskedMemIntrin and ExpandReduction
+ // passes since it emits those kinds of intrinsics.
+ addPass(ExpandVectorPredicationPass());
// Add scalarization of target's unsupported masked memory intrinsics pass.
// the unsupported intrinsic will be replaced with a chain of basic blocks,
@@ -646,7 +846,12 @@ void CodeGenPassBuilder<Derived>::addIRPasses(AddIRPass &addPass) const {
addPass(ScalarizeMaskedMemIntrinPass());
// Expand reduction intrinsics into shuffle sequences if the target wants to.
- addPass(ExpandReductionsPass());
+ // Allow disabling it for testing purposes.
+ if (!Opt.DisableExpandReductions)
+ addPass(ExpandReductionsPass());
+
+ if (getOptLevel() != CodeGenOptLevel::None)
+ addPass(TLSVariableHoistPass());
// Convert conditional moves to conditional jumps when profitable.
if (getOptLevel() != CodeGenOptLevel::None && !Opt.DisableSelectOptimize)
@@ -705,8 +910,6 @@ template <typename Derived>
void CodeGenPassBuilder<Derived>::addCodeGenPrepare(AddIRPass &addPass) const {
if (getOptLevel() != CodeGenOptLevel::None && !Opt.DisableCGP)
addPass(CodeGenPreparePass());
- // TODO: Default ctor'd RewriteSymbolPass is no-op.
- // addPass(RewriteSymbolPass());
}
/// Add common passes that perform LLVM IR to IR transforms in preparation for
@@ -716,6 +919,7 @@ void CodeGenPassBuilder<Derived>::addISelPrepare(AddIRPass &addPass) const {
derived().addPreISel(addPass);
addPass(CallBrPrepare());
+
// Add both the safe stack and the stack protection passes: each of them will
// only protect functions that have corresponding attributes.
addPass(SafeStackPass());
@@ -754,6 +958,19 @@ Error CodeGenPassBuilder<Derived>::addCoreISelPasses(
else
Selector = SelectorType::SelectionDAG;
+ // FIXME: Injecting into the DAGISel pipeline seems to cause issues with
+ // analyses needing to be re-run. This can result in being unable to
+ // schedule passes (particularly with 'Function Alias Analysis
+ // Results'). It's not entirely clear why but AFAICT this seems to be
+ // due to one FunctionPassManager not being able to use analyses from a
+ // previous one. As we're injecting a ModulePass we break the usual
+ // pass manager into two. GlobalISel with the fallback path disabled
+ // and -run-pass seem to be unaffected. The majority of GlobalISel
+ // testing uses -run-pass so this probably isn't too bad.
+ SaveAndRestore SavedDebugifyIsSafe(DebugifyIsSafe);
+ if (Selector != SelectorType::GlobalISel || !isGlobalISelAbortEnabled())
+ DebugifyIsSafe = false;
+
// Set consistently TM.Options.EnableFastISel and EnableGlobalISel.
if (Selector == SelectorType::FastISel) {
TM.setFastISel(true);
@@ -765,6 +982,7 @@ Error CodeGenPassBuilder<Derived>::addCoreISelPasses(
// Add instruction selector passes.
if (Selector == SelectorType::GlobalISel) {
+ SaveAndRestore SavedAddingMachinePasses(addPass.AddPrePostHook, true);
if (auto Err = derived().addIRTranslator(addPass))
return std::move(Err);
@@ -803,8 +1021,7 @@ Error CodeGenPassBuilder<Derived>::addCoreISelPasses(
addPass(FinalizeISelPass());
// // Print the instruction selected machine code...
- // printAndVerify("After Instruction Selection");
-
+ printAndVerify(addPass, "After Instruction Selection");
return Error::success();
}
@@ -841,9 +1058,28 @@ Error CodeGenPassBuilder<Derived>::addMachinePasses(
// Run pre-ra passes.
derived().addPreRegAlloc(addPass);
+ // Debugifying the register allocator passes seems to provoke some
+ // non-determinism that affects CodeGen and there doesn't seem to be a point
+ // where it becomes safe again so stop debugifying here.
+ DebugifyIsSafe = false;
+
+ // Add a FSDiscriminator pass right before RA, so that we could get
+ // more precise SampleFDO profile for RA.
+ if (EnableFSDiscriminator) {
+ addPass(MIRAddFSDiscriminatorsPass(sampleprof::FSDiscriminatorPass::Pass1));
+ const std::string ProfileFile = getFSProfileFile();
+ if (!ProfileFile.empty() && !Opt.DisableRAFSProfileLoader)
+ addPass(MIRProfileLoaderPass(ProfileFile, getFSRemappingFile(),
+ sampleprof::FSDiscriminatorPass::Pass1,
+ nullptr));
+ }
+
// Run register allocation and passes that are tightly coupled with it,
// including phi elimination and scheduling.
- if (*Opt.OptimizeRegAlloc) {
+ bool IsOptimizeRegAlloc = Opt.OptimizeRegAlloc.has_value()
+ ? *Opt.OptimizeRegAlloc
+ : getOptLevel() != CodeGenOptLevel::None;
+ if (IsOptimizeRegAlloc) {
derived().addOptimizedRegAlloc(addPass);
} else {
if (auto Err = derived().addFastRegAlloc(addPass))
@@ -855,13 +1091,20 @@ Error CodeGenPassBuilder<Derived>::addMachinePasses(
addPass(RemoveRedundantDebugValuesPass());
- // Insert prolog/epilog code. Eliminate abstract frame index references...
+ addPass(FixupStatepointCallerSavedPass());
+
+ // Insert prolog/epilog code. Eliminate abstract frame index
+ // references...
if (getOptLevel() != CodeGenOptLevel::None) {
addPass(PostRAMachineSinkingPass());
addPass(ShrinkWrapPass());
}
- addPass(PrologEpilogInserterPass());
+ // Prolog/Epilog inserter needs a TargetMachine to instantiate. But only
+ // do so if it hasn't been disabled, substituted, or overridden.
+
+ if (!DisabledPasses.contains(&PrologEpilogCodeInserterPass::Key))
+ addPass(PrologEpilogInserterPass());
/// Add passes that optimize machine instructions after register allocation.
if (getOptLevel() != CodeGenOptLevel::None)
@@ -887,9 +1130,6 @@ Error CodeGenPassBuilder<Derived>::addMachinePasses(
addPass(PostRASchedulerPass());
}
- // GC
- derived().addGCPasses(addPass);
-
// Basic block placement.
if (getOptLevel() != CodeGenOptLevel::None)
derived().addBlockPlacement(addPass);
@@ -907,6 +1147,8 @@ Error CodeGenPassBuilder<Derived>::addMachinePasses(
// clobbered registers, to be used to optimize call sites.
addPass(RegUsageInfoCollectorPass());
+ // FIXME: Some backends are incompatible with running the verifier after
+ // addPreEmitPass. Maybe only pass "false" here for those targets?
addPass(FuncletLayoutPass());
addPass(StackMapLivenessPass());
@@ -923,12 +1165,77 @@ Error CodeGenPassBuilder<Derived>::addMachinePasses(
addPass(MachineOutlinerPass(RunOnAllFunctions));
}
+ if (Opt.GCEmptyBlocks)
+ addPass(GCEmptyBasicBlocksPass());
+
+ if (EnableFSDiscriminator)
+ addPass(
+ MIRAddFSDiscriminatorsPass(sampleprof::FSDiscriminatorPass::PassLast));
+
+ // Machine function splitter uses the basic block sections feature. Both
+ // cannot be enabled at the same time. Basic block sections takes precedence.
+ // FIXME: In principle, BasicBlockSection::Labels and splitting can used
+ // together. Update this check once we have addressed any issues.
+ if (TM.getBBSectionsType() != llvm::BasicBlockSection::None) {
+ if (TM.getBBSectionsType() == llvm::BasicBlockSection::List) {
+ addPass(
+ BasicBlockSectionsProfileReaderPass(TM.getBBSectionsFuncListBuf()));
+ }
+ addPass(BasicBlockSectionsPass());
+ } else if (TM.Options.EnableMachineFunctionSplitter ||
+ Opt.EnableMachineFunctionSplitter) {
+ const std::string ProfileFile = getFSProfileFile();
+ if (!ProfileFile.empty()) {
+ if (EnableFSDiscriminator) {
+ addPass(MIRProfileLoaderPass(ProfileFile, getFSRemappingFile(),
+ sampleprof::FSDiscriminatorPass::PassLast,
+ nullptr));
+ } else {
+ // Sample profile is given, but FSDiscriminator is not
+ // enabled, this may result in performance regression.
+ WithColor::warning()
+ << "Using AutoFDO without FSDiscriminator for MFS may regress "
+ "performance.";
+ }
+ }
+ addPass(MachineFunctionSplitterPass());
+ }
+
+ derived().addPostBBSections(addPass);
+
+ if (!Opt.DisableCFIFixup && TM.Options.EnableCFIFixup)
+ addPass(CFIFixupPass());
+
+ addPass(StackFrameLayoutAnalysisPass());
+
// Add passes that directly emit MI after all other MI passes.
derived().addPreEmitPass2(addPass);
return Error::success();
}
+template <typename DerivedT>
+void CodeGenPassBuilder<DerivedT>::addMachinePrePasses(
+ MachineFunctionPassManager &MFPM) const {
+ if (DebugifyIsSafe &&
+ ((Opt.DebugifyAndStripAll && *Opt.DebugifyAndStripAll) ||
+ (Opt.DebugifyCheckAndStripAll && *Opt.DebugifyCheckAndStripAll)))
+ MFPM.addPass(DebugifyMachineModule());
+}
+
+template <typename DerivedT>
+void llvm::CodeGenPassBuilder<DerivedT>::addMachinePostPasses(
+ MachineFunctionPassManager &MFPM, const std::string &Banner) const {
+ if (DebugifyIsSafe) {
+ if (Opt.DebugifyCheckAndStripAll && *Opt.DebugifyCheckAndStripAll) {
+ MFPM.addPass(CheckDebugMachineModulePass());
+ MFPM.addPass(StripDebugMachineModulePass(/*OnlyDebugified=*/true));
+ } else if (Opt.DebugifyAndStripAll && *Opt.DebugifyAndStripAll)
+ MFPM.addPass(StripDebugMachineModulePass(/*OnlyDebugified=*/true));
+ }
+ addVerifyPass(MFPM, Banner);
+}
+
/// Add passes that optimize machine instructions in SSA form.
template <typename Derived>
void CodeGenPassBuilder<Derived>::addMachineSSAOptimization(
@@ -1013,7 +1320,7 @@ void CodeGenPassBuilder<Derived>::addRegAllocPass(AddMachinePass &addPass,
}
template <typename Derived>
-Error CodeGenPassBuilder<Derived>::addRegAssignmentFast(
+Error CodeGenPassBuilder<Derived>::addRegAssignAndRewriteFast(
AddMachinePass &addPass) const {
if (Opt.RegAlloc != RegAllocType::Default &&
Opt.RegAlloc != RegAllocType::Fast)
@@ -1021,26 +1328,27 @@ Error CodeGenPassBuilder<Derived>::addRegAssignmentFast(
"Must use fast (default) register allocator for unoptimized regalloc.",
inconvertibleErrorCode());
- addRegAllocPass(addPass, false);
- return Error::success();
+ addPass(RegAllocPass(false));
+
+ // Allow targets to change the register assignments after
+ // fast register allocation.
+ return derived().addPostFastRegAllocRewrite(addPass);
}
-template <typename Derived>
-Error CodeGenPassBuilder<Derived>::addRegAssignmentOptimized(
+template <typename DerivedT>
+Error llvm::CodeGenPassBuilder<DerivedT>::addRegAssignAndRewriteOptimized(
AddMachinePass &addPass) const {
// Add the selected register allocation pass.
addRegAllocPass(addPass, true);
-
// Allow targets to change the register assignments before rewriting.
- derived().addPreRewrite(addPass);
+ addPreRewrite(addPass);
// Finally rewrite virtual registers.
addPass(VirtRegRewriterPass());
- // Perform stack slot coloring and post-ra machine LICM.
- //
- // FIXME: Re-enable coloring with register when it's capable of adding
- // kill markers.
- addPass(StackSlotColoringPass());
+
+ // Regalloc scoring for ML-driven eviction - noop except when learning a new
+ // eviction policy.
+ addPass(RegAllocScoringPass());
return Error::success();
}
@@ -1052,7 +1360,7 @@ Error CodeGenPassBuilder<Derived>::addFastRegAlloc(
AddMachinePass &addPass) const {
addPass(PHIEliminationPass());
addPass(TwoAddressInstructionPass());
- return derived().addRegAssignmentFast(addPass);
+ return derived().addRegAssignAndRewriteFast(addPass);
}
/// Add standard target-independent passes that are tightly coupled with
@@ -1083,7 +1391,8 @@ void CodeGenPassBuilder<Derived>::addOptimizedRegAlloc(
// PreRA instruction scheduling.
addPass(MachineSchedulerPass());
- if (derived().addRegAssignmentOptimized(addPass)) {
+ Error Err = derived().addRegAssignAndRewriteOptimized(addPass);
+ if (!Err) {
// Allow targets to expand pseudo instructions depending on the choice of
// registers before MachineCopyPropagation.
derived().addPostRewrite(addPass);
diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h
index c1d05b25ea21f8a..e28a5c00f7c9a6d 100644
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -14,6 +14,7 @@
#define LLVM_TARGET_TARGETMACHINE_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/MachinePassManager.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/Allocator.h"
@@ -450,19 +451,26 @@ class LLVMTargetMachine : public TargetMachine {
bool DisableVerify = true,
MachineModuleInfoWrapperPass *MMIWP = nullptr) override;
- virtual Error buildCodeGenPipeline(ModulePassManager &,
- MachineFunctionPassManager &,
- MachineFunctionAnalysisManager &,
+ virtual Error buildCodeGenPipeline(ModulePassManager &MPM,
+ MachineFunctionPassManager &MFPM,
raw_pwrite_stream &, raw_pwrite_stream *,
CodeGenFileType, CGPassBuilderOption,
+ MachineFunctionAnalysisManager &,
PassInstrumentationCallbacks *) {
return make_error<StringError>("buildCodeGenPipeline is not overridden",
inconvertibleErrorCode());
}
virtual std::pair<StringRef, bool> getPassNameFromLegacyName(StringRef) {
- llvm_unreachable(
- "getPassNameFromLegacyName parseMIRPipeline is not overridden");
+ llvm_unreachable("getPassNameFromLegacyName is not overridden");
+ }
+
+ virtual Error parseMIRPipeline(MachineFunctionPassManager &MFPM,
+ StringRef PipelineText,
+ CGPassBuilderOption Opts,
+ MachineFunctionAnalysisManager &MFAM,
+ PassInstrumentationCallbacks *PIC) {
+ llvm_unreachable("parseMIRPipeline is not overridden");
}
/// Add passes to the specified pass manager to get machine code emitted with
More information about the llvm-commits
mailing list