[llvm] [NewPM][CodeGen][llc] Add NPM support (PR #70922)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 22 22:31:56 PST 2024
https://github.com/paperchalice updated https://github.com/llvm/llvm-project/pull/70922
>From 41528ffe3e10ae79c37aba6dccd9f226323604b8 Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Fri, 19 Jan 2024 17:56:10 +0800
Subject: [PATCH 1/8] [X86] Add CodeGenBuilder for test
---
llvm/lib/Target/X86/CMakeLists.txt | 3 +
llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp | 56 +++++++++++++++++++
llvm/lib/Target/X86/X86TargetMachine.h | 6 ++
3 files changed, 65 insertions(+)
create mode 100644 llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
diff --git a/llvm/lib/Target/X86/CMakeLists.txt b/llvm/lib/Target/X86/CMakeLists.txt
index 4d6300cad2a7a8..610999f0cc3cf0 100644
--- a/llvm/lib/Target/X86/CMakeLists.txt
+++ b/llvm/lib/Target/X86/CMakeLists.txt
@@ -29,6 +29,7 @@ set(sources
X86CallFrameOptimization.cpp
X86CallingConv.cpp
X86CmovConversion.cpp
+ X86CodeGenPassBuilder.cpp
X86DomainReassignment.cpp
X86DiscriminateMemOps.cpp
X86LowerTileCopy.cpp
@@ -98,9 +99,11 @@ add_llvm_target(X86CodeGen ${sources}
CodeGenTypes
Core
GlobalISel
+ IRPrinter
Instrumentation
MC
ProfileData
+ Scalar
SelectionDAG
Support
Target
diff --git a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
new file mode 100644
index 00000000000000..616f777833e565
--- /dev/null
+++ b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
@@ -0,0 +1,56 @@
+//===-- X86CodeGenPassBuilder.cpp ---------------------------------*- 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
+/// This file contains X86 CodeGen pipeline builder.
+/// TODO: Port CodeGen passes to new pass manager.
+//===----------------------------------------------------------------------===//
+
+#include "X86TargetMachine.h"
+
+#include "llvm/CodeGen/CodeGenPassBuilder.h"
+#include "llvm/MC/MCStreamer.h"
+
+using namespace llvm;
+
+namespace {
+
+class X86CodeGenPassBuilder : public CodeGenPassBuilder<X86CodeGenPassBuilder> {
+public:
+ explicit X86CodeGenPassBuilder(LLVMTargetMachine &TM,
+ CGPassBuilderOption Opts,
+ PassInstrumentationCallbacks *PIC)
+ : CodeGenPassBuilder(TM, Opts, PIC) {}
+ void addPreISel(AddIRPass &addPass) const;
+ void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const;
+ Error addInstSelector(AddMachinePass &) const;
+};
+
+void X86CodeGenPassBuilder::addPreISel(AddIRPass &addPass) const {
+ // TODO: Add passes pre instruction selection.
+}
+
+void X86CodeGenPassBuilder::addAsmPrinter(AddMachinePass &addPass,
+ CreateMCStreamer) const {
+ // TODO: Add AsmPrinter.
+}
+
+Error X86CodeGenPassBuilder::addInstSelector(AddMachinePass &) const {
+ // TODO: Add instruction selector.
+ return Error::success();
+}
+
+} // namespace
+
+Error X86TargetMachine::buildCodeGenPipeline(
+ ModulePassManager &MPM, MachineFunctionPassManager &MFPM,
+ MachineFunctionAnalysisManager &, raw_pwrite_stream &Out,
+ raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
+ CGPassBuilderOption Opt, PassInstrumentationCallbacks *PIC) {
+ auto CGPB = X86CodeGenPassBuilder(*this, Opt, PIC);
+ return CGPB.buildPipeline(MPM, MFPM, Out, DwoOut, FileType);
+}
diff --git a/llvm/lib/Target/X86/X86TargetMachine.h b/llvm/lib/Target/X86/X86TargetMachine.h
index 4836be4db0e8e8..f31c971df9584d 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.h
+++ b/llvm/lib/Target/X86/X86TargetMachine.h
@@ -58,6 +58,12 @@ class X86TargetMachine final : public LLVMTargetMachine {
createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
const TargetSubtargetInfo *STI) const override;
+ Error buildCodeGenPipeline(ModulePassManager &, MachineFunctionPassManager &,
+ MachineFunctionAnalysisManager &,
+ raw_pwrite_stream &, raw_pwrite_stream *,
+ CodeGenFileType, CGPassBuilderOption,
+ PassInstrumentationCallbacks *) override;
+
bool isJIT() const { return IsJIT; }
bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override;
>From 7f96af2dcdfa6c573687c526a8533dec7d9e5cd3 Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Fri, 19 Jan 2024 17:56:45 +0800
Subject: [PATCH 2/8] [llc] Move tests
---
llvm/test/tools/llc/new-pm/lit.local.cfg | 2 +
llvm/test/tools/llc/new-pm/pipeline.ll | 5 +
llvm/test/tools/llc/new-pm/start-stop.ll | 4 +
llvm/unittests/CodeGen/CMakeLists.txt | 1 -
.../CodeGen/CodeGenPassBuilderTest.cpp | 141 ------------------
5 files changed, 11 insertions(+), 142 deletions(-)
create mode 100644 llvm/test/tools/llc/new-pm/lit.local.cfg
create mode 100644 llvm/test/tools/llc/new-pm/pipeline.ll
create mode 100644 llvm/test/tools/llc/new-pm/start-stop.ll
delete mode 100644 llvm/unittests/CodeGen/CodeGenPassBuilderTest.cpp
diff --git a/llvm/test/tools/llc/new-pm/lit.local.cfg b/llvm/test/tools/llc/new-pm/lit.local.cfg
new file mode 100644
index 00000000000000..42bf50dcc13c35
--- /dev/null
+++ b/llvm/test/tools/llc/new-pm/lit.local.cfg
@@ -0,0 +1,2 @@
+if not "X86" in config.root.targets:
+ config.unsupported = True
diff --git a/llvm/test/tools/llc/new-pm/pipeline.ll b/llvm/test/tools/llc/new-pm/pipeline.ll
new file mode 100644
index 00000000000000..1ace5963e4ef8c
--- /dev/null
+++ b/llvm/test/tools/llc/new-pm/pipeline.ll
@@ -0,0 +1,5 @@
+; RUN: llc -mtriple=x86_64-pc-linux-gnu -enable-new-pm -print-pipeline-passes -filetype=null %s | FileCheck %s
+
+; CHECK: require<profile-summary>,require<collector-metadata>
+; CHECK: MachineSanitizerBinaryMetadata,FreeMachineFunctionPass
+
diff --git a/llvm/test/tools/llc/new-pm/start-stop.ll b/llvm/test/tools/llc/new-pm/start-stop.ll
new file mode 100644
index 00000000000000..9b43d227041d23
--- /dev/null
+++ b/llvm/test/tools/llc/new-pm/start-stop.ll
@@ -0,0 +1,4 @@
+; RUN: llc -mtriple=x86_64-pc-linux-gnu -enable-new-pm -print-pipeline-passes -start-before=mergeicmps -stop-after=gc-lowering -filetype=null %s | FileCheck %s
+
+; CHECK: function(mergeicmps,expand-memcmp,gc-lowering)
+
diff --git a/llvm/unittests/CodeGen/CMakeLists.txt b/llvm/unittests/CodeGen/CMakeLists.txt
index c78cbfcc281939..6140e0d6fb370b 100644
--- a/llvm/unittests/CodeGen/CMakeLists.txt
+++ b/llvm/unittests/CodeGen/CMakeLists.txt
@@ -25,7 +25,6 @@ add_llvm_unittest(CodeGenTests
AMDGPUMetadataTest.cpp
AsmPrinterDwarfTest.cpp
CCStateTest.cpp
- CodeGenPassBuilderTest.cpp
DIEHashTest.cpp
DIETest.cpp
DwarfStringPoolEntryRefTest.cpp
diff --git a/llvm/unittests/CodeGen/CodeGenPassBuilderTest.cpp b/llvm/unittests/CodeGen/CodeGenPassBuilderTest.cpp
deleted file mode 100644
index d6ec393155cf09..00000000000000
--- a/llvm/unittests/CodeGen/CodeGenPassBuilderTest.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-//===- llvm/unittest/CodeGen/CodeGenPassBuilderTest.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
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CodeGen/CodeGenPassBuilder.h"
-#include "llvm/CodeGen/MachinePassManager.h"
-#include "llvm/CodeGen/TargetPassConfig.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/TargetRegistry.h"
-#include "llvm/Passes/PassBuilder.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/TargetSelect.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/TargetParser/Host.h"
-#include "gtest/gtest.h"
-#include <string>
-
-using namespace llvm;
-
-namespace {
-
-class DummyCodeGenPassBuilder
- : public CodeGenPassBuilder<DummyCodeGenPassBuilder> {
-public:
- DummyCodeGenPassBuilder(LLVMTargetMachine &TM, CGPassBuilderOption Opts,
- PassInstrumentationCallbacks *PIC)
- : CodeGenPassBuilder(TM, Opts, PIC){};
-
- void addPreISel(AddIRPass &addPass) const {
- addPass(NoOpModulePass());
- addPass(NoOpFunctionPass());
- addPass(NoOpFunctionPass());
- addPass(NoOpFunctionPass());
- addPass(NoOpModulePass());
- addPass(NoOpFunctionPass());
- }
-
- void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const {}
-
- Error addInstSelector(AddMachinePass &) const { return Error::success(); }
-};
-
-class CodeGenPassBuilderTest : public testing::Test {
-public:
- std::unique_ptr<LLVMTargetMachine> TM;
-
- static void SetUpTestCase() {
- InitializeAllTargets();
- InitializeAllTargetMCs();
-
- // TODO: Move this test to normal lit test when llc supports new pm.
- static const char *argv[] = {
- "test",
- "-print-pipeline-passes",
- };
- int argc = std::size(argv);
- cl::ParseCommandLineOptions(argc, argv);
- }
-
- void SetUp() override {
- std::string TripleName = Triple::normalize("x86_64-pc-linux-gnu");
- std::string Error;
- const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
- if (!TheTarget)
- GTEST_SKIP();
-
- TargetOptions Options;
- TM = std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>(
- TheTarget->createTargetMachine("", "", "", Options, std::nullopt)));
- if (!TM)
- GTEST_SKIP();
- }
-};
-
-TEST_F(CodeGenPassBuilderTest, basic) {
- LoopAnalysisManager LAM;
- FunctionAnalysisManager FAM;
- CGSCCAnalysisManager CGAM;
- ModuleAnalysisManager MAM;
-
- PassInstrumentationCallbacks PIC;
- DummyCodeGenPassBuilder CGPB(*TM, getCGPassBuilderOption(), &PIC);
- PipelineTuningOptions PTO;
- PassBuilder PB(TM.get(), PTO, std::nullopt, &PIC);
-
- PB.registerModuleAnalyses(MAM);
- PB.registerCGSCCAnalyses(CGAM);
- PB.registerFunctionAnalyses(FAM);
- PB.registerLoopAnalyses(LAM);
- PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
-
- ModulePassManager MPM;
- MachineFunctionPassManager MFPM;
- Error Err =
- CGPB.buildPipeline(MPM, MFPM, outs(), nullptr, CodeGenFileType::Null);
- EXPECT_FALSE(Err);
-
- std::string IRPipeline;
- raw_string_ostream IROS(IRPipeline);
- MPM.printPipeline(IROS, [&PIC](StringRef Name) {
- auto PassName = PIC.getPassNameForClassName(Name);
- return PassName.empty() ? Name : PassName;
- });
- const char ExpectedIRPipeline[] =
- "no-op-module,function(no-op-function,"
- "no-op-function,no-op-function),no-op-module";
- // TODO: Move this test to normal lit test when llc supports new pm.
- EXPECT_TRUE(StringRef(IRPipeline).contains(ExpectedIRPipeline));
-
- std::string MIRPipeline;
- raw_string_ostream MIROS(MIRPipeline);
- MFPM.printPipeline(MIROS, [&PIC](StringRef Name) {
- auto PassName = PIC.getPassNameForClassName(Name);
- return PassName.empty() ? Name : PassName;
- });
- const char ExpectedMIRPipeline[] =
- "FinalizeISelPass,EarlyTailDuplicatePass,OptimizePHIsPass,"
- "StackColoringPass,LocalStackSlotPass,DeadMachineInstructionElimPass,"
- "EarlyMachineLICMPass,MachineCSEPass,MachineSinkingPass,"
- "PeepholeOptimizerPass,DeadMachineInstructionElimPass,"
- "DetectDeadLanesPass,ProcessImplicitDefsPass,PHIEliminationPass,"
- "TwoAddressInstructionPass,RegisterCoalescerPass,"
- "RenameIndependentSubregsPass,MachineSchedulerPass,RAGreedyPass,"
- "VirtRegRewriterPass,StackSlotColoringPass,"
- "RemoveRedundantDebugValuesPass,PostRAMachineSinkingPass,ShrinkWrapPass,"
- "PrologEpilogInserterPass,BranchFolderPass,TailDuplicatePass,"
- "MachineLateInstrsCleanupPass,MachineCopyPropagationPass,"
- "ExpandPostRAPseudosPass,PostRASchedulerPass,MachineBlockPlacementPass,"
- "FEntryInserterPass,XRayInstrumentationPass,PatchableFunctionPass,"
- "FuncletLayoutPass,StackMapLivenessPass,LiveDebugValuesPass,"
- "MachineSanitizerBinaryMetadata,FreeMachineFunctionPass";
- // TODO: Check pipeline string when all pass names are populated.
- // TODO: Move this test to normal lit test when llc supports new pm.
- EXPECT_EQ(MIRPipeline, ExpectedMIRPipeline);
-}
-
-} // namespace
>From d8f253276323c9e923d9b70590935449917fc8ac Mon Sep 17 00:00:00 2001
From: Yuanfang Chen <455423+yuanfang-chen at users.noreply.github.com>
Date: Wed, 1 Nov 2023 10:48:45 +0800
Subject: [PATCH 3/8] [NewPM][CodeGen] Add NPM support to llc
This patch add new pass manager support to llc. User can use `--passes`
to run mir passes in new pass manager.
This patch is taken from D83612, the original author is yichen.
---
llvm/tools/llc/CMakeLists.txt | 3 +
llvm/tools/llc/NewPMDriver.cpp | 243 +++++++++++++++++++++++++++++++++
llvm/tools/llc/NewPMDriver.h | 49 +++++++
llvm/tools/llc/llc.cpp | 66 ++++-----
4 files changed, 329 insertions(+), 32 deletions(-)
create mode 100644 llvm/tools/llc/NewPMDriver.cpp
create mode 100644 llvm/tools/llc/NewPMDriver.h
diff --git a/llvm/tools/llc/CMakeLists.txt b/llvm/tools/llc/CMakeLists.txt
index 257d5b519f0406..01825c6e4c64c7 100644
--- a/llvm/tools/llc/CMakeLists.txt
+++ b/llvm/tools/llc/CMakeLists.txt
@@ -8,9 +8,11 @@ set(LLVM_LINK_COMPONENTS
CodeGen
CodeGenTypes
Core
+ IRPrinter
IRReader
MC
MIRParser
+ Passes
Remarks
ScalarOpts
SelectionDAG
@@ -23,6 +25,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_tool(llc
llc.cpp
+ NewPMDriver.cpp
DEPENDS
intrinsics_gen
diff --git a/llvm/tools/llc/NewPMDriver.cpp b/llvm/tools/llc/NewPMDriver.cpp
new file mode 100644
index 00000000000000..bd6fe896786f90
--- /dev/null
+++ b/llvm/tools/llc/NewPMDriver.cpp
@@ -0,0 +1,243 @@
+//===- NewPMDriver.cpp - Driver for llc using new PM ----------------------===//
+//
+// 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
+///
+/// This file is just a split of the code that logically belongs in llc.cpp but
+/// that includes the new pass manager headers.
+///
+//===----------------------------------------------------------------------===//
+
+#include "NewPMDriver.h"
+#include "llvm/Analysis/CGSCCPassManager.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/CodeGen/CodeGenPassBuilder.h"
+#include "llvm/CodeGen/CommandFlags.h"
+#include "llvm/CodeGen/MIRParser/MIRParser.h"
+#include "llvm/CodeGen/MIRPrinter.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachinePassManager.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/IRReader/IRReader.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Passes/StandardInstrumentations.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Target/CGPassBuilderOption.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Transforms/Scalar/LoopPassManager.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+
+namespace llvm {
+extern cl::opt<bool> PrintPipelinePasses;
+} // namespace llvm
+
+using namespace llvm;
+
+static cl::opt<RegAllocType> RegAlloc(
+ "regalloc-npm", cl::desc("Register allocator to use for new pass manager"),
+ cl::Hidden, cl::ValueOptional, cl::init(RegAllocType::Default),
+ cl::values(
+ clEnumValN(RegAllocType::Default, "default",
+ "pick register allocator based on -O option"),
+ clEnumValN(RegAllocType::Basic, "basic", "basic register allocator"),
+ clEnumValN(RegAllocType::Fast, "fast", "fast register allocator"),
+ clEnumValN(RegAllocType::Greedy, "greedy", "greedy register allocator"),
+ clEnumValN(RegAllocType::PBQP, "pbqp", "PBQP register allocator")));
+
+static cl::opt<bool>
+ DebugPM("debug-pass-manager", cl::Hidden,
+ cl::desc("Print pass management debugging information"));
+
+bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) {
+ DiagnosticHandler::handleDiagnostics(DI);
+ if (DI.getKind() == llvm::DK_SrcMgr) {
+ const auto &DISM = cast<DiagnosticInfoSrcMgr>(DI);
+ const SMDiagnostic &SMD = DISM.getSMDiag();
+
+ SMD.print(nullptr, errs());
+
+ // For testing purposes, we print the LocCookie here.
+ if (DISM.isInlineAsmDiag() && DISM.getLocCookie())
+ WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n";
+
+ return true;
+ }
+
+ if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
+ if (!Remark->isEnabled())
+ return true;
+
+ DiagnosticPrinterRawOStream DP(errs());
+ errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
+ DI.print(DP);
+ errs() << "\n";
+ return true;
+}
+
+static llvm::ExitOnError ExitOnErr;
+
+static void RunPasses(bool BOS, ToolOutputFile *Out, Module *M,
+ LLVMContext &Context, SmallString<0> &Buffer,
+ ModulePassManager *MPM, ModuleAnalysisManager *MAM,
+ MachineFunctionPassManager &MFPM,
+ MachineFunctionAnalysisManager &MFAM) {
+ assert(M && "invalid input module!");
+
+ // Before executing passes, print the final values of the LLVM options.
+ cl::PrintOptionValues();
+
+ if (MPM) {
+ assert(MAM && "expect a ModuleAnalysisManager!");
+ MPM->run(*M, *MAM);
+ }
+
+ ExitOnErr(MFPM.run(*M, MFAM));
+
+ if (Context.getDiagHandlerPtr()->HasErrors)
+ exit(1);
+
+ if (BOS)
+ Out->os() << Buffer;
+}
+
+int llvm::compileModuleWithNewPM(
+ StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR,
+ std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out,
+ std::unique_ptr<ToolOutputFile> DwoOut, LLVMContext &Context,
+ const TargetLibraryInfoImpl &TLII, bool NoVerify, StringRef PassPipeline,
+ CodeGenFileType FileType) {
+
+ if (!PassPipeline.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) {
+ WithColor::warning(errs(), Arg0)
+ << "--passes cannot be used with "
+ << TargetPassConfig::getLimitedCodeGenPipelineReason() << ".\n";
+ return 1;
+ }
+
+ LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine &>(*Target);
+
+ {
+ raw_pwrite_stream *OS = &Out->os();
+
+ // Manually do the buffering rather than using buffer_ostream,
+ // so we can memcmp the contents in CompileTwice mode in future.
+ SmallString<0> Buffer;
+ std::unique_ptr<raw_svector_ostream> BOS;
+ if ((codegen::getFileType() != CodeGenFileType::AssemblyFile &&
+ !Out->os().supportsSeeking())) {
+ BOS = std::make_unique<raw_svector_ostream>(Buffer);
+ OS = BOS.get();
+ }
+
+ // Fetch options from TargetPassConfig
+ CGPassBuilderOption Opt = getCGPassBuilderOption();
+ Opt.DisableVerify = NoVerify;
+ Opt.DebugPM = DebugPM;
+ Opt.RegAlloc = RegAlloc;
+
+ PassInstrumentationCallbacks PIC;
+ StandardInstrumentations SI(Context, Opt.DebugPM);
+ SI.registerCallbacks(PIC);
+ registerCodeGenCallback(PIC, LLVMTM);
+
+ LoopAnalysisManager LAM;
+ FunctionAnalysisManager FAM;
+ CGSCCAnalysisManager CGAM;
+ ModuleAnalysisManager MAM;
+ PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC);
+ PB.registerModuleAnalyses(MAM);
+ PB.registerCGSCCAnalyses(CGAM);
+ PB.registerFunctionAnalyses(FAM);
+ PB.registerLoopAnalyses(LAM);
+ PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+ FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); });
+ MAM.registerPass([&] { return MachineModuleAnalysis(&LLVMTM); });
+
+ MachineFunctionAnalysisManager MFAM(FAM, MAM);
+
+ if (!PassPipeline.empty()) {
+ // Construct a custom pass pipeline that starts after instruction
+ // selection.
+
+ if (!MIR) {
+ WithColor::warning(errs(), Arg0) << "-passes is for .mir file only.\n";
+ return 1;
+ }
+
+ MachineFunctionPassManager MFPM;
+ ExitOnErr(PB.parsePassPipeline(MFPM, PassPipeline));
+ MFPM.addPass(PrintMIRPass(*OS));
+ MFPM.addPass(FreeMachineFunctionPass());
+
+ auto &MMI = MFAM.getResult<MachineModuleAnalysis>(*M);
+ if (MIR->parseMachineFunctions(*M, MMI))
+ return 1;
+
+ RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, nullptr,
+ nullptr, MFPM, MFAM);
+ } else {
+ ModulePassManager MPM;
+ MachineFunctionPassManager MFPM;
+
+ ExitOnErr(LLVMTM.buildCodeGenPipeline(MPM, MFPM, MFAM, *OS,
+ DwoOut ? &DwoOut->os() : nullptr,
+ FileType, Opt, &PIC));
+
+ auto StartStopInfo = TargetPassConfig::getStartStopInfo(PIC);
+ assert(StartStopInfo && "Expect StartStopInfo!");
+ // Add IR or MIR printing pass according the pass type.
+
+ if (auto StopPassName = StartStopInfo->StopPass; !StopPassName.empty()) {
+ MFPM.addPass(PrintMIRPass(*OS));
+ MFPM.addPass(FreeMachineFunctionPass());
+ }
+
+ if (PrintPipelinePasses) {
+ std::string IRPipeline;
+ raw_string_ostream IRSOS(IRPipeline);
+ MPM.printPipeline(IRSOS, [&PIC](StringRef ClassName) {
+ auto PassName = PIC.getPassNameForClassName(ClassName);
+ return PassName.empty() ? ClassName : PassName;
+ });
+ outs() << "IR pipeline: " << IRPipeline << '\n';
+
+ std::string MIRPipeline;
+ raw_string_ostream MIRSOS(MIRPipeline);
+ MFPM.printPipeline(MIRSOS, [&PIC](StringRef ClassName) {
+ auto PassName = PIC.getPassNameForClassName(ClassName);
+ return PassName.empty() ? ClassName : PassName;
+ });
+ outs() << "MIR pipeline: " << MIRPipeline << '\n';
+ }
+
+ RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, &MPM, &MAM,
+ MFPM, MFAM);
+ }
+ }
+
+ // Declare success.
+ Out->keep();
+ if (DwoOut)
+ DwoOut->keep();
+
+ return 0;
+}
diff --git a/llvm/tools/llc/NewPMDriver.h b/llvm/tools/llc/NewPMDriver.h
new file mode 100644
index 00000000000000..b0beeaf596c8fd
--- /dev/null
+++ b/llvm/tools/llc/NewPMDriver.h
@@ -0,0 +1,49 @@
+//===- NewPMDriver.h - Function to drive llc with the new PM ----*- 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
+///
+/// A single function which is called to drive the llc behavior for the new
+/// PassManager.
+///
+/// This is only in a separate TU with a header to avoid including all of the
+/// old pass manager headers and the new pass manager headers into the same
+/// file. Eventually all of the routines here will get folded back into
+/// llc.cpp.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_LLC_NEWPMDRIVER_H
+#define LLVM_TOOLS_LLC_NEWPMDRIVER_H
+
+#include "llvm/IR/DiagnosticHandler.h"
+#include "llvm/Support/CodeGen.h"
+#include <memory>
+#include <vector>
+
+namespace llvm {
+class Module;
+class TargetLibraryInfoImpl;
+class TargetMachine;
+class ToolOutputFile;
+class LLVMContext;
+class MIRParser;
+
+struct LLCDiagnosticHandler : public DiagnosticHandler {
+ bool handleDiagnostics(const DiagnosticInfo &DI) override;
+};
+
+int compileModuleWithNewPM(StringRef Arg0, std::unique_ptr<Module> M,
+ std::unique_ptr<MIRParser> MIR,
+ std::unique_ptr<TargetMachine> Target,
+ std::unique_ptr<ToolOutputFile> Out,
+ std::unique_ptr<ToolOutputFile> DwoOut,
+ LLVMContext &Context,
+ const TargetLibraryInfoImpl &TLII, bool NoVerify,
+ StringRef PassPipeline, CodeGenFileType FileType);
+} // namespace llvm
+
+#endif
diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp
index 4a1957588a2243..b60ed0f7eb9a22 100644
--- a/llvm/tools/llc/llc.cpp
+++ b/llvm/tools/llc/llc.cpp
@@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//
+#include "NewPMDriver.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
@@ -186,6 +187,21 @@ static cl::opt<std::string> RemarksFormat(
cl::desc("The format used for serializing remarks (default: YAML)"),
cl::value_desc("format"), cl::init("yaml"));
+static cl::opt<bool> EnableNewPassManager(
+ "enable-new-pm", cl::desc("Enable the new pass manager"), cl::init(false));
+
+// This flag specifies a textual description of the optimization pass pipeline
+// to run over the module. This flag switches opt to use the new pass manager
+// infrastructure, completely disabling all of the flags specific to the old
+// pass management.
+static cl::opt<std::string> PassPipeline(
+ "passes",
+ cl::desc(
+ "A textual description of the pass pipeline. To have analysis passes "
+ "available before a certain pass, add 'require<foo-analysis>'."));
+static cl::alias PassPipeline2("p", cl::aliasopt(PassPipeline),
+ cl::desc("Alias for -passes"));
+
static cl::opt<bool> TryUseNewDbgInfoFormat(
"try-experimental-debuginfo-iterators",
cl::desc("Enable debuginfo iterator positions, if they're built in"),
@@ -306,34 +322,6 @@ static std::unique_ptr<ToolOutputFile> GetOutputStream(const char *TargetName,
return FDOut;
}
-struct LLCDiagnosticHandler : public DiagnosticHandler {
- bool handleDiagnostics(const DiagnosticInfo &DI) override {
- DiagnosticHandler::handleDiagnostics(DI);
- if (DI.getKind() == llvm::DK_SrcMgr) {
- const auto &DISM = cast<DiagnosticInfoSrcMgr>(DI);
- const SMDiagnostic &SMD = DISM.getSMDiag();
-
- SMD.print(nullptr, errs());
-
- // For testing purposes, we print the LocCookie here.
- if (DISM.isInlineAsmDiag() && DISM.getLocCookie())
- WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n";
-
- return true;
- }
-
- if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
- if (!Remark->isEnabled())
- return true;
-
- DiagnosticPrinterRawOStream DP(errs());
- errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
- DI.print(DP);
- errs() << "\n";
- return true;
- }
-};
-
// main - Entry point for the llc compiler.
//
int main(int argc, char **argv) {
@@ -377,6 +365,13 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");
+ if (!PassPipeline.empty() && !getRunPassNames().empty()) {
+ errs() << "The `llc -run-pass=...` syntax for the new pass manager is "
+ "not supported, please use `llc -passes=<pipeline>` (or the `-p` "
+ "alias for a more concise version).\n";
+ return 1;
+ }
+
// RemoveDIs debug-info transition: tests may request that we /try/ to use the
// new debug-info format, if it's built in.
#ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
@@ -642,16 +637,12 @@ static int compileModule(char **argv, LLVMContext &Context) {
reportError(EC.message(), SplitDwarfOutputFile);
}
- // Build up all of the passes that we want to do to the module.
- legacy::PassManager PM;
-
// Add an appropriate TargetLibraryInfo pass for the module's triple.
TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
// The -disable-simplify-libcalls flag actually disables all builtin optzns.
if (DisableSimplifyLibCalls)
TLII.disableAllFunctions();
- PM.add(new TargetLibraryInfoWrapperPass(TLII));
// Verify module immediately to catch problems before doInitialization() is
// called on any passes.
@@ -667,6 +658,17 @@ static int compileModule(char **argv, LLVMContext &Context) {
WithColor::warning(errs(), argv[0])
<< ": warning: ignoring -mc-relax-all because filetype != obj";
+ if (EnableNewPassManager || !PassPipeline.empty()) {
+ return compileModuleWithNewPM(argv[0], std::move(M), std::move(MIR),
+ std::move(Target), std::move(Out),
+ std::move(DwoOut), Context, TLII, NoVerify,
+ PassPipeline, codegen::getFileType());
+ }
+
+ // Build up all of the passes that we want to do to the module.
+ legacy::PassManager PM;
+ PM.add(new TargetLibraryInfoWrapperPass(TLII));
+
{
raw_pwrite_stream *OS = &Out->os();
>From 758831e3f9416b415014f7c770a3906b1200b87f Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Tue, 23 Jan 2024 09:02:55 +0800
Subject: [PATCH 4/8] use " and " only in `getLimitedCodeGenPipelineReason`
---
llvm/include/llvm/CodeGen/TargetPassConfig.h | 3 +--
llvm/lib/CodeGen/TargetPassConfig.cpp | 5 ++---
llvm/tools/llc/llc.cpp | 2 +-
3 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetPassConfig.h b/llvm/include/llvm/CodeGen/TargetPassConfig.h
index de6a760c4e4fd1..da96da944c04f4 100644
--- a/llvm/include/llvm/CodeGen/TargetPassConfig.h
+++ b/llvm/include/llvm/CodeGen/TargetPassConfig.h
@@ -174,8 +174,7 @@ class TargetPassConfig : public ImmutablePass {
/// If hasLimitedCodeGenPipeline is true, this method
/// returns a string with the name of the options, separated
/// by \p Separator that caused this pipeline to be limited.
- static std::string
- getLimitedCodeGenPipelineReason(const char *Separator = "/");
+ static std::string getLimitedCodeGenPipelineReason();
struct StartStopInfo {
bool StartAfter;
diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp
index 76ba8da547e6b9..853e1f23b6f8b4 100644
--- a/llvm/lib/CodeGen/TargetPassConfig.cpp
+++ b/llvm/lib/CodeGen/TargetPassConfig.cpp
@@ -635,8 +635,7 @@ bool TargetPassConfig::hasLimitedCodeGenPipeline() {
!willCompleteCodeGenPipeline();
}
-std::string
-TargetPassConfig::getLimitedCodeGenPipelineReason(const char *Separator) {
+std::string TargetPassConfig::getLimitedCodeGenPipelineReason() {
if (!hasLimitedCodeGenPipeline())
return std::string();
std::string Res;
@@ -648,7 +647,7 @@ TargetPassConfig::getLimitedCodeGenPipelineReason(const char *Separator) {
for (int Idx = 0; Idx < 4; ++Idx)
if (!PassNames[Idx]->empty()) {
if (!IsFirst)
- Res += Separator;
+ Res += " and ";
IsFirst = false;
Res += OptNames[Idx];
}
diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp
index b60ed0f7eb9a22..94d034064ac572 100644
--- a/llvm/tools/llc/llc.cpp
+++ b/llvm/tools/llc/llc.cpp
@@ -702,7 +702,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
if (TPC.hasLimitedCodeGenPipeline()) {
WithColor::warning(errs(), argv[0])
<< "run-pass cannot be used with "
- << TPC.getLimitedCodeGenPipelineReason(" and ") << ".\n";
+ << TPC.getLimitedCodeGenPipelineReason() << ".\n";
delete PTPC;
delete MMIWP;
return 1;
>From eeb115c92107ca4c94ff4fbd97eb5922af2cb376 Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Tue, 23 Jan 2024 09:07:25 +0800
Subject: [PATCH 5/8] Return after PrintPipelinePasses
---
llvm/tools/llc/NewPMDriver.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/tools/llc/NewPMDriver.cpp b/llvm/tools/llc/NewPMDriver.cpp
index bd6fe896786f90..8e1637409f8828 100644
--- a/llvm/tools/llc/NewPMDriver.cpp
+++ b/llvm/tools/llc/NewPMDriver.cpp
@@ -227,6 +227,7 @@ int llvm::compileModuleWithNewPM(
return PassName.empty() ? ClassName : PassName;
});
outs() << "MIR pipeline: " << MIRPipeline << '\n';
+ return 0;
}
RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, &MPM, &MAM,
>From 13d6d53cf87bc83b639373ab6c0c97e1254eacba Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Tue, 23 Jan 2024 09:09:17 +0800
Subject: [PATCH 6/8] use `--match-full-lines` in start stop test
---
llvm/test/tools/llc/new-pm/start-stop.ll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/test/tools/llc/new-pm/start-stop.ll b/llvm/test/tools/llc/new-pm/start-stop.ll
index 9b43d227041d23..c25e45d1f7ab9f 100644
--- a/llvm/test/tools/llc/new-pm/start-stop.ll
+++ b/llvm/test/tools/llc/new-pm/start-stop.ll
@@ -1,4 +1,4 @@
-; RUN: llc -mtriple=x86_64-pc-linux-gnu -enable-new-pm -print-pipeline-passes -start-before=mergeicmps -stop-after=gc-lowering -filetype=null %s | FileCheck %s
+; RUN: llc -mtriple=x86_64-pc-linux-gnu -enable-new-pm -print-pipeline-passes -start-before=mergeicmps -stop-after=gc-lowering -filetype=null %s | FileCheck --match-full-lines %s
-; CHECK: function(mergeicmps,expand-memcmp,gc-lowering)
+; CHECK: IR pipeline: function(mergeicmps,expand-memcmp,gc-lowering)
>From 691b64737f7717986b3200d7696a779b99f12845 Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Tue, 23 Jan 2024 09:23:45 +0800
Subject: [PATCH 7/8] Add test for conflict option
---
llvm/test/tools/llc/new-pm/option-conflict.ll | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 llvm/test/tools/llc/new-pm/option-conflict.ll
diff --git a/llvm/test/tools/llc/new-pm/option-conflict.ll b/llvm/test/tools/llc/new-pm/option-conflict.ll
new file mode 100644
index 00000000000000..2adac76f239e4e
--- /dev/null
+++ b/llvm/test/tools/llc/new-pm/option-conflict.ll
@@ -0,0 +1,3 @@
+; RUN: not llc -mtriple=x86_64-pc-linux-gnu -passes=foo -start-before=mergeicmps -stop-after=gc-lowering -filetype=null %s 2>&1 | FileCheck %s
+
+; CHECK: warning: run-pass cannot be used with start-before and stop-after.
>From 4fa708acea532a1d28125dd0a928450782e3ad05 Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Tue, 23 Jan 2024 14:31:38 +0800
Subject: [PATCH 8/8] fix doc string in getLimitedCodeGenPipelineReason
---
llvm/include/llvm/CodeGen/TargetPassConfig.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetPassConfig.h b/llvm/include/llvm/CodeGen/TargetPassConfig.h
index da96da944c04f4..d00e0bed91a457 100644
--- a/llvm/include/llvm/CodeGen/TargetPassConfig.h
+++ b/llvm/include/llvm/CodeGen/TargetPassConfig.h
@@ -171,9 +171,9 @@ class TargetPassConfig : public ImmutablePass {
/// set.
static bool willCompleteCodeGenPipeline();
- /// If hasLimitedCodeGenPipeline is true, this method
- /// returns a string with the name of the options, separated
- /// by \p Separator that caused this pipeline to be limited.
+ /// If hasLimitedCodeGenPipeline is true, this method returns
+ /// a string with the name of the options that caused this
+ /// pipeline to be limited.
static std::string getLimitedCodeGenPipelineReason();
struct StartStopInfo {
More information about the llvm-commits
mailing list