[llvm] 7e50f00 - [NewPM][CodeGen][llc] Add NPM support (#70922)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 23 17:27:29 PST 2024


Author: paperchalice
Date: 2024-01-24T09:27:25+08:00
New Revision: 7e50f006f7f652b9a5ac5ddd64deba5f1c9388a8

URL: https://github.com/llvm/llvm-project/commit/7e50f006f7f652b9a5ac5ddd64deba5f1c9388a8
DIFF: https://github.com/llvm/llvm-project/commit/7e50f006f7f652b9a5ac5ddd64deba5f1c9388a8.diff

LOG: [NewPM][CodeGen][llc] Add NPM support (#70922)

Add new pass manager support to `llc`. Users can use
`--passes=pass1,pass2...` to run mir passes, and use `--enable-new-pm`
to run default codegen pipeline.
This patch is taken from [D83612](https://reviews.llvm.org/D83612), the
original author is @yuanfang-chen.

---------

Co-authored-by: Yuanfang Chen <455423+yuanfang-chen at users.noreply.github.com>

Added: 
    llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
    llvm/test/tools/llc/new-pm/lit.local.cfg
    llvm/test/tools/llc/new-pm/option-conflict.ll
    llvm/test/tools/llc/new-pm/pipeline.ll
    llvm/test/tools/llc/new-pm/start-stop.ll
    llvm/tools/llc/NewPMDriver.cpp
    llvm/tools/llc/NewPMDriver.h

Modified: 
    llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
    llvm/include/llvm/CodeGen/TargetPassConfig.h
    llvm/include/llvm/Target/CGPassBuilderOption.h
    llvm/lib/CodeGen/TargetPassConfig.cpp
    llvm/lib/Target/X86/CMakeLists.txt
    llvm/lib/Target/X86/X86TargetMachine.h
    llvm/tools/llc/CMakeLists.txt
    llvm/tools/llc/llc.cpp
    llvm/unittests/CodeGen/CMakeLists.txt

Removed: 
    llvm/unittests/CodeGen/CodeGenPassBuilderTest.cpp


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
index 12088f6fc35e0b8..96d6f891af4e2d7 100644
--- a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
+++ b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
@@ -1113,30 +1113,13 @@ void CodeGenPassBuilder<Derived>::addTargetRegisterAllocator(
 template <typename Derived>
 void CodeGenPassBuilder<Derived>::addRegAllocPass(AddMachinePass &addPass,
                                                   bool Optimized) const {
-  if (Opt.RegAlloc == RegAllocType::Default)
-    // With no -regalloc= override, ask the target for a regalloc pass.
-    derived().addTargetRegisterAllocator(addPass, Optimized);
-  else if (Opt.RegAlloc == RegAllocType::Basic)
-    addPass(RABasicPass());
-  else if (Opt.RegAlloc == RegAllocType::Fast)
-    addPass(RAFastPass());
-  else if (Opt.RegAlloc == RegAllocType::Greedy)
-    addPass(RAGreedyPass());
-  else if (Opt.RegAlloc == RegAllocType::PBQP)
-    addPass(RAPBQPPass());
-  else
-    llvm_unreachable("unknonwn register allocator type");
+  // TODO: Parse Opt.RegAlloc to add register allocator.
 }
 
 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());
-
+  // TODO: Ensure allocator is default or fast.
   addRegAllocPass(addPass, false);
   return Error::success();
 }

diff  --git a/llvm/include/llvm/CodeGen/TargetPassConfig.h b/llvm/include/llvm/CodeGen/TargetPassConfig.h
index de6a760c4e4fd16..d00e0bed91a4579 100644
--- a/llvm/include/llvm/CodeGen/TargetPassConfig.h
+++ b/llvm/include/llvm/CodeGen/TargetPassConfig.h
@@ -171,11 +171,10 @@ 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.
-  static std::string
-  getLimitedCodeGenPipelineReason(const char *Separator = "/");
+  /// 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 {
     bool StartAfter;

diff  --git a/llvm/include/llvm/Target/CGPassBuilderOption.h b/llvm/include/llvm/Target/CGPassBuilderOption.h
index 6b5c023a9b6adfa..8ab6d63a00056a1 100644
--- a/llvm/include/llvm/Target/CGPassBuilderOption.h
+++ b/llvm/include/llvm/Target/CGPassBuilderOption.h
@@ -52,7 +52,7 @@ struct CGPassBuilderOption {
   bool RequiresCodeGenSCCOrder = false;
 
   RunOutliner EnableMachineOutliner = RunOutliner::TargetDefault;
-  RegAllocType RegAlloc = RegAllocType::Default;
+  StringRef RegAlloc = "default";
   std::optional<GlobalISelAbortMode> EnableGlobalISelAbort;
   std::string FSProfileFile;
   std::string FSRemappingFile;

diff  --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp
index 46697480db52aa4..599ca48189048c4 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/lib/Target/X86/CMakeLists.txt b/llvm/lib/Target/X86/CMakeLists.txt
index 4d6300cad2a7a82..610999f0cc3cf09 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 000000000000000..616f777833e565c
--- /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 4836be4db0e8e84..f31c971df9584d6 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;

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 000000000000000..42bf50dcc13c35f
--- /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/option-conflict.ll b/llvm/test/tools/llc/new-pm/option-conflict.ll
new file mode 100644
index 000000000000000..5847a32058756f2
--- /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: --passes cannot be used with start-before and stop-after.

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 000000000000000..1ace5963e4ef8c5
--- /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 000000000000000..c25e45d1f7ab9f7
--- /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 --match-full-lines %s
+
+; CHECK: IR pipeline: function(mergeicmps,expand-memcmp,gc-lowering)
+

diff  --git a/llvm/tools/llc/CMakeLists.txt b/llvm/tools/llc/CMakeLists.txt
index 257d5b519f0406f..01825c6e4c64c77 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 000000000000000..13020f3dd07feba
--- /dev/null
+++ b/llvm/tools/llc/NewPMDriver.cpp
@@ -0,0 +1,236 @@
+//===- 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<std::string>
+    RegAlloc("regalloc-npm",
+             cl::desc("Register allocator to use for new pass manager"),
+             cl::Hidden, cl::init("default"));
+
+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';
+      return 0;
+    }
+
+    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 000000000000000..b0beeaf596c8fd3
--- /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 02187f7048a10de..d76d89eae3b1850 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();
 
@@ -700,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;

diff  --git a/llvm/unittests/CodeGen/CMakeLists.txt b/llvm/unittests/CodeGen/CMakeLists.txt
index c78cbfcc2819390..6140e0d6fb370b2 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 d6ec393155cf090..000000000000000
--- 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


        


More information about the llvm-commits mailing list