[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, aeubanks

Differential Revision: https://reviews.llvm.org/D83608
This commit is contained in:
Yuanfang Chen 2020-12-28 16:56:11 -08:00
parent f782d5ea86
commit 4646de5d75
9 changed files with 1640 additions and 20 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,197 @@
//===- 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, ())
// MACHINE_FUNCTION_PASS("free-machine-function", FreeMachineFunctionPass, ())
#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("mir-printer", PrintMIRPass, ())
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

View File

@ -25,6 +25,7 @@ struct MachineSchedContext;
class PassConfigImpl;
class ScheduleDAGInstrs;
class CSEConfigBase;
class PassInstrumentationCallbacks;
// The old pass manager infrastructure is hidden in a legacy namespace now.
namespace legacy {
@ -465,6 +466,9 @@ protected:
virtual bool addRegAssignmentOptimized();
};
void registerCodeGenCallback(PassInstrumentationCallbacks &PIC,
LLVMTargetMachine &);
} // end namespace llvm
#endif // LLVM_CODEGEN_TARGETPASSCONFIG_H

View File

@ -0,0 +1,65 @@
//===- 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 CCState and CCValAssign classes, used for lowering
// and implementing calling conventions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_PASSBUILDER_OPTION_H
#define LLVM_CODEGEN_PASSBUILDER_OPTION_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 {
Optional<bool> OptimizeRegAlloc;
Optional<bool> EnableIPRA;
bool DebugPM = false;
bool DisableVerify = false;
bool EnableImplicitNullChecks = false;
bool EnableBlockPlacementStats = false;
bool MISchedPostRA = false;
bool EarlyLiveIntervals = false;
bool DisableLSR = false;
bool DisableCGP = false;
bool PrintLSR = false;
bool DisableMergeICmps = false;
bool DisablePartialLibcallInlining = false;
bool DisableConstantHoisting = false;
bool PrintISelInput = false;
bool PrintGCInfo = false;
bool RequiresCodeGenSCCOrder = false;
RunOutliner EnableMachineOutliner = RunOutliner::TargetDefault;
RegAllocType RegAlloc = RegAllocType::Default;
CFLAAType UseCFLAA = CFLAAType::None;
Optional<GlobalISelAbortMode> EnableGlobalISelAbort;
Optional<bool> VerifyMachineCode;
Optional<bool> EnableFastISelOption;
Optional<bool> EnableGlobalISelOption;
};
CGPassBuilderOption getCGPassBuilderOption();
} // namespace llvm
#endif // LLVM_CODEGEN_PASSBUILDER_OPTION_H

View File

@ -16,22 +16,32 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Error.h"
#include "llvm/Target/CGPassBuilderOption.h"
#include "llvm/Target/TargetOptions.h"
#include <string>
namespace llvm {
class AAManager;
template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
class PassManager;
using ModulePassManager = PassManager<Module>;
class Function;
class GlobalValue;
class MachineFunctionPassManager;
class MachineFunctionAnalysisManager;
class MachineModuleInfoWrapperPass;
class Mangler;
class MCAsmInfo;
class MCContext;
class MCInstrInfo;
class MCRegisterInfo;
class MCStreamer;
class MCSubtargetInfo;
class MCSymbol;
class raw_pwrite_stream;
@ -401,6 +411,21 @@ public:
bool DisableVerify = true,
MachineModuleInfoWrapperPass *MMIWP = nullptr) override;
virtual Error buildCodeGenPipeline(ModulePassManager &,
MachineFunctionPassManager &,
MachineFunctionAnalysisManager &,
raw_pwrite_stream &, raw_pwrite_stream *,
CodeGenFileType, CGPassBuilderOption,
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
@ -421,6 +446,10 @@ public:
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

View File

@ -14,6 +14,7 @@ add_llvm_component_library(LLVMCodeGen
CFGuardLongjmp.cpp
CFIInstrInserter.cpp
CodeGen.cpp
CodeGenPassBuilder.cpp
CodeGenPrepare.cpp
CommandFlags.cpp
CriticalAntiDepBreaker.cpp

View File

@ -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

View File

@ -121,6 +121,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);
@ -155,10 +173,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(
@ -177,14 +199,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 AsmStreamer;
}
bool LLVMTargetMachine::addPassesToEmitFile(

View File

@ -29,6 +29,7 @@
#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"
@ -41,6 +42,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/Threading.h"
#include "llvm/Target/CGPassBuilderOption.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils.h"
@ -126,16 +128,16 @@ static cl::opt<cl::boolOrDefault> DebugifyCheckAndStripAll(
"Debugify MIR before, by checking and stripping the debug info 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.
@ -178,7 +180,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"),
@ -415,6 +416,145 @@ 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)
#define SET_BOOLEAN_OPTION(Option) Opt.Option = Option;
SET_BOOLEAN_OPTION(EarlyLiveIntervals)
SET_BOOLEAN_OPTION(EnableBlockPlacementStats)
SET_BOOLEAN_OPTION(EnableImplicitNullChecks)
SET_BOOLEAN_OPTION(EnableMachineOutliner)
SET_BOOLEAN_OPTION(MISchedPostRA)
SET_BOOLEAN_OPTION(UseCFLAA)
SET_BOOLEAN_OPTION(DisableMergeICmps)
SET_BOOLEAN_OPTION(DisableLSR)
SET_BOOLEAN_OPTION(DisableConstantHoisting)
SET_BOOLEAN_OPTION(DisableCGP)
SET_BOOLEAN_OPTION(DisablePartialLibcallInlining)
SET_BOOLEAN_OPTION(PrintLSR)
SET_BOOLEAN_OPTION(PrintISelInput)
SET_BOOLEAN_OPTION(PrintGCInfo)
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.registerShouldRunOptionalPassCallback(
[=, 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.registerShouldRunOptionalPassCallback([](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)
@ -1037,10 +1177,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));
}