[llvm] 31ecf8d - [NewPM][CodeGen] Introduce CodeGenPassBuilder to help build codegen pipeline
David Blaikie via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 11 18:40:20 PDT 2020
This commit introduces a circular dependency between llvm/lib/Target and
llvm/lib/CodeGen (prior to this patch, CodeGen depended on Target, but not
the other way around - with this patch, TargetMachine.h includes
llvm/CodeGen/CGPassBuilderOption.h and llvm/CodeGen/MachinePassManager.h)
Could you revert this patch to revisit the layering here before continuing?
(that is, assuming fixing the layering would be more complicated than a few
minutes/maybe an hour?)
On Fri, Sep 11, 2020 at 4:41 PM Yuanfang Chen via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
>
> Author: Yuanfang Chen
> Date: 2020-09-11T16:41:17-07:00
> New Revision: 31ecf8d29d81d196374a562c6d2bd2c25a62861e
>
> URL:
> https://github.com/llvm/llvm-project/commit/31ecf8d29d81d196374a562c6d2bd2c25a62861e
> DIFF:
> https://github.com/llvm/llvm-project/commit/31ecf8d29d81d196374a562c6d2bd2c25a62861e.diff
>
> LOG: [NewPM][CodeGen] Introduce CodeGenPassBuilder to help build codegen
> pipeline
>
> Following up on D67687.
> Please refer to the RFC here
> http://lists.llvm.org/pipermail/llvm-dev/2020-July/143309.html
>
> `CodeGenPassBuilder` is the NPM counterpart of `TargetPassConfig` with
> below differences.
> - Debugging features (MIR print/verify, disable pass,
> start/stop-before/after, etc.) living in `TargetPassConfig` are moved to
> use PassInstrument as much as possible. (Implementation also lives in
> `TargetPassConfig.cpp`)
> - `TargetPassConfig` is a polymorphic base (virtual inheritance) to build
> the target-dependent pipeline whereas `CodeGenPassBuilder` is the CRTP
> base/helper to implement the target-dependent pipeline. The motivation is
> flexibility for targets to customize the pipeline, inlining opportunity,
> and fits the overall NPM value semantics design.
> - `TargetPassConfig` is a legacy immutable pass to declare hooks for
> targets to customize some target-independent codegen layer behavior. This
> is partially ported to TargetMachine::options. The rest, such as
> `createMachineScheduler/createPostMachineScheduler`, are left out for now.
> They should be implemented in LLVMTargetMachine in the future.
>
> Reviewed By: arsenm
>
> Differential Revision: https://reviews.llvm.org/D83608
>
> Added:
> llvm/include/llvm/CodeGen/CGPassBuilderOption.h
> llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
> llvm/include/llvm/CodeGen/MachinePassRegistry.def
> llvm/lib/CodeGen/CodeGenPassBuilder.cpp
>
> Modified:
> llvm/include/llvm/Passes/StandardInstrumentations.h
> llvm/include/llvm/Target/TargetMachine.h
> llvm/lib/CodeGen/CMakeLists.txt
> llvm/lib/CodeGen/LLVMTargetMachine.cpp
> llvm/lib/CodeGen/TargetPassConfig.cpp
>
> Removed:
>
>
>
>
> ################################################################################
> diff --git a/llvm/include/llvm/CodeGen/CGPassBuilderOption.h
> b/llvm/include/llvm/CodeGen/CGPassBuilderOption.h
> new file mode 100644
> index 000000000000..4553060e687b
> --- /dev/null
> +++ b/llvm/include/llvm/CodeGen/CGPassBuilderOption.h
> @@ -0,0 +1,110 @@
> +//===- CGPassBuilderOption.h - Options for pass builder ---------*- C++
> -*-===//
> +//
> +// 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 declares the options influencing building of codegen
> pipeline.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_CODEGEN_CGPASSBUILDEROPTION_H
> +#define LLVM_CODEGEN_CGPASSBUILDEROPTION_H
> +
> +#include "llvm/ADT/Optional.h"
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/Target/TargetOptions.h"
> +#include <vector>
> +
> +namespace llvm {
> +class TargetMachine;
> +
> +enum class RunOutliner { TargetDefault, AlwaysOutline, NeverOutline };
> +enum class RegAllocType { Default, Basic, Fast, Greedy, PBQP };
> +enum class CFLAAType { None, Steensgaard, Andersen, Both };
> +
> +// Not one-on-one but mostly corresponding to commandline options in
> +// TargetPassConfig.cpp
> +struct CGPassBuilderOption {
> + // Enable optimized register allocation compilation path
> + Optional<bool> OptimizeRegAlloc;
> +
> + // Enable interprocedural register allocation to reduce load/store at
> + // procedure calls
> + Optional<bool> EnableIPRA;
> +
> + // Enable debug logging of pass pipeline
> + bool DebugPM = false;
> +
> + // Disable machine function verification
> + bool DisableVerify = false;
> +
> + // Fold null checks into faulting memory operations
> + bool EnableImplicitNullChecksPass = false;
> +
> + // Collect probability-driven block placement stats
> + bool EnableMachineBlockPlacementStatsPass = false;
> +
> + // Run MachineScheduler post regalloc (independent of preRA sched)
> + bool EnablePostMachineSchedulerPass = false;
> +
> + // Run live interval analysis earlier in the pipeline
> + bool EnableLiveIntervalsPass = false;
> +
> + // Disable Loop Strength Reduction Pass
> + bool DisableLoopStrengthReducePass = false;
> +
> + // Disable Codegen Prepare
> + bool DisableCodeGenPreparePass = false;
> +
> + // Disable MergeICmps Pass
> + bool DisableMergeICmpsPass = false;
> +
> + // Disable Partial Libcall Inlining Pass
> + bool DisablePartiallyInlineLibCallsPass = false;
> +
> + // Disable ConstantHoisting Pass
> + bool DisableConstantHoistingPass = false;
> +
> + // Print LLVM IR produced by the loop-reduce pass
> + bool PrintAfterLSR = false;
> +
> + // Print LLVM IR input to isel pass
> + bool PrintISelInput = false;
> +
> + // Dump garbage collector data
> + bool PrintGCInfo = false;
> +
> + // Enable codegen in SCC order.
> + bool RequiresCodeGenSCCOrder = false;
> +
> + // Enable the machine outliner
> + RunOutliner EnableMachineOutliner = RunOutliner::TargetDefault;
> +
> + // Register allocator to use
> + RegAllocType RegAlloc = RegAllocType::Default;
> +
> + // Experimental option to use CFL-AA in codegen
> + CFLAAType UseCFLAA = CFLAAType::None;
> +
> + // Enable abort calls when "global" instruction selection fails to
> + // lower/select an instruction
> + Optional<GlobalISelAbortMode> EnableGlobalISelAbort;
> +
> + // Verify generated machine code"
> + Optional<bool> VerifyMachineCode;
> +
> + // Enable the "fast" instruction selector
> + Optional<bool> EnableFastISelOption;
> +
> + // Enable the "global" instruction selector
> + Optional<bool> EnableGlobalISelOption;
> +};
> +
> +CGPassBuilderOption getCGPassBuilderOption();
> +
> +} // namespace llvm
> +
> +#endif // LLVM_CODEGEN_CGPASSBUILDEROPTION_H
>
> diff --git a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
> b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
> new file mode 100644
> index 000000000000..0c679eb174b7
> --- /dev/null
> +++ b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
> @@ -0,0 +1,1171 @@
> +//===- Construction of codegen pass pipelines ------------------*- C++
> -*--===//
> +//
> +// 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
> +//
>
> +//===----------------------------------------------------------------------===//
> +/// \file
> +///
> +/// Interfaces for registering analysis passes, producing common pass
> manager
> +/// configurations, and parsing of pass pipelines.
> +///
> +/// TODO: handle addRequiredID where, in legacy PM, one pass require
> other pass
> +/// to run as prerequisite.
> +///
>
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_CODEGEN_CODEGENPASSBUILDER_H
> +#define LLVM_CODEGEN_CODEGENPASSBUILDER_H
> +
> +#include "llvm/ADT/FunctionExtras.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/CGPassBuilderOption.h"
> +#include "llvm/CodeGen/ExpandReductions.h"
> +#include "llvm/CodeGen/MIRPrinter.h"
> +#include "llvm/CodeGen/MachineModuleInfo.h"
> +#include "llvm/CodeGen/MachinePassManager.h"
> +#include "llvm/CodeGen/PreISelIntrinsicLowering.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/MCStreamer.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/TargetMachine.h"
> +#include "llvm/Transforms/Scalar.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/Utils.h"
> +#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
> +#include "llvm/Transforms/Utils/LowerInvoke.h"
> +#include <cassert>
> +#include <string>
> +#include <type_traits>
> +#include <utility>
> +#include <vector>
> +
> +namespace llvm {
> +
> +// FIXME: Dummy target independent passes definitions that have not yet
> been
> +// ported to new pass manager. Once they do, remove these.
> +#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"
> +
> +/// This class provides access to building LLVM's passes.
> +///
> +/// Its members provide the baseline state available to passes during
> their
> +/// construction. The \c MachinePassRegistry.def file specifies how to
> construct
> +/// all of the built-in passes, and those may reference these members
> during
> +/// construction.
> +template <typename DerivedT> class CodeGenPassBuilder {
> +public:
> + explicit CodeGenPassBuilder(LLVMTargetMachine &TM, CGPassBuilderOption
> Opts,
> + PassInstrumentationCallbacks *PIC)
> + : TM(TM), Opt(Opts), PIC(PIC) {
> + // Target could set CGPassBuilderOption::MISchedPostRA to true to
> achieve
> + // substitutePass(&PostRASchedulerID, &PostMachineSchedulerID)
> +
> + // Target should override TM.Options.EnableIPRA in their
> target-specific
> + // LLVMTM ctor. See TargetMachine::setGlobalISel for example.
> + if (Opt.EnableIPRA)
> + TM.Options.EnableIPRA = *Opt.EnableIPRA;
> +
> + if (Opt.EnableGlobalISelAbort)
> + TM.Options.GlobalISelAbort = *Opt.EnableGlobalISelAbort;
> +
> + if (!Opt.OptimizeRegAlloc)
> + Opt.OptimizeRegAlloc = getOptLevel() != CodeGenOpt::None;
> +
> + if (!Opt.VerifyMachineCode) {
> +#ifdef EXPENSIVE_CHECKS
> + Opt.VerifyMachineCode = TM->isMachineVerifierClean();
> +#else
> + Opt.VerifyMachineCode = false;
> +#endif
> + }
> + }
> +
> + Expected<std::pair<ModulePassManager, MachineFunctionPassManager>>
> + buildPipeline(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
> &>()));
> +
> + // Function object to maintain state while adding codegen IR passes.
> + class AddIRPass {
> + public:
> + AddIRPass(bool DebugPM) : MPM(DebugPM), FPM(DebugPM) {
> + AddingFunctionPasses = false;
> + }
> +
> + // Add Function Pass
> + template <typename PassT>
> + std::enable_if_t<is_detected<is_function_pass_t, PassT>::value>
> + operator()(PassT &&Pass) {
> + if (!AddingFunctionPasses)
> + AddingFunctionPasses = true;
> + FPM.addPass(std::forward<PassT>(Pass));
> + }
> +
> + // Add Module 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) &&
> + "could not add module pass after adding function pass");
> + MPM.addPass(std::forward<PassT>(Pass));
> + }
> +
> + ModulePassManager releasePM() {
> + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
> + return std::move(MPM);
> + }
> +
> + private:
> + ModulePassManager MPM;
> + FunctionPassManager FPM;
> + // The codegen IR pipeline are mostly function passes with the
> exceptions of
> + // a few loop and module passes. `AddingFunctionPasses` makes sure
> that
> + // we could only add module passes at the beginning of the pipeline.
> Once
> + // we begin adding function passes, we could no longer add module
> passes.
> + // This special-casing introduces less adaptor passes. If we have the
> need
> + // of adding module passes after function passes, we could change the
> + // implementation to accommodate that.
> + bool AddingFunctionPasses;
> + };
> +
> + // Function object to maintain state while adding codegen machine
> passes.
> + class AddMachinePass {
> + public:
> + AddMachinePass(bool DebugPM, bool RequiresCodeGenSCCOrder,
> + bool VerifyMachineCode)
> + : PM(DebugPM, RequiresCodeGenSCCOrder, VerifyMachineCode) {}
> +
> + 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;
> +
> + /// 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); }
> + CodeGenOpt::Level getOptLevel() const { return TM.getOptLevel(); }
> +
> + /// Check whether or not GlobalISel should abort on error.
> + /// When this is disabled, GlobalISel will fall back on SDISel instead
> of
> + /// erroring out.
> + bool isGlobalISelAbortEnabled() const {
> + return TM.Options.GlobalISelAbort == GlobalISelAbortMode::Enable;
> + }
> +
> + /// Check whether or not a diagnostic should be emitted when GlobalISel
> + /// uses the fallback path. In other words, it will emit a diagnostic
> + /// when GlobalISel failed and isGlobalISelAbortEnabled is false.
> + bool reportDiagnosticWhenGlobalISelFallback() const {
> + return TM.Options.GlobalISelAbort ==
> GlobalISelAbortMode::DisableWithDiag;
> + }
> +
> + /// addInstSelector - This method should install an instruction
> selector pass,
> + /// which converts from LLVM code to machine instructions.
> + Error addInstSelector(AddMachinePass &) const {
> + return make_error<StringError>("addInstSelector is not overridden",
> + inconvertibleErrorCode());
> + }
> +
> + /// Add passes that optimize instruction level parallelism for
> out-of-order
> + /// targets. These passes are run while the machine code is still in SSA
> + /// form, so they can use MachineTraceMetrics to control their
> heuristics.
> + ///
> + /// All passes added here should preserve the MachineDominatorTree,
> + /// MachineLoopInfo, and MachineTraceMetrics analyses.
> + void addILPOpts(AddMachinePass &) const {}
> +
> + /// This method may be implemented by targets that want to run passes
> + /// immediately before register allocation.
> + void addPreRegAlloc(AddMachinePass &) const {}
> +
> + /// addPreRewrite - Add passes to the optimized register allocation
> pipeline
> + /// after register allocation is complete, but before virtual registers
> are
> + /// rewritten to physical registers.
> + ///
> + /// These passes must preserve VirtRegMap and LiveIntervals, and when
> running
> + /// after RABasic or RAGreedy, they should take advantage of
> LiveRegMatrix.
> + /// When these passes run, VirtRegMap contains legal physreg
> assignments for
> + /// all virtual registers.
> + ///
> + /// Note if the target overloads addRegAssignAndRewriteOptimized, this
> may not
> + /// be honored. This is also not generally used for the the fast
> variant,
> + /// where the allocation and rewriting are done in one pass.
> + void addPreRewrite(AddMachinePass &) const {}
> +
> + /// Add passes to be run immediately after virtual registers are
> rewritten
> + /// to physical registers.
> + void addPostRewrite(AddMachinePass &) const {}
> +
> + /// This method may be implemented by targets that want to run passes
> after
> + /// register allocation pass pipeline but before prolog-epilog
> insertion.
> + void addPostRegAlloc(AddMachinePass &) const {}
> +
> + /// This method may be implemented by targets that want to run passes
> after
> + /// prolog-epilog insertion and before the second instruction
> scheduling pass.
> + void addPreSched2(AddMachinePass &) const {}
> +
> + /// This pass may be implemented by targets that want to run passes
> + /// immediately before machine code is emitted.
> + void addPreEmitPass(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
> + // position and remove the `2` suffix here as this callback is what
> + // `addPreEmitPass` *should* be but in reality isn't.
> + void addPreEmitPass2(AddMachinePass &) const {}
> +
> + /// {{@ For GlobalISel
> + ///
> +
> + /// addPreISel - This method should add any "last minute" LLVM->LLVM
> + /// passes (which are run just before instruction selector).
> + void addPreISel(AddIRPass &) const {
> + llvm_unreachable("addPreISel is not overridden");
> + }
> +
> + /// This method should install an IR translator pass, which converts
> from
> + /// LLVM code to machine instructions with possibly generic opcodes.
> + Error addIRTranslator(AddMachinePass &) const {
> + return make_error<StringError>("addIRTranslator is not overridden",
> + inconvertibleErrorCode());
> + }
> +
> + /// This method may be implemented by targets that want to run passes
> + /// immediately before legalization.
> + void addPreLegalizeMachineIR(AddMachinePass &) const {}
> +
> + /// This method should install a legalize pass, which converts the
> instruction
> + /// sequence into one that can be selected by the target.
> + Error addLegalizeMachineIR(AddMachinePass &) const {
> + return make_error<StringError>("addLegalizeMachineIR is not
> overridden",
> + inconvertibleErrorCode());
> + }
> +
> + /// This method may be implemented by targets that want to run passes
> + /// immediately before the register bank selection.
> + void addPreRegBankSelect(AddMachinePass &) const {}
> +
> + /// This method should install a register bank selector pass, which
> + /// assigns register banks to virtual registers without a register
> + /// class or register banks.
> + Error addRegBankSelect(AddMachinePass &) const {
> + return make_error<StringError>("addRegBankSelect is not overridden",
> + inconvertibleErrorCode());
> + }
> +
> + /// This method may be implemented by targets that want to run passes
> + /// immediately before the (global) instruction selection.
> + void addPreGlobalInstructionSelect(AddMachinePass &) const {}
> +
> + /// This method should install a (global) instruction selector pass,
> which
> + /// converts possibly generic instructions to fully target-specific
> + /// instructions, thereby constraining all generic virtual registers to
> + /// register classes.
> + Error addGlobalInstructionSelect(AddMachinePass &) const {
> + return make_error<StringError>(
> + "addGlobalInstructionSelect is not overridden",
> + inconvertibleErrorCode());
> + }
> + /// @}}
> +
> + /// High level function that adds all passes necessary to go from llvm
> IR
> + /// representation to the MI representation.
> + /// Adds IR based lowering and target specific optimization passes and
> finally
> + /// the core instruction selection passes.
> + /// \returns true if an error occurred, false otherwise.
> + ModulePassManager addISelPasses() const;
> +
> + /// Add the actual instruction selection passes. This does not include
> + /// preparation passes on IR.
> + Expected<AddMachinePass> addCoreISelPasses() const;
> +
> + /// Add the complete, standard set of LLVM CodeGen passes.
> + /// Fully developed targets will not generally override this.
> + Error addMachinePasses(AddMachinePass &) const;
> +
> + /// Add passes to lower exception handling for the code generator.
> + void addPassesToHandleExceptions(AddIRPass &) const;
> +
> + /// Add common target configurable passes that perform LLVM IR to IR
> + /// transforms following machine independent optimization.
> + void addIRPasses(AddIRPass &) const;
> +
> + /// Add pass to prepare the LLVM IR for code generation. This should be
> done
> + /// before exception handling preparation passes.
> + void addCodeGenPrepare(AddIRPass &) const;
> +
> + /// Add common passes that perform LLVM IR to IR transforms in
> preparation for
> + /// instruction selection.
> + void addISelPrepare(AddIRPass &) const;
> +
> + /// Methods with trivial inline returns are convenient points in the
> common
> + /// codegen pass pipeline where targets may insert passes. Methods with
> + /// out-of-line standard implementations are major CodeGen stages
> called by
> + /// addMachinePasses. Some targets may override major stages when
> inserting
> + /// passes is insufficient, but maintaining overriden stages is more
> work.
> + ///
> +
> + /// addMachineSSAOptimization - Add standard passes that optimize
> machine
> + /// instructions in SSA form.
> + void addMachineSSAOptimization(AddMachinePass &) const;
> +
> + /// addFastRegAlloc - Add the minimum set of target-independent passes
> that
> + /// are required for fast register allocation.
> + Error addFastRegAlloc(AddMachinePass &) const;
> +
> + /// addOptimizedRegAlloc - Add passes related to register allocation.
> + /// LLVMTargetMachine provides standard regalloc passes for most
> targets.
> + void addOptimizedRegAlloc(AddMachinePass &) const;
> +
> + /// Add passes that optimize machine instructions after register
> allocation.
> + void addMachineLateOptimization(AddMachinePass &) const;
> +
> + /// addGCPasses - 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 {}
> +
> + /// Add standard basic block placement passes.
> + 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");
> + }
> +
> + /// Utilities for targets to add passes to the pass manager.
> + ///
> +
> + /// createTargetRegisterAllocator - Create the register allocator pass
> for
> + /// this target at the current optimization level.
> + void addTargetRegisterAllocator(AddMachinePass &, bool Optimized) const;
> +
> + /// addMachinePasses helper to create the target-selected or overriden
> + /// 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;
> +
> +private:
> + DerivedT &derived() { return static_cast<DerivedT &>(*this); }
> + const DerivedT &derived() const {
> + return static_cast<const DerivedT &>(*this);
> + }
> +};
> +
> +template <typename Derived>
> +Expected<std::pair<ModulePassManager, MachineFunctionPassManager>>
> +CodeGenPassBuilder<Derived>::buildPipeline(raw_pwrite_stream &Out,
> + raw_pwrite_stream *DwoOut,
> + CodeGenFileType FileType)
> const {
> + Expected<AddMachinePass> AddPassOrErr = addCoreISelPasses();
> + if (!AddPassOrErr)
> + return AddPassOrErr.takeError();
> +
> + AddMachinePass &addPass = *AddPassOrErr;
> +
> + 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 std::pair<ModulePassManager, MachineFunctionPassManager>{
> + addISelPasses(), addPass.releasePM()};
> +}
> +
> +static inline AAManager registerAAAnalyses(CFLAAType UseCFLAA) {
> + AAManager AA;
> +
> + // The order in which these are registered determines their priority
> when
> + // being queried.
> +
> + 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;
> + }
> +
> + // Basic AliasAnalysis support.
> + // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that
> + // BasicAliasAnalysis wins if they disagree. This is intended to help
> + // support "obvious" type-punning idioms.
> + 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);
> +}
> +
> +// FIXME: For new PM, use pass name directly in commandline seems good.
> +// Translate stringfied pass name to its old commandline name. Returns the
> +// matching legacy name and a boolean value indicating if the pass is a
> machine
> +// pass.
> +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>
> +ModulePassManager CodeGenPassBuilder<Derived>::addISelPasses() const {
> + AddIRPass addPass(Opt.DebugPM);
> +
> + if (TM.useEmulatedTLS())
> + addPass(LowerEmuTLSPass());
> +
> + addPass(PreISelIntrinsicLoweringPass());
> +
> + derived().addIRPasses(addPass);
> + derived().addCodeGenPrepare(addPass);
> + addPassesToHandleExceptions(addPass);
> + derived().addISelPrepare(addPass);
> + return addPass.releasePM();
> +}
> +
> +/// Add common target configurable passes that perform LLVM IR to IR
> transforms
> +/// following machine independent optimization.
> +template <typename Derived>
> +void CodeGenPassBuilder<Derived>::addIRPasses(AddIRPass &addPass) const {
> + // Before running any passes, run the verifier to determine if the input
> + // coming from the front-end and/or optimizer is valid.
> + if (!Opt.DisableVerify)
> + addPass(VerifierPass());
> +
> + // Run loop strength reduction before anything else.
> + if (getOptLevel() != CodeGenOpt::None &&
> !Opt.DisableLoopStrengthReducePass) {
> + addPass(createFunctionToLoopPassAdaptor(
> + LoopStrengthReducePass(), /*UseMemorySSA*/ true, Opt.DebugPM));
> + // FIXME: use -stop-after so we could remove PrintAfterLSR
> + if (Opt.PrintAfterLSR)
> + addPass(PrintFunctionPass(dbgs(), "\n\n*** Code after LSR ***\n"));
> + }
> +
> + if (getOptLevel() != CodeGenOpt::None) {
> + // 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
> + // target lowering hook.
> + if (!Opt.DisableMergeICmpsPass)
> + addPass(MergeICmpsPass());
> + addPass(ExpandMemCmpPass());
> + }
> +
> + // Run GC lowering passes for builtin collectors
> + // TODO: add a pass insertion point here
> + addPass(GCLoweringPass());
> + addPass(ShadowStackGCLoweringPass());
> + addPass(LowerConstantIntrinsicsPass());
> +
> + // Make sure that no unreachable blocks are instruction selected.
> + addPass(UnreachableBlockElimPass());
> +
> + // Prepare expensive constants for SelectionDAG.
> + if (getOptLevel() != CodeGenOpt::None &&
> !Opt.DisableConstantHoistingPass)
> + addPass(ConstantHoistingPass());
> +
> + if (getOptLevel() != CodeGenOpt::None &&
> + !Opt.DisablePartiallyInlineLibCallsPass)
> + addPass(PartiallyInlineLibCallsPass());
> +
> + // Instrument function entry and exit, e.g. with calls to mcount().
> + addPass(EntryExitInstrumenterPass(/*PostInlining=*/true));
> +
> + // Add scalarization of target's unsupported masked memory intrinsics
> pass.
> + // the unsupported intrinsic will be replaced with a chain of basic
> blocks,
> + // that stores/loads element one-by-one if the appropriate mask bit is
> set.
> + addPass(ScalarizeMaskedMemIntrinPass());
> +
> + // Expand reduction intrinsics into shuffle sequences if the target
> wants to.
> + addPass(ExpandReductionsPass());
> +}
> +
> +/// Turn exception handling constructs into something the code generators
> can
> +/// handle.
> +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:
> + // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to
> both
> + // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise,
> + // catch info can get misplaced when a selector ends up more than one
> block
> + // removed from the parent invoke(s). This could happen when a landing
> + // pad is shared by multiple invokes and is also a target of a normal
> + // edge from elsewhere.
> + addPass(SjLjEHPreparePass());
> + LLVM_FALLTHROUGH;
> + case ExceptionHandling::DwarfCFI:
> + case ExceptionHandling::ARM:
> + addPass(DwarfEHPass());
> + break;
> + case ExceptionHandling::WinEH:
> + // We support using both GCC-style and MSVC-style exceptions on
> Windows, so
> + // add both preparation passes. Each pass will only actually run if it
> + // recognizes the personality function.
> + addPass(WinEHPass());
> + addPass(DwarfEHPass());
> + break;
> + case ExceptionHandling::Wasm:
> + // Wasm EH uses Windows EH instructions, but it does not need to
> demote PHIs
> + // on catchpads and cleanuppads because it does not outline them into
> + // funclets. Catchswitch blocks are not lowered in SelectionDAG, so we
> + // should remove PHIs there.
> + addPass(WinEHPass(/*DemoteCatchSwitchPHIOnly=*/false));
> + addPass(WasmEHPass());
> + break;
> + case ExceptionHandling::None:
> + addPass(LowerInvokePass());
> +
> + // The lower invoke pass may create unreachable code. Remove it.
> + addPass(UnreachableBlockElimPass());
> + break;
> + }
> +}
> +
> +/// Add pass to prepare the LLVM IR for code generation. This should be
> done
> +/// before exception handling preparation passes.
> +template <typename Derived>
> +void CodeGenPassBuilder<Derived>::addCodeGenPrepare(AddIRPass &addPass)
> const {
> + if (getOptLevel() != CodeGenOpt::None && !Opt.DisableCodeGenPreparePass)
> + 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
> +/// instruction selection.
> +template <typename Derived>
> +void CodeGenPassBuilder<Derived>::addISelPrepare(AddIRPass &addPass)
> const {
> + derived().addPreISel(addPass);
> +
> + // Add both the safe stack and the stack protection passes: each of
> them will
> + // only protect functions that have corresponding attributes.
> + addPass(SafeStackPass());
> + addPass(StackProtectorPass());
> +
> + if (Opt.PrintISelInput)
> + addPass(PrintFunctionPass(dbgs(),
> + "\n\n*** Final LLVM Code input to ISel
> ***\n"));
> +
> + // All passes which modify the LLVM IR are now complete; run the
> verifier
> + // to ensure that the IR is valid.
> + if (!Opt.DisableVerify)
> + addPass(VerifierPass());
> +}
> +
> +template <typename Derived>
> +Expected<typename CodeGenPassBuilder<Derived>::AddMachinePass>
> +CodeGenPassBuilder<Derived>::addCoreISelPasses() const {
> + // Enable FastISel with -fast-isel, but allow that to be overridden.
> + TM.setO0WantsFastISel(Opt.EnableFastISelOption.getValueOr(true));
> +
> + // Determine an instruction selector.
> + 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;
> +
> + // Set consistently TM.Options.EnableFastISel and EnableGlobalISel.
> + if (Selector == SelectorType::FastISel) {
> + TM.setFastISel(true);
> + TM.setGlobalISel(false);
> + } else if (Selector == SelectorType::GlobalISel) {
> + TM.setFastISel(false);
> + TM.setGlobalISel(true);
> + }
> +
> + AddMachinePass addPass(Opt.DebugPM, Opt.RequiresCodeGenSCCOrder,
> + *Opt.VerifyMachineCode);
> +
> + // Add instruction selector passes.
> + 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);
> +
> + // Before running the register bank selector, ask the target if it
> + // wants to run some passes.
> + 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);
> +
> + // Pass to reset the MachineFunction if the ISel failed.
> +
> addPass(ResetMachineFunctionPass(reportDiagnosticWhenGlobalISelFallback(),
> + isGlobalISelAbortEnabled()));
> +
> + // Provide a fallback path when we do not want to abort on
> + // not-yet-supported input.
> + if (!isGlobalISelAbortEnabled()) {
> + if (auto Err = derived().addInstSelector(addPass))
> + return std::move(Err);
> + }
> +
> + } else if (auto Err = derived().addInstSelector(addPass))
> + return std::move(Err);
> +
> + // Expand pseudo-instructions emitted by ISel. Don't run the verifier
> before
> + // FinalizeISel.
> + addPass(FinalizeISelPass());
> +
> + return addPass;
> +}
> +
> +/// Add the complete set of target-independent postISel code generator
> passes.
> +///
> +/// This can be read as the standard order of major LLVM CodeGen stages.
> Stages
> +/// with nontrivial configuration or multiple passes are broken out below
> in
> +/// add%Stage routines.
> +///
> +/// Any CodeGenPassBuilder<Derived>::addXX routine may be overriden by the
> +/// Target. The addPre/Post methods with empty header implementations
> allow
> +/// injecting target-specific fixups just before or after major stages.
> +/// Additionally, targets have the flexibility to change pass order
> within a
> +/// stage by overriding default implementation of add%Stage routines
> below. Each
> +/// technique has maintainability tradeoffs because alternate pass orders
> are
> +/// not well supported. addPre/Post works better if the target pass is
> easily
> +/// tied to a common pass. But if it has subtle dependencies on multiple
> passes,
> +/// the target should override the stage instead.
> +template <typename Derived>
> +Error CodeGenPassBuilder<Derived>::addMachinePasses(
> + AddMachinePass &addPass) const {
> + // Add passes that optimize machine instructions in SSA form.
> + if (getOptLevel() != CodeGenOpt::None) {
> + derived().addMachineSSAOptimization(addPass);
> + } else {
> + // If the target requests it, assign local variables to stack slots
> relative
> + // to one another and simplify frame index references where possible.
> + addPass(LocalStackSlotPass());
> + }
> +
> + if (TM.Options.EnableIPRA)
> + addPass(RegUsageInfoPropagationPass());
> +
> + // Run pre-ra passes.
> + derived().addPreRegAlloc(addPass);
> +
> + // Run register allocation and passes that are tightly coupled with it,
> + // including phi elimination and scheduling.
> + if (*Opt.OptimizeRegAlloc) {
> + derived().addOptimizedRegAlloc(addPass);
> + } else {
> + if (auto Err = derived().addFastRegAlloc(addPass))
> + return Err;
> + }
> +
> + // Run post-ra passes.
> + derived().addPostRegAlloc(addPass);
> +
> + // Insert prolog/epilog code. Eliminate abstract frame index
> references...
> + if (getOptLevel() != CodeGenOpt::None) {
> + addPass(PostRAMachineSinkingPass());
> + addPass(ShrinkWrapPass());
> + }
> +
> + addPass(PrologEpilogInserterPass());
> +
> + /// Add passes that optimize machine instructions after register
> allocation.
> + if (getOptLevel() != CodeGenOpt::None)
> + derived().addMachineLateOptimization(addPass);
> +
> + // Expand pseudo instructions before second scheduling pass.
> + addPass(ExpandPostRAPseudosPass());
> +
> + // Run pre-sched2 passes.
> + derived().addPreSched2(addPass);
> +
> + if (Opt.EnableImplicitNullChecksPass)
> + addPass(ImplicitNullChecksPass());
> +
> + // Second pass scheduler.
> + // Let Target optionally insert this pass by itself at some other point.
> + if (getOptLevel() != CodeGenOpt::None &&
> + !TM.targetSchedulesPostRAScheduling()) {
> + if (Opt.EnablePostMachineSchedulerPass)
> + addPass(PostMachineSchedulerPass());
> + else
> + addPass(PostRASchedulerPass());
> + }
> +
> + // GC
> + derived().addGCPasses(addPass);
> +
> + // Basic block placement.
> + if (getOptLevel() != CodeGenOpt::None)
> + derived().addBlockPlacement(addPass);
> +
> + // Insert before XRay Instrumentation.
> + addPass(FEntryInserterPass());
> +
> + addPass(XRayInstrumentationPass());
> + addPass(PatchableFunctionPass());
> +
> + derived().addPreEmitPass(addPass);
> +
> + if (TM.Options.EnableIPRA) {
> + // Collect register usage information and produce a register mask of
> + // clobbered registers, to be used to optimize call sites.
> + 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));
> + }
> +
> + // Add passes that directly emit MI after all other MI passes.
> + derived().addPreEmitPass2(addPass);
> +
> + return Error::success();
> +}
> +
> +/// Add passes that optimize machine instructions in SSA form.
> +template <typename Derived>
> +void CodeGenPassBuilder<Derived>::addMachineSSAOptimization(
> + AddMachinePass &addPass) const {
> + // Pre-ra tail duplication.
> + addPass(EarlyTailDuplicatePass());
> +
> + // Optimize PHIs before DCE: removing dead PHI cycles may make more
> + // instructions dead.
> + addPass(OptimizePHIsPass());
> +
> + // This pass merges large allocas. StackSlotColoring is a
> diff erent pass
> + // which merges spill slots.
> + addPass(StackColoringPass());
> +
> + // If the target requests it, assign local variables to stack slots
> relative
> + // to one another and simplify frame index references where possible.
> + addPass(LocalStackSlotPass());
> +
> + // With optimization, dead code should already be eliminated. However
> + // there is one known exception: lowered code for arguments that are
> only
> + // used by tail calls, where the tail calls reuse the incoming stack
> + // arguments directly (see t11 in test/CodeGen/X86/sibcall.ll).
> + addPass(DeadMachineInstructionElimPass());
> +
> + // Allow targets to insert passes that improve instruction level
> parallelism,
> + // like if-conversion. Such passes will typically need dominator trees
> and
> + // loop info, just like LICM and CSE below.
> + derived().addILPOpts(addPass);
> +
> + addPass(EarlyMachineLICMPass());
> + addPass(MachineCSEPass());
> +
> + addPass(MachineSinkingPass());
> +
> + addPass(PeepholeOptimizerPass());
> + // Clean-up the dead code that may have been generated by peephole
> + // rewriting.
> + addPass(DeadMachineInstructionElimPass());
> +}
> +
>
> +//===---------------------------------------------------------------------===//
> +/// Register Allocation Pass Configuration
>
> +//===---------------------------------------------------------------------===//
> +
> +/// Instantiate the default register allocator pass for this target for
> either
> +/// the optimized or unoptimized allocation path. This will be added to
> the pass
> +/// manager by addFastRegAlloc in the unoptimized case or
> addOptimizedRegAlloc
> +/// in the optimized case.
> +///
> +/// A target that uses the standard regalloc pass order for fast or
> optimized
> +/// allocation may still override this for per-target regalloc
> +/// selection. But -regalloc=... always takes precedence.
> +template <typename Derived>
> +void CodeGenPassBuilder<Derived>::addTargetRegisterAllocator(
> + AddMachinePass &addPass, bool Optimized) const {
> + if (Optimized)
> + addPass(RAGreedyPass());
> + else
> + addPass(RAFastPass());
> +}
> +
> +/// Find and instantiate the register allocation pass requested by this
> target
> +/// at the current optimization level. Different register allocators are
> +/// defined as separate passes because they may require
> diff erent analysis.
> +template <typename Derived>
> +void CodeGenPassBuilder<Derived>::addRegAllocPass(AddMachinePass &addPass,
> + bool Optimized) const {
> + switch (Opt.RegAlloc) {
> + case RegAllocType::Default:
> + // With no -regalloc= override, ask the target for a regalloc pass.
> + derived().addTargetRegisterAllocator(addPass, Optimized);
> + break;
> + case RegAllocType::Basic:
> + addPass(RABasicPass());
> + break;
> + case RegAllocType::Fast:
> + addPass(RAFastPass());
> + break;
> + case RegAllocType::Greedy:
> + addPass(RAGreedyPass());
> + break;
> + case RegAllocType::PBQP:
> + addPass(RAPBQPPass());
> + break;
> + default:
> + 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 {
> + // Add the selected register allocation pass.
> + addRegAllocPass(addPass, true);
> +
> + // Allow targets to change the register assignments before rewriting.
> + derived().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());
> +
> + return Error::success();
> +}
> +
> +/// Add the minimum set of target-independent passes that are required for
> +/// register allocation. No coalescing or scheduling.
> +template <typename Derived>
> +Error CodeGenPassBuilder<Derived>::addFastRegAlloc(
> + AddMachinePass &addPass) const {
> + addPass(PHIEliminationPass());
> + addPass(TwoAddressInstructionPass());
> + return derived().addRegAssignmentFast(addPass);
> +}
> +
> +/// Add standard target-independent passes that are tightly coupled with
> +/// optimized register allocation, including coalescing, machine
> instruction
> +/// scheduling, and register allocation itself.
> +template <typename Derived>
> +void CodeGenPassBuilder<Derived>::addOptimizedRegAlloc(
> + AddMachinePass &addPass) const {
> + addPass(DetectDeadLanesPass());
> +
> + addPass(ProcessImplicitDefsPass());
> +
> + // Edge splitting is smarter with machine loop info.
> + addPass(PHIEliminationPass());
> +
> + // Eventually, we want to run LiveIntervals before PHI elimination.
> + if (Opt.EnableLiveIntervalsPass)
> + addPass(LiveIntervalsPass());
> +
> + addPass(TwoAddressInstructionPass());
> + addPass(RegisterCoalescerPass());
> +
> + // The machine scheduler may accidentally create disconnected components
> + // when moving subregister definitions around, avoid this by splitting
> them to
> + // separate vregs before. Splitting can also improve reg. allocation
> quality.
> + addPass(RenameIndependentSubregsPass());
> +
> + // PreRA instruction scheduling.
> + addPass(MachineSchedulerPass());
> +
> + if (derived().addRegAssignmentOptimized(addPass)) {
> + // Allow targets to expand pseudo instructions depending on the
> choice of
> + // registers before MachineCopyPropagation.
> + derived().addPostRewrite(addPass);
> +
> + // Copy propagate to forward register uses and try to eliminate COPYs
> that
> + // were not coalesced.
> + addPass(MachineCopyPropagationPass());
> +
> + // Run post-ra machine LICM to hoist reloads / remats.
> + //
> + // FIXME: can this move into MachineLateOptimization?
> + addPass(MachineLICMPass());
> + }
> +}
> +
>
> +//===---------------------------------------------------------------------===//
> +/// Post RegAlloc Pass Configuration
>
> +//===---------------------------------------------------------------------===//
> +
> +/// Add passes that optimize machine instructions after register
> allocation.
> +template <typename Derived>
> +void CodeGenPassBuilder<Derived>::addMachineLateOptimization(
> + AddMachinePass &addPass) const {
> + // Branch folding must be run after regalloc and prolog/epilog
> insertion.
> + addPass(BranchFolderPass());
> +
> + // Tail duplication.
> + // Note that duplicating tail just increases code size and degrades
> + // performance for targets that require Structured Control Flow.
> + // In addition it can also make CFG irreducible. Thus we disable it.
> + if (!TM.requiresStructuredCFG())
> + addPass(TailDuplicatePass());
> +
> + // Copy propagation.
> + addPass(MachineCopyPropagationPass());
> +}
> +
> +/// Add standard basic block placement passes.
> +template <typename Derived>
> +void CodeGenPassBuilder<Derived>::addBlockPlacement(
> + AddMachinePass &addPass) const {
> + addPass(MachineBlockPlacementPass());
> + // Run a separate pass to collect block placement statistics.
> + if (Opt.EnableMachineBlockPlacementStatsPass)
> + addPass(MachineBlockPlacementStatsPass());
> +}
> +
> +} // namespace llvm
> +
> +#endif // LLVM_CODEGEN_CODEGENPASSBUILDER_H
>
> diff --git a/llvm/include/llvm/CodeGen/MachinePassRegistry.def
> b/llvm/include/llvm/CodeGen/MachinePassRegistry.def
> new file mode 100644
> index 000000000000..734bbebc76de
> --- /dev/null
> +++ b/llvm/include/llvm/CodeGen/MachinePassRegistry.def
> @@ -0,0 +1,195 @@
> +//===- MachinePassRegistry.def - Registry of passes -------------*- C++
> -*-===//
> +//
> +// 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 is used as the registry of passes that are for
> target-independent
> +// code generator.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +// NOTE: NO INCLUDE GUARD DESIRED!
> +
> +#ifndef MODULE_ANALYSIS
> +#define MODULE_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR)
> +#endif
> +MODULE_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis,
> (PIC))
> +#undef MODULE_ANALYSIS
> +
> +#ifndef MODULE_PASS
> +#define MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR)
> +#endif
> +MODULE_PASS("pre-isel-intrinsic-lowering", PreISelIntrinsicLoweringPass,
> ())
> +#undef MODULE_PASS
> +
> +#ifndef FUNCTION_ANALYSIS
> +#define FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR)
> +#endif
> +FUNCTION_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis,
> (PIC))
> +FUNCTION_ANALYSIS("targetir", TargetIRAnalysis,
> (std::move(TM.getTargetIRAnalysis())))
> +#undef FUNCTION_ANALYSIS
> +
> +#ifndef FUNCTION_PASS
> +#define FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR)
> +#endif
> +FUNCTION_PASS("mergeicmps", MergeICmpsPass, ())
> +FUNCTION_PASS("lower-constant-intrinsics", LowerConstantIntrinsicsPass,
> ())
> +FUNCTION_PASS("unreachableblockelim", UnreachableBlockElimPass, ())
> +FUNCTION_PASS("consthoist", ConstantHoistingPass, ())
> +FUNCTION_PASS("partially-inline-libcalls", PartiallyInlineLibCallsPass,
> ())
> +FUNCTION_PASS("ee-instrument", EntryExitInstrumenterPass, (false))
> +FUNCTION_PASS("post-inline-ee-instrument", EntryExitInstrumenterPass,
> (true))
> +FUNCTION_PASS("expand-reductions", ExpandReductionsPass, ())
> +FUNCTION_PASS("lowerinvoke", LowerInvokePass, ())
> +FUNCTION_PASS("verify", VerifierPass, ())
> +#undef FUNCTION_PASS
> +
> +#ifndef LOOP_PASS
> +#define LOOP_PASS(NAME, PASS_NAME, CONSTRUCTOR)
> +#endif
> +LOOP_PASS("loop-reduce", LoopStrengthReducePass, ())
> +#undef LOOP_PASS
> +
> +#ifndef MACHINE_MODULE_PASS
> +#define MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR)
> +#endif
> +#undef MACHINE_MODULE_PASS
> +
> +#ifndef MACHINE_FUNCTION_ANALYSIS
> +#define MACHINE_FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR)
> +#endif
> +MACHINE_FUNCTION_ANALYSIS("pass-instrumentation",
> PassInstrumentationAnalysis, (PIC))
> +// LiveVariables currently requires pure SSA form.
> +// FIXME: Once TwoAddressInstruction pass no longer uses kill flags,
> +// LiveVariables can be removed completely, and LiveIntervals can be
> directly
> +// computed. (We still either need to regenerate kill flags after
> regalloc, or
> +// preferably fix the scavenger to not depend on them).
> +// MACHINE_FUNCTION_ANALYSIS("live-vars", LiveVariablesAnalysis())
> +
> +// MACHINE_FUNCTION_ANALYSIS("live-stacks", LiveStacksPass())
> +// MACHINE_FUNCTION_ANALYSIS("slot-indexes", SlotIndexesAnalysis())
> +// MACHINE_FUNCTION_ANALYSIS("edge-bundles", EdgeBundlesAnalysis())
> +// MACHINE_FUNCTION_ANALYSIS("lazy-machine-bfi",
> LazyMachineBlockFrequencyInfoAnalysis())
> +// MACHINE_FUNCTION_ANALYSIS("machine-bfi",
> MachineBlockFrequencyInfoAnalysis())
> +// MACHINE_FUNCTION_ANALYSIS("machine-loops", MachineLoopInfoAnalysis())
> +// MACHINE_FUNCTION_ANALYSIS("machine-dom-frontier",
> MachineDominanceFrontierAnalysis())
> +// MACHINE_FUNCTION_ANALYSIS("machine-dom-tree",
> MachineDominatorTreeAnalysis())
> +// MACHINE_FUNCTION_ANALYSIS("machine-ore",
> MachineOptimizationRemarkEmitterPassAnalysis())
> +// MACHINE_FUNCTION_ANALYSIS("machine-post-dom-tree",
> MachinePostDominatorTreeAnalysis())
> +// MACHINE_FUNCTION_ANALYSIS("machine-region-info",
> MachineRegionInfoPassAnalysis())
> +// MACHINE_FUNCTION_ANALYSIS("machine-trace-metrics",
> MachineTraceMetricsAnalysis())
> +// MACHINE_FUNCTION_ANALYSIS("reaching-def",
> ReachingDefAnalysisAnalysis())
> +// MACHINE_FUNCTION_ANALYSIS("live-reg-matrix", LiveRegMatrixAnalysis())
> +// MACHINE_FUNCTION_ANALYSIS("gc-analysis", GCMachineCodeAnalysisPass())
> +#undef MACHINE_FUNCTION_ANALYSIS
> +
> +#ifndef MACHINE_FUNCTION_PASS
> +#define MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR)
> +#endif
> +MACHINE_FUNCTION_PASS("mir-printer", PrintMIRPass, ())
> +#undef MACHINE_FUNCTION_PASS
> +
> +// After a pass is converted to new pass manager, its entry should be
> moved from
> +// dummy table to the normal one. For example, for a machine function
> pass,
> +// DUMMY_MACHINE_FUNCTION_PASS to MACHINE_FUNCTION_PASS.
> +
> +#ifndef DUMMY_FUNCTION_PASS
> +#define DUMMY_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR)
> +#endif
> +DUMMY_FUNCTION_PASS("expandmemcmp", ExpandMemCmpPass, ())
> +DUMMY_FUNCTION_PASS("gc-lowering", GCLoweringPass, ())
> +DUMMY_FUNCTION_PASS("shadow-stack-gc-lowering",
> ShadowStackGCLoweringPass, ())
> +DUMMY_FUNCTION_PASS("scalarize-masked-mem-intrin",
> ScalarizeMaskedMemIntrinPass, ())
> +DUMMY_FUNCTION_PASS("sjljehprepare", SjLjEHPreparePass, ())
> +DUMMY_FUNCTION_PASS("dwarfehprepare", DwarfEHPass, ())
> +DUMMY_FUNCTION_PASS("winehprepare", WinEHPass, ())
> +DUMMY_FUNCTION_PASS("wasmehprepare", WasmEHPass, ())
> +DUMMY_FUNCTION_PASS("codegenprepare", CodeGenPreparePass, ())
> +DUMMY_FUNCTION_PASS("safe-stack", SafeStackPass, ())
> +DUMMY_FUNCTION_PASS("stack-protector", StackProtectorPass, ())
> +DUMMY_FUNCTION_PASS("atomic-expand", AtomicExpandPass, ())
> +DUMMY_FUNCTION_PASS("interleaved-access", InterleavedAccessPass, ())
> +DUMMY_FUNCTION_PASS("indirectbr-expand", IndirectBrExpandPass, ())
> +DUMMY_FUNCTION_PASS("cfguard-dispatch", CFGuardDispatchPass, ())
> +DUMMY_FUNCTION_PASS("cfguard-check", CFGuardCheckPass, ())
> +DUMMY_FUNCTION_PASS("gc-info-printer", GCInfoPrinterPass, ())
> +#undef DUMMY_FUNCTION_PASS
> +
> +#ifndef DUMMY_MODULE_PASS
> +#define DUMMY_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR)
> +#endif
> +DUMMY_MODULE_PASS("lower-emutls", LowerEmuTLSPass, ())
> +#undef DUMMY_MODULE_PASS
> +
> +#ifndef DUMMY_MACHINE_MODULE_PASS
> +#define DUMMY_MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR)
> +#endif
> +DUMMY_MACHINE_MODULE_PASS("machine-outliner", MachineOutlinerPass, ())
> +#undef DUMMY_MACHINE_MODULE_PASS
> +
> +#ifndef DUMMY_MACHINE_FUNCTION_PASS
> +#define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR)
> +#endif
> +DUMMY_MACHINE_FUNCTION_PASS("free-machine-function",
> FreeMachineFunctionPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("finalize-isel", FinalizeISelPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("localstackalloc", LocalStackSlotPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("shrink-wrap", ShrinkWrapPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("prologepilog", PrologEpilogInserterPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("postrapseudos", ExpandPostRAPseudosPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("implicit-null-checks",
> ImplicitNullChecksPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("postmisched", PostMachineSchedulerPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("machine-scheduler", MachineSchedulerPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("machine-cp", MachineCopyPropagationPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("post-RA-sched", PostRASchedulerPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("fentry-insert", FEntryInserterPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("xray-instrumentation",
> XRayInstrumentationPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("patchable-function", PatchableFunctionPass,
> ())
> +DUMMY_MACHINE_FUNCTION_PASS("reg-usage-propagation",
> RegUsageInfoPropagationPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("reg-usage-collector",
> RegUsageInfoCollectorPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("funclet-layout", FuncletLayoutPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("stackmap-liveness", StackMapLivenessPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("livedebugvalues", LiveDebugValuesPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("early-tailduplication",
> EarlyTailDuplicatePass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("opt-phis", OptimizePHIsPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("stack-coloring", StackColoringPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("dead-mi-elimination",
> DeadMachineInstructionElimPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("early-machinelicm", EarlyMachineLICMPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("machinelicm", MachineLICMPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("machine-cse", MachineCSEPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("machine-sink", MachineSinkingPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("postra-machine-sink",
> PostRAMachineSinkingPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("peephole-opt", PeepholeOptimizerPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("regalloc", RegAllocPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("virtregrewriter", VirtRegRewriterPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("stack-slot-coloring", StackSlotColoringPass,
> ())
> +DUMMY_MACHINE_FUNCTION_PASS("phi-node-elimination", PHIEliminationPass,
> ())
> +DUMMY_MACHINE_FUNCTION_PASS("twoaddressinstruction",
> TwoAddressInstructionPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("detect-dead-lanes", DetectDeadLanesPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("processimpdefs", ProcessImplicitDefsPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("liveintervals", LiveIntervalsPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("simple-register-coalescing",
> RegisterCoalescerPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("rename-independent-subregs",
> RenameIndependentSubregsPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("branch-folder", BranchFolderPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("tailduplication", TailDuplicatePass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("block-placement", MachineBlockPlacementPass,
> ())
> +DUMMY_MACHINE_FUNCTION_PASS("block-placement-stats",
> MachineBlockPlacementStatsPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("early-ifcvt", EarlyIfConverterPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("machine-combiner", MachineCombinerPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("lrshrink", LiveRangeShrinkPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("break-false-deps", BreakFalseDepsPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("cfi-instr-inserter", CFIInstrInserterPass,
> ())
> +DUMMY_MACHINE_FUNCTION_PASS("cfguard-longjmp", CFGuardLongjmpPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("ra-basic", RABasicPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("ra-fast", RAFastPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("ra-greedy", RAGreedyPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("ra-pbqp", RAPBQPPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("legalizer", LegalizerPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("irtranslator", IRTranslatorPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("regbankselect", RegBankSelectPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("instruction-select", InstructionSelectPass,
> ())
> +DUMMY_MACHINE_FUNCTION_PASS("reset-machine-function",
> ResetMachineFunctionPass, ())
> +DUMMY_MACHINE_FUNCTION_PASS("machineverifier", MachineVerifierPass, ())
> +#undef DUMMY_MACHINE_FUNCTION_PASS
>
> diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h
> b/llvm/include/llvm/Passes/StandardInstrumentations.h
> index 76e217c89974..457eae26fd47 100644
> --- a/llvm/include/llvm/Passes/StandardInstrumentations.h
> +++ b/llvm/include/llvm/Passes/StandardInstrumentations.h
> @@ -28,6 +28,7 @@
>
> namespace llvm {
>
> +class LLVMTargetMachine;
> class Module;
> class Function;
>
> @@ -140,6 +141,10 @@ class StandardInstrumentations {
>
> TimePassesHandler &getTimePasses() { return TimePasses; }
> };
> +
> +void registerCodeGenCallback(PassInstrumentationCallbacks &PIC,
> + LLVMTargetMachine &);
> +
> } // namespace llvm
>
> #endif
>
> diff --git a/llvm/include/llvm/Target/TargetMachine.h
> b/llvm/include/llvm/Target/TargetMachine.h
> index 2a422341fdc8..c7673d3e74e4 100644
> --- a/llvm/include/llvm/Target/TargetMachine.h
> +++ b/llvm/include/llvm/Target/TargetMachine.h
> @@ -15,9 +15,12 @@
>
> #include "llvm/ADT/StringRef.h"
> #include "llvm/ADT/Triple.h"
> +#include "llvm/CodeGen/CGPassBuilderOption.h"
> +#include "llvm/CodeGen/MachinePassManager.h"
> #include "llvm/IR/DataLayout.h"
> #include "llvm/Pass.h"
> #include "llvm/Support/CodeGen.h"
> +#include "llvm/Support/Error.h"
> #include "llvm/Target/TargetOptions.h"
> #include <string>
>
> @@ -367,6 +370,20 @@ class LLVMTargetMachine : public TargetMachine {
> bool DisableVerify = true,
> MachineModuleInfoWrapperPass *MMIWP = nullptr)
> override;
>
> + virtual Expected<std::pair<ModulePassManager,
> MachineFunctionPassManager>>
> + buildCodeGenPipeline(raw_pwrite_stream &, raw_pwrite_stream *,
> + CodeGenFileType, CGPassBuilderOption,
> + MachineFunctionAnalysisManager &,
> + PassInstrumentationCallbacks *) {
> + return make_error<StringError>("buildCodeGenPipeline is not
> overriden",
> + inconvertibleErrorCode());
> + }
> +
> + virtual std::pair<StringRef, bool> getPassNameFromLegacyName(StringRef)
> {
> + llvm_unreachable(
> + "getPassNameFromLegacyName parseMIRPipeline is not overriden");
> + }
> +
> /// Add passes to the specified pass manager to get machine code
> emitted with
> /// the MCJIT. This method returns true if machine code is not
> supported. It
> /// fills the MCContext Ctx pointer which can be used to build custom
> @@ -387,6 +404,10 @@ class LLVMTargetMachine : public TargetMachine {
> raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
> MCContext &Context);
>
> + Expected<std::unique_ptr<MCStreamer>>
> + createMCStreamer(raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
> + CodeGenFileType FileType, MCContext &Ctx);
> +
> /// True if the target uses physical regs (as nearly all targets do).
> False
> /// for stack machines such as WebAssembly and other virtual-register
> /// machines. If true, all vregs must be allocated before PEI. If
> false, then
>
> diff --git a/llvm/lib/CodeGen/CMakeLists.txt
> b/llvm/lib/CodeGen/CMakeLists.txt
> index 617692a34792..83b3655441fe 100644
> --- a/llvm/lib/CodeGen/CMakeLists.txt
> +++ b/llvm/lib/CodeGen/CMakeLists.txt
> @@ -14,6 +14,7 @@ add_llvm_component_library(LLVMCodeGen
> CFGuardLongjmp.cpp
> CFIInstrInserter.cpp
> CodeGen.cpp
> + CodeGenPassBuilder.cpp
> CodeGenPrepare.cpp
> CommandFlags.cpp
> CriticalAntiDepBreaker.cpp
>
> diff --git a/llvm/lib/CodeGen/CodeGenPassBuilder.cpp
> b/llvm/lib/CodeGen/CodeGenPassBuilder.cpp
> new file mode 100644
> index 000000000000..7f37f2069a3b
> --- /dev/null
> +++ b/llvm/lib/CodeGen/CodeGenPassBuilder.cpp
> @@ -0,0 +1,25 @@
> +//===--- CodeGenPassBuilder.cpp ---------------------------------------
> ---===//
> +//
> +// 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 defines interfaces to access the target independent code
> +// generation passes provided by the LLVM backend.
> +//
>
> +//===---------------------------------------------------------------------===//
> +
> +#include "llvm/CodeGen/CodeGenPassBuilder.h"
> +
> +using namespace llvm;
> +
> +namespace llvm {
> +#define DUMMY_MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR)
> \
> + AnalysisKey PASS_NAME::Key;
> +#include "llvm/CodeGen/MachinePassRegistry.def"
> +#define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR)
> \
> + AnalysisKey PASS_NAME::Key;
> +#include "llvm/CodeGen/MachinePassRegistry.def"
> +} // namespace llvm
>
> diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp
> b/llvm/lib/CodeGen/LLVMTargetMachine.cpp
> index e94b7ed4de03..e86f25512999 100644
> --- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp
> +++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp
> @@ -118,6 +118,24 @@ bool LLVMTargetMachine::addAsmPrinter(PassManagerBase
> &PM,
> raw_pwrite_stream *DwoOut,
> CodeGenFileType FileType,
> MCContext &Context) {
> + Expected<std::unique_ptr<MCStreamer>> MCStreamerOrErr =
> + createMCStreamer(Out, DwoOut, FileType, Context);
> + if (auto Err = MCStreamerOrErr.takeError())
> + return true;
> +
> + // Create the AsmPrinter, which takes ownership of AsmStreamer if
> successful.
> + FunctionPass *Printer =
> + getTarget().createAsmPrinter(*this, std::move(*MCStreamerOrErr));
> + if (!Printer)
> + return true;
> +
> + PM.add(Printer);
> + return false;
> +}
> +
> +Expected<std::unique_ptr<MCStreamer>> LLVMTargetMachine::createMCStreamer(
> + raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, CodeGenFileType
> FileType,
> + MCContext &Context) {
> if (Options.MCOptions.MCSaveTempLabels)
> Context.setAllowTemporaryLabels(false);
>
> @@ -152,10 +170,14 @@ bool
> LLVMTargetMachine::addAsmPrinter(PassManagerBase &PM,
> // Create the code emitter for the target if it exists. If not, .o
> file
> // emission fails.
> MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(MII, MRI,
> Context);
> + if (!MCE)
> + return make_error<StringError>("createMCCodeEmitter failed",
> + inconvertibleErrorCode());
> MCAsmBackend *MAB =
> getTarget().createMCAsmBackend(STI, MRI, Options.MCOptions);
> - if (!MCE || !MAB)
> - return true;
> + if (!MAB)
> + return make_error<StringError>("createMCAsmBackend failed",
> + inconvertibleErrorCode());
>
> Triple T(getTargetTriple().str());
> AsmStreamer.reset(getTarget().createMCObjectStreamer(
> @@ -174,14 +196,7 @@ bool LLVMTargetMachine::addAsmPrinter(PassManagerBase
> &PM,
> break;
> }
>
> - // Create the AsmPrinter, which takes ownership of AsmStreamer if
> successful.
> - FunctionPass *Printer =
> - getTarget().createAsmPrinter(*this, std::move(AsmStreamer));
> - if (!Printer)
> - return true;
> -
> - PM.add(Printer);
> - return false;
> + return std::move(AsmStreamer);
> }
>
> bool LLVMTargetMachine::addPassesToEmitFile(
>
> diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp
> b/llvm/lib/CodeGen/TargetPassConfig.cpp
> index 19db8eb480ca..03a567e3d443 100644
> --- a/llvm/lib/CodeGen/TargetPassConfig.cpp
> +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp
> @@ -22,6 +22,7 @@
> #include "llvm/Analysis/ScopedNoAliasAA.h"
> #include "llvm/Analysis/TargetTransformInfo.h"
> #include "llvm/Analysis/TypeBasedAliasAnalysis.h"
> +#include "llvm/CodeGen/CGPassBuilderOption.h"
> #include "llvm/CodeGen/CSEConfigBase.h"
> #include "llvm/CodeGen/MachineFunctionPass.h"
> #include "llvm/CodeGen/MachinePassRegistry.h"
> @@ -29,11 +30,13 @@
> #include "llvm/CodeGen/RegAllocRegistry.h"
> #include "llvm/IR/IRPrintingPasses.h"
> #include "llvm/IR/LegacyPassManager.h"
> +#include "llvm/IR/PassInstrumentation.h"
> #include "llvm/IR/Verifier.h"
> #include "llvm/InitializePasses.h"
> #include "llvm/MC/MCAsmInfo.h"
> #include "llvm/MC/MCTargetOptions.h"
> #include "llvm/Pass.h"
> +#include "llvm/Passes/StandardInstrumentations.h"
> #include "llvm/Support/CodeGen.h"
> #include "llvm/Support/CommandLine.h"
> #include "llvm/Support/Compiler.h"
> @@ -120,16 +123,17 @@ static cl::opt<cl::boolOrDefault>
> DebugifyAndStripAll(
> "Debugify MIR before and Strip debug after "
> "each pass except those known to be unsafe when debug info is
> present"),
> cl::ZeroOrMore);
> -enum RunOutliner { AlwaysOutline, NeverOutline, TargetDefault };
> +
> // Enable or disable the MachineOutliner.
> static cl::opt<RunOutliner> EnableMachineOutliner(
> "enable-machine-outliner", cl::desc("Enable the machine outliner"),
> - cl::Hidden, cl::ValueOptional, cl::init(TargetDefault),
> - cl::values(clEnumValN(AlwaysOutline, "always",
> + cl::Hidden, cl::ValueOptional, cl::init(RunOutliner::TargetDefault),
> + cl::values(clEnumValN(RunOutliner::AlwaysOutline, "always",
> "Run on all functions guaranteed to be
> beneficial"),
> - clEnumValN(NeverOutline, "never", "Disable all outlining"),
> + clEnumValN(RunOutliner::NeverOutline, "never",
> + "Disable all outlining"),
> // Sentinel value for unspecified option.
> - clEnumValN(AlwaysOutline, "", "")));
> + clEnumValN(RunOutliner::AlwaysOutline, "", "")));
> // Enable or disable FastISel. Both options are needed, because
> // FastISel is enabled by default with -fast, and we wish to be
> // able to enable or disable fast-isel independently from -O0.
> @@ -172,7 +176,6 @@ static cl::opt<bool>
> EarlyLiveIntervals("early-live-intervals", cl::Hidden,
> cl::desc("Run live interval analysis earlier in the pipeline"));
>
> // Experimental option to use CFL-AA in codegen
> -enum class CFLAAType { None, Steensgaard, Andersen, Both };
> static cl::opt<CFLAAType> UseCFLAA(
> "use-cfl-aa-in-codegen", cl::init(CFLAAType::None), cl::Hidden,
> cl::desc("Enable the new, experimental CFL alias analysis in
> CodeGen"),
> @@ -404,6 +407,143 @@ void TargetPassConfig::setStartStopPasses() {
> Started = (StartAfter == nullptr) && (StartBefore == nullptr);
> }
>
> +CGPassBuilderOption llvm::getCGPassBuilderOption() {
> + CGPassBuilderOption Opt;
> +
> +#define SET_OPTION(Option)
> \
> + if (Option.getNumOccurrences())
> \
> + Opt.Option = Option;
> +
> + SET_OPTION(EnableFastISelOption)
> + SET_OPTION(EnableGlobalISelAbort)
> + SET_OPTION(EnableGlobalISelOption)
> + SET_OPTION(EnableIPRA)
> + SET_OPTION(OptimizeRegAlloc)
> + SET_OPTION(VerifyMachineCode)
> +
> + Opt.EnableMachineOutliner = EnableMachineOutliner;
> + Opt.UseCFLAA = UseCFLAA;
> + Opt.PrintISelInput = PrintISelInput;
> + Opt.PrintGCInfo = PrintGCInfo;
> + Opt.EnablePostMachineSchedulerPass = MISchedPostRA;
> + Opt.EnableLiveIntervalsPass = EarlyLiveIntervals;
> + Opt.EnableMachineBlockPlacementStatsPass = EnableBlockPlacementStats;
> + Opt.EnableImplicitNullChecksPass = EnableImplicitNullChecks;
> + Opt.DisableLoopStrengthReducePass = DisableLSR;
> + Opt.DisableCodeGenPreparePass = DisableCGP;
> + Opt.DisableMergeICmpsPass = DisableMergeICmps;
> + Opt.DisablePartiallyInlineLibCallsPass = DisablePartialLibcallInlining;
> + Opt.DisableConstantHoistingPass = DisableConstantHoisting;
> + Opt.PrintAfterLSR = PrintLSR;
> +
> + return Opt;
> +}
> +
> +static void registerPartialPipelineCallback(PassInstrumentationCallbacks
> &PIC,
> + LLVMTargetMachine &LLVMTM) {
> + StringRef StartBefore;
> + StringRef StartAfter;
> + StringRef StopBefore;
> + StringRef StopAfter;
> +
> + unsigned StartBeforeInstanceNum = 0;
> + unsigned StartAfterInstanceNum = 0;
> + unsigned StopBeforeInstanceNum = 0;
> + unsigned StopAfterInstanceNum = 0;
> +
> + std::tie(StartBefore, StartBeforeInstanceNum) =
> + getPassNameAndInstanceNum(StartBeforeOpt);
> + std::tie(StartAfter, StartAfterInstanceNum) =
> + getPassNameAndInstanceNum(StartAfterOpt);
> + std::tie(StopBefore, StopBeforeInstanceNum) =
> + getPassNameAndInstanceNum(StopBeforeOpt);
> + std::tie(StopAfter, StopAfterInstanceNum) =
> + getPassNameAndInstanceNum(StopAfterOpt);
> +
> + if (StartBefore.empty() && StartAfter.empty() && StopBefore.empty() &&
> + StopAfter.empty())
> + return;
> +
> + std::tie(StartBefore, std::ignore) =
> + LLVMTM.getPassNameFromLegacyName(StartBefore);
> + std::tie(StartAfter, std::ignore) =
> + LLVMTM.getPassNameFromLegacyName(StartAfter);
> + std::tie(StopBefore, std::ignore) =
> + LLVMTM.getPassNameFromLegacyName(StopBefore);
> + std::tie(StopAfter, std::ignore) =
> + LLVMTM.getPassNameFromLegacyName(StopAfter);
> + if (!StartBefore.empty() && !StartAfter.empty())
> + report_fatal_error(Twine(StartBeforeOptName) + Twine(" and ") +
> + Twine(StartAfterOptName) + Twine(" specified!"));
> + if (!StopBefore.empty() && !StopAfter.empty())
> + report_fatal_error(Twine(StopBeforeOptName) + Twine(" and ") +
> + Twine(StopAfterOptName) + Twine(" specified!"));
> +
> + PIC.registerBeforePassCallback(
> + [=, EnableCurrent = StartBefore.empty() && StartAfter.empty(),
> + EnableNext = Optional<bool>(), StartBeforeCount = 0u,
> + StartAfterCount = 0u, StopBeforeCount = 0u,
> + StopAfterCount = 0u](StringRef P, Any) mutable {
> + bool StartBeforePass = !StartBefore.empty() &&
> P.contains(StartBefore);
> + bool StartAfterPass = !StartAfter.empty() &&
> P.contains(StartAfter);
> + bool StopBeforePass = !StopBefore.empty() &&
> P.contains(StopBefore);
> + bool StopAfterPass = !StopAfter.empty() && P.contains(StopAfter);
> +
> + // Implement -start-after/-stop-after
> + if (EnableNext) {
> + EnableCurrent = *EnableNext;
> + EnableNext.reset();
> + }
> +
> + // Using PIC.registerAfterPassCallback won't work because if this
> + // callback returns false, AfterPassCallback is also skipped.
> + if (StartAfterPass && StartAfterCount++ == StartAfterInstanceNum)
> {
> + assert(!EnableNext && "Error: assign to EnableNext more than
> once");
> + EnableNext = true;
> + }
> + if (StopAfterPass && StopAfterCount++ == StopAfterInstanceNum) {
> + assert(!EnableNext && "Error: assign to EnableNext more than
> once");
> + EnableNext = false;
> + }
> +
> + if (StartBeforePass && StartBeforeCount++ ==
> StartBeforeInstanceNum)
> + EnableCurrent = true;
> + if (StopBeforePass && StopBeforeCount++ == StopBeforeInstanceNum)
> + EnableCurrent = false;
> + return EnableCurrent;
> + });
> +}
> +
> +void llvm::registerCodeGenCallback(PassInstrumentationCallbacks &PIC,
> + LLVMTargetMachine &LLVMTM) {
> +
> + // Register a callback for disabling passes.
> + PIC.registerBeforePassCallback([](StringRef P, Any) {
> +
> +#define DISABLE_PASS(Option, Name)
> \
> + if (Option && P.contains(#Name))
> \
> + return false;
> + DISABLE_PASS(DisableBlockPlacement, MachineBlockPlacementPass)
> + DISABLE_PASS(DisableBranchFold, BranchFolderPass)
> + DISABLE_PASS(DisableCopyProp, MachineCopyPropagationPass)
> + DISABLE_PASS(DisableEarlyIfConversion, EarlyIfConverterPass)
> + DISABLE_PASS(DisableEarlyTailDup, EarlyTailDuplicatePass)
> + DISABLE_PASS(DisableMachineCSE, MachineCSEPass)
> + DISABLE_PASS(DisableMachineDCE, DeadMachineInstructionElimPass)
> + DISABLE_PASS(DisableMachineLICM, EarlyMachineLICMPass)
> + DISABLE_PASS(DisableMachineSink, MachineSinkingPass)
> + DISABLE_PASS(DisablePostRAMachineLICM, MachineLICMPass)
> + DISABLE_PASS(DisablePostRAMachineSink, PostRAMachineSinkingPass)
> + DISABLE_PASS(DisablePostRASched, PostRASchedulerPass)
> + DISABLE_PASS(DisableSSC, StackSlotColoringPass)
> + DISABLE_PASS(DisableTailDuplicate, TailDuplicatePass)
> +
> + return true;
> + });
> +
> + registerPartialPipelineCallback(PIC, LLVMTM);
> +}
> +
> // Out of line constructor provides default values for pass options and
> // registers all common codegen passes.
> TargetPassConfig::TargetPassConfig(LLVMTargetMachine &TM, PassManagerBase
> &pm)
> @@ -1012,10 +1152,11 @@ void TargetPassConfig::addMachinePasses() {
> addPass(&LiveDebugValuesID, false);
>
> if (TM->Options.EnableMachineOutliner && getOptLevel() !=
> CodeGenOpt::None &&
> - EnableMachineOutliner != NeverOutline) {
> - bool RunOnAllFunctions = (EnableMachineOutliner == AlwaysOutline);
> - bool AddOutliner = RunOnAllFunctions ||
> - TM->Options.SupportsDefaultOutlining;
> + EnableMachineOutliner != RunOutliner::NeverOutline) {
> + bool RunOnAllFunctions =
> + (EnableMachineOutliner == RunOutliner::AlwaysOutline);
> + bool AddOutliner =
> + RunOnAllFunctions || TM->Options.SupportsDefaultOutlining;
> if (AddOutliner)
> addPass(createMachineOutlinerPass(RunOnAllFunctions));
> }
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200911/6b1d44e4/attachment-0001.html>
More information about the llvm-commits
mailing list