[llvm] [RISCV][NewPM] Add NewPM Codegen Pipeline Skeleton (PR #213129)
Sam Elliott via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 30 14:47:57 PDT 2026
https://github.com/lenary updated https://github.com/llvm/llvm-project/pull/213129
>From 35dfdc739489ee67ad907dbc061b64940b80c54d Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Thu, 30 Jul 2026 11:23:20 -0700
Subject: [PATCH 1/4] [RISCV][NewPM] Add NewPM Codegen Pipeline Skeleton
This follows what has been done for other targets. Follow-up commits
will port each pass and add them to this pipeline.
I intend to have many fewer `cl::opt`s in this pipeline, as I think lots
are left over from early work to enable specific passes.
---
llvm/lib/Target/RISCV/CMakeLists.txt | 3 +
llvm/lib/Target/RISCV/RISCV.h | 6 +
llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp | 33 +++
llvm/lib/Target/RISCV/RISCVAsmPrinter.h | 39 +++
.../Target/RISCV/RISCVCodeGenPassBuilder.cpp | 238 ++++++++++++++++++
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 4 +
llvm/lib/Target/RISCV/RISCVPassRegistry.def | 6 +
llvm/lib/Target/RISCV/RISCVTargetMachine.cpp | 13 -
llvm/lib/Target/RISCV/RISCVTargetMachine.h | 5 +
llvm/test/CodeGen/RISCV/O1-newpm-pipeline.ll | 107 ++++++++
llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll | 108 ++++++++
11 files changed, 549 insertions(+), 13 deletions(-)
create mode 100644 llvm/lib/Target/RISCV/RISCVAsmPrinter.h
create mode 100644 llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
create mode 100644 llvm/test/CodeGen/RISCV/O1-newpm-pipeline.ll
create mode 100644 llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll
diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
index afab81b2cf7b0..27879c1dd1085 100644
--- a/llvm/lib/Target/RISCV/CMakeLists.txt
+++ b/llvm/lib/Target/RISCV/CMakeLists.txt
@@ -33,6 +33,7 @@ add_public_tablegen_target(RISCVCommonTableGen)
add_llvm_target(RISCVCodeGen
RISCVAsmPrinter.cpp
RISCVCallingConv.cpp
+ RISCVCodeGenPassBuilder.cpp
RISCVCodeGenPrepare.cpp
RISCVConstantPoolValue.cpp
RISCVDeadRegisterDefinitions.cpp
@@ -93,7 +94,9 @@ add_llvm_target(RISCVCodeGen
Core
GlobalISel
IPO
+ IRPrinter
MC
+ ObjCARC
Passes
RISCVDesc
RISCVInfo
diff --git a/llvm/lib/Target/RISCV/RISCV.h b/llvm/lib/Target/RISCV/RISCV.h
index 8db90ee51c441..013cb57565d93 100644
--- a/llvm/lib/Target/RISCV/RISCV.h
+++ b/llvm/lib/Target/RISCV/RISCV.h
@@ -15,6 +15,7 @@
#define LLVM_LIB_TARGET_RISCV_RISCV_H
#include "MCTargetDesc/RISCVBaseInfo.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetMachine.h"
namespace llvm {
@@ -50,6 +51,11 @@ void initializeRISCVLandingPadSetupPass(PassRegistry &);
FunctionPass *createRISCVISelDag(RISCVTargetMachine &TM,
CodeGenOptLevel OptLevel);
+class RISCVISelDAGToDAGPass : public SelectionDAGISelPass {
+public:
+ RISCVISelDAGToDAGPass(RISCVTargetMachine &TM, CodeGenOptLevel OptLevel);
+};
+
FunctionPass *createRISCVLateBranchOptPass();
void initializeRISCVLateBranchOptPass(PassRegistry &);
diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index e37ea27364e6e..6dee7fb37ef4c 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "RISCVAsmPrinter.h"
#include "MCTargetDesc/RISCVBaseInfo.h"
#include "MCTargetDesc/RISCVELFStreamer.h"
#include "MCTargetDesc/RISCVInstPrinter.h"
@@ -26,7 +27,9 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/AsmPrinterAnalysis.h"
#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/Module.h"
@@ -1324,3 +1327,33 @@ char RISCVAsmPrinter::ID = 0;
INITIALIZE_PASS(RISCVAsmPrinter, "riscv-asm-printer", "RISC-V Assembly Printer",
false, false)
+
+PreservedAnalyses RISCVAsmPrinterBeginPass::run(Module &M,
+ ModuleAnalysisManager &MAM) {
+ RISCVAsmPrinter &AsmPrinter = static_cast<RISCVAsmPrinter &>(
+ MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
+ setupModuleAsmPrinter(M, MAM, AsmPrinter);
+ AsmPrinter.doInitialization(M);
+ return PreservedAnalyses::all();
+}
+
+PreservedAnalyses
+RISCVAsmPrinterPass::run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM) {
+ RISCVAsmPrinter &AsmPrinter = static_cast<RISCVAsmPrinter &>(
+ MFAM.getResult<ModuleAnalysisManagerMachineFunctionProxy>(MF)
+ .getCachedResult<AsmPrinterAnalysis>(*MF.getFunction().getParent())
+ ->getPrinter());
+ setupMachineFunctionAsmPrinter(MFAM, MF, AsmPrinter);
+ AsmPrinter.runOnMachineFunction(MF);
+ return PreservedAnalyses::all();
+}
+
+PreservedAnalyses RISCVAsmPrinterEndPass::run(Module &M,
+ ModuleAnalysisManager &MAM) {
+ RISCVAsmPrinter &AsmPrinter = static_cast<RISCVAsmPrinter &>(
+ MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
+ setupModuleAsmPrinter(M, MAM, AsmPrinter);
+ AsmPrinter.doFinalization(M);
+ return PreservedAnalyses::all();
+}
diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.h b/llvm/lib/Target/RISCV/RISCVAsmPrinter.h
new file mode 100644
index 0000000000000..d4a3807fc62a7
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.h
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_RISCV_RISCVASMPRINTER_H
+#define LLVM_LIB_TARGET_RISCV_RISCVASMPRINTER_H
+
+#include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
+#include "llvm/IR/Analysis.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class RISCVAsmPrinterBeginPass
+ : public RequiredPassInfoMixin<RISCVAsmPrinterBeginPass> {
+public:
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+};
+
+class RISCVAsmPrinterPass : public RequiredPassInfoMixin<RISCVAsmPrinterPass> {
+public:
+ PreservedAnalyses run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM);
+};
+
+class RISCVAsmPrinterEndPass
+ : public RequiredPassInfoMixin<RISCVAsmPrinterEndPass> {
+public:
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+};
+
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_RISCV_RISCVASMPRINTER_H
diff --git a/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp b/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
new file mode 100644
index 0000000000000..e7951918bf632
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
@@ -0,0 +1,238 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 the RISC-V CodeGen pipeline builder.
+/// TODO: Port the remaining RISC-V CodeGen passes to the new pass manager.
+//===----------------------------------------------------------------------===//
+
+#include "RISCV.h"
+#include "RISCVAsmPrinter.h"
+#include "RISCVTargetMachine.h"
+#include "llvm/CodeGen/AtomicExpand.h"
+#include "llvm/CodeGen/BranchRelaxation.h"
+#include "llvm/CodeGen/InterleavedAccess.h"
+#include "llvm/CodeGen/KCFI.h"
+#include "llvm/CodeGen/MachineCopyPropagation.h"
+#include "llvm/CodeGen/MachineInstrBundle.h"
+#include "llvm/CodeGen/MachineLICM.h"
+#include "llvm/CodeGen/TypePromotion.h"
+#include "llvm/IR/PassInstrumentation.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Passes/CodeGenPassBuilder.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Support/CodeGen.h"
+#include "llvm/Target/CGPassBuilderOption.h"
+#include "llvm/Transforms/Vectorize/LoopIdiomVectorize.h"
+#include "llvm/Transforms/Scalar/LoopDataPrefetch.h"
+
+using namespace llvm;
+
+namespace {
+
+class RISCVCodeGenPassBuilder
+ : public CodeGenPassBuilder<RISCVCodeGenPassBuilder, RISCVTargetMachine> {
+ using Base = CodeGenPassBuilder<RISCVCodeGenPassBuilder, RISCVTargetMachine>;
+
+public:
+ explicit RISCVCodeGenPassBuilder(RISCVTargetMachine &TM,
+ const CGPassBuilderOption &Opts,
+ PassInstrumentationCallbacks *PIC)
+ : CodeGenPassBuilder(TM, Opts, PIC) {
+ // TODO: See the FIXME on RISCVPassConfig::setEnableSinkAndFold in the
+ // legacy pass manager pipeline. There is currently no way to plumb
+ // -riscv-enable-sink-fold through to CGPassBuilderOption::EnableSinkAndFold
+ // from a target-local CodeGenPassBuilder, so this NewPM pipeline always
+ // uses the base class default (disabled).
+ }
+
+ void addIRPasses(PassManagerWrapper &PMW) const;
+ void addCodeGenPrepare(PassManagerWrapper &PMW) const;
+ Error addInstSelector(PassManagerWrapper &PMW) const;
+ void addPreRegAlloc(PassManagerWrapper &PMW) const;
+ void addPostRegAlloc(PassManagerWrapper &PMW) const;
+ void addMachineSSAOptimization(PassManagerWrapper &PMW) const;
+ void addPreSched2(PassManagerWrapper &PMW) const;
+ void addPreEmitPass(PassManagerWrapper &PMW) const;
+ void addPreEmitPass2(PassManagerWrapper &PMW) const;
+ void addAsmPrinterBegin(PassManagerWrapper &PMW) const;
+ void addAsmPrinter(PassManagerWrapper &PMW) const;
+ void addAsmPrinterEnd(PassManagerWrapper &PMW) const;
+};
+
+void RISCVCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) const {
+ addFunctionPass(AtomicExpandPass(TM), PMW);
+ // TODO: RISCVZacasABIFixPass
+
+ if (getOptLevel() != CodeGenOptLevel::None) {
+ addFunctionPass(LoopDataPrefetchPass(), PMW);
+
+ // TODO: RISCVGatherScatterLoweringPass
+ addFunctionPass(InterleavedAccessPass(TM), PMW);
+ addFunctionPass(RISCVCodeGenPreparePass(&TM), PMW);
+ }
+
+ Base::addIRPasses(PMW);
+
+ // TODO: SelectOptimizePass is already added by the base class when
+ // !Opt.DisableSelectOptimize. The legacy pipeline additionally gates this
+ // on -riscv-select-opt and only runs it at -O3; that extra gating is not
+ // yet replicated here.
+}
+
+void RISCVCodeGenPassBuilder::addCodeGenPrepare(PassManagerWrapper &PMW) const {
+ if (getOptLevel() != CodeGenOptLevel::None)
+ addFunctionPass(TypePromotionPass(TM), PMW);
+ Base::addCodeGenPrepare(PMW);
+}
+
+Error RISCVCodeGenPassBuilder::addInstSelector(PassManagerWrapper &PMW) const {
+ addMachineFunctionPass(RISCVISelDAGToDAGPass(TM, getOptLevel()), PMW);
+ return Error::success();
+}
+
+void RISCVCodeGenPassBuilder::addPreRegAlloc(PassManagerWrapper &PMW) const {
+ // TODO: RISCVPreRAExpandPseudoPass
+ if (getOptLevel() != CodeGenOptLevel::None) {
+ // TODO: RISCVMergeBaseOffsetOptPass
+ // TODO: RISCVPreAllocZilsdOptPass
+ }
+
+ // TODO: RISCVInsertReadWriteCSRPass
+ // TODO: RISCVInsertWriteVXRMPass
+ // TODO: RISCVLandingPadSetupPass
+
+ // TODO: MachinePipelinerPass (no new pass manager port exists yet)
+
+ // TODO: RISCVVMV0EliminationPass
+}
+
+void RISCVCodeGenPassBuilder::addPostRegAlloc(PassManagerWrapper &PMW) const {
+ if (getOptLevel() != CodeGenOptLevel::None) {
+ // TODO: RISCVRedundantCopyEliminationPass
+ }
+}
+
+void RISCVCodeGenPassBuilder::addMachineSSAOptimization(
+ PassManagerWrapper &PMW) const {
+ // It's beneficial to reduce the VL to enable more
+ // Machine SSA optimizations.
+ if (getOptLevel() != CodeGenOptLevel::None) {
+ // RISCVVLOptimizer can make loop invariant instructions like vmv.v.i
+ // loop variant by propagating a VL defined inside the loop. Run LICM and
+ // hoist them early. Don't do this at -O0 to avoid the compile-time
+ // overhead. Not reducing the VL of loop invariant pseudos results in more
+ // vsetvli toggles, and still requires the MachineLoopInfo analysis to be
+ // run.
+ addMachineFunctionPass(EarlyMachineLICMPass(), PMW);
+ // TODO: RISCVVLOptimizerPass
+ }
+
+ // TODO: RISCVVectorPeepholePass
+ // TODO: RISCVFoldMemOffsetPass
+
+ Base::addMachineSSAOptimization(PMW);
+
+ if (TM.getTargetTriple().isRISCV64()) {
+ // TODO: RISCVOptWInstrsPass
+ }
+}
+
+void RISCVCodeGenPassBuilder::addPreSched2(PassManagerWrapper &PMW) const {
+ // TODO: RISCVPostRAExpandPseudoPass
+
+ addMachineFunctionPass(MachineKCFIPass(), PMW);
+ if (getOptLevel() != CodeGenOptLevel::None) {
+ // TODO: RISCVLoadStoreOptPass
+ }
+}
+
+void RISCVCodeGenPassBuilder::addPreEmitPass(PassManagerWrapper &PMW) const {
+ // TODO: It would potentially be better to schedule copy propagation after
+ // expanding pseudos (in addPreEmitPass2). However, performing copy
+ // propagation after the machine outliner (which runs after addPreEmitPass)
+ // currently leads to incorrect code-gen, where copies to registers within
+ // outlined functions are removed erroneously.
+ if (getOptLevel() >= CodeGenOptLevel::Default) {
+ addMachineFunctionPass(MachineCopyPropagationPass(true), PMW);
+ // TODO: RISCVLateBranchOptPass
+ }
+ // The IndirectBranchTrackingPass inserts lpad and could have changed the
+ // basic block alignment. It must be done before Branch Relaxation to
+ // prevent the adjusted offset exceeding the branch range.
+ // TODO: RISCVIndirectBranchTrackingPass
+ addMachineFunctionPass(BranchRelaxationPass(), PMW);
+ // TODO: RISCVMakeCompressibleOptPass
+}
+
+void RISCVCodeGenPassBuilder::addPreEmitPass2(PassManagerWrapper &PMW) const {
+ if (getOptLevel() != CodeGenOptLevel::None) {
+ // TODO: RISCVMoveMergePass
+ // TODO: RISCVPushPopOptimizationPass
+ }
+ // TODO: RISCVExpandPseudoPass
+
+ // Add QC Relaxation Markers as late as possible, and only for RV32
+ if (getOptLevel() != CodeGenOptLevel::None &&
+ TM.getTargetTriple().isRISCV32()) {
+ // TODO: RISCVQCRelaxMarkingPass
+ }
+
+ // TODO: RISCVExpandAtomicPseudoPass
+
+ // KCFI indirect call checks are lowered to a bundle.
+ addMachineFunctionPass(
+ UnpackMachineBundlesPass([&](const MachineFunction &MF) {
+ return MF.getFunction().getParent()->getModuleFlag("kcfi");
+ }),
+ PMW);
+
+ // TODO: CFIInstrInserterPass
+}
+
+void RISCVCodeGenPassBuilder::addAsmPrinterBegin(
+ PassManagerWrapper &PMW) const {
+ addModulePass(RISCVAsmPrinterBeginPass(), PMW, /*Force=*/true);
+}
+
+void RISCVCodeGenPassBuilder::addAsmPrinter(PassManagerWrapper &PMW) const {
+ addMachineFunctionPass(RISCVAsmPrinterPass(), PMW);
+}
+
+void RISCVCodeGenPassBuilder::addAsmPrinterEnd(PassManagerWrapper &PMW) const {
+ addModulePass(RISCVAsmPrinterEndPass(), PMW, /*Force=*/true);
+}
+
+} // namespace
+
+void RISCVTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
+#define GET_PASS_REGISTRY "RISCVPassRegistry.def"
+#include "llvm/Passes/TargetPassRegistry.inc"
+
+ PB.registerLateLoopOptimizationsEPCallback([=](LoopPassManager &LPM,
+ OptimizationLevel Level) {
+ if (Level != OptimizationLevel::O0)
+ LPM.addPass(LoopIdiomVectorizePass(LoopIdiomVectorizeStyle::Predicated));
+ });
+
+ if (PIC) {
+ PIC->addClassToPassName(RISCVAsmPrinterBeginPass::name(),
+ "riscv-asm-printer-begin");
+ PIC->addClassToPassName(RISCVAsmPrinterPass::name(), "riscv-asm-printer");
+ PIC->addClassToPassName(RISCVAsmPrinterEndPass::name(),
+ "riscv-asm-printer-end");
+ }
+}
+
+Error RISCVTargetMachine::buildCodeGenPipeline(
+ ModulePassManager &MPM, ModuleAnalysisManager &MAM, raw_pwrite_stream &Out,
+ raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
+ const CGPassBuilderOption &Opt, MCContext &Ctx,
+ PassInstrumentationCallbacks *PIC) {
+ auto CGPB = RISCVCodeGenPassBuilder(*this, Opt, PIC);
+ return CGPB.buildPipeline(MPM, MAM, Out, DwoOut, FileType, Ctx);
+}
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 611306b6ab7b3..680e2fd00de21 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -5099,6 +5099,10 @@ FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM,
return new RISCVDAGToDAGISelLegacy(TM, OptLevel);
}
+RISCVISelDAGToDAGPass::RISCVISelDAGToDAGPass(RISCVTargetMachine &TM,
+ CodeGenOptLevel OptLevel)
+ : SelectionDAGISelPass(std::make_unique<RISCVDAGToDAGISel>(TM, OptLevel)) {}
+
char RISCVDAGToDAGISelLegacy::ID = 0;
RISCVDAGToDAGISelLegacy::RISCVDAGToDAGISelLegacy(RISCVTargetMachine &TM,
diff --git a/llvm/lib/Target/RISCV/RISCVPassRegistry.def b/llvm/lib/Target/RISCV/RISCVPassRegistry.def
index 29ccf2cff1ca5..b42e8ea5b9f35 100644
--- a/llvm/lib/Target/RISCV/RISCVPassRegistry.def
+++ b/llvm/lib/Target/RISCV/RISCVPassRegistry.def
@@ -18,3 +18,9 @@
#endif
FUNCTION_PASS("riscv-codegenprepare", RISCVCodeGenPreparePass(this))
#undef FUNCTION_PASS
+
+#ifndef MACHINE_FUNCTION_PASS
+#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS)
+#endif
+MACHINE_FUNCTION_PASS("riscv-isel", RISCVISelDAGToDAGPass(*this, getOptLevel()))
+#undef MACHINE_FUNCTION_PASS
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index 8cf29ca900faa..517e48faa1043 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -34,12 +34,10 @@
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/InitializePasses.h"
#include "llvm/MC/TargetRegistry.h"
-#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
-#include "llvm/Transforms/Vectorize/LoopIdiomVectorize.h"
#include <optional>
using namespace llvm;
@@ -681,17 +679,6 @@ bool RISCVPassConfig::addILPOpts() {
return true;
}
-void RISCVTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
-#define GET_PASS_REGISTRY "RISCVPassRegistry.def"
-#include "llvm/Passes/TargetPassRegistry.inc"
-
- PB.registerLateLoopOptimizationsEPCallback([=](LoopPassManager &LPM,
- OptimizationLevel Level) {
- if (Level != OptimizationLevel::O0)
- LPM.addPass(LoopIdiomVectorizePass(LoopIdiomVectorizeStyle::Predicated));
- });
-}
-
yaml::MachineFunctionInfo *
RISCVTargetMachine::createDefaultFuncInfoYAML() const {
return new yaml::RISCVMachineFunctionInfo();
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.h b/llvm/lib/Target/RISCV/RISCVTargetMachine.h
index c85c2b3d0e611..fdc76454b08d9 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.h
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.h
@@ -59,6 +59,11 @@ class RISCVTargetMachine : public CodeGenTargetMachineImpl {
SMDiagnostic &Error,
SMRange &SourceRange) const override;
void registerPassBuilderCallbacks(PassBuilder &PB) override;
+ Error buildCodeGenPipeline(ModulePassManager &MPM, ModuleAnalysisManager &MAM,
+ raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
+ CodeGenFileType FileType,
+ const CGPassBuilderOption &Opt, MCContext &Ctx,
+ PassInstrumentationCallbacks *PIC) override;
ScheduleDAGInstrs *
createMachineScheduler(MachineSchedContext *C) const override;
ScheduleDAGInstrs *
diff --git a/llvm/test/CodeGen/RISCV/O1-newpm-pipeline.ll b/llvm/test/CodeGen/RISCV/O1-newpm-pipeline.ll
new file mode 100644
index 0000000000000..92d894d445447
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/O1-newpm-pipeline.ll
@@ -0,0 +1,107 @@
+; RUN: llc -enable-new-pm -mtriple=riscv32 -O1 -print-pipeline-passes=tree < %s 2>&1 \
+; RUN: | FileCheck %s
+; RUN: llc -enable-new-pm -mtriple=riscv64 -O1 -print-pipeline-passes=tree < %s 2>&1 \
+; RUN: | FileCheck %s
+
+; CHECK: require<MachineModuleAnalysis>
+; CHECK-NEXT: require<profile-summary>
+; CHECK-NEXT: require<collector-metadata>
+; CHECK-NEXT: require<runtime-libcall-info>
+; CHECK-NEXT: require<libcall-lowering-info>
+; CHECK-NEXT: function
+; CHECK-NEXT: objc-arc-contract
+; CHECK-NEXT: pre-isel-intrinsic-lowering
+; CHECK-NEXT: function
+; CHECK-NEXT: expand-ir-insts<O1>
+; CHECK-NEXT: atomic-expand
+; CHECK-NEXT: loop-data-prefetch
+; CHECK-NEXT: interleaved-access
+; CHECK-NEXT: riscv-codegenprepare
+; CHECK-NEXT: verify
+; CHECK-NEXT: loop
+; CHECK-NEXT: canon-freeze
+; CHECK-NEXT: loop-reduce
+; CHECK-NEXT: gc-lowering
+; CHECK-NEXT: shadow-stack-gc-lowering
+; CHECK-NEXT: function
+; CHECK-NEXT: unreachableblockelim
+; CHECK-NEXT: consthoist
+; CHECK-NEXT: replace-with-veclib
+; CHECK-NEXT: partially-inline-libcalls
+; CHECK-NEXT: ee-instrument<post-inline>
+; CHECK-NEXT: scalarize-masked-mem-intrin
+; CHECK-NEXT: expand-reductions
+; CHECK-NEXT: typepromotion
+; CHECK-NEXT: codegenprepare
+; CHECK-NEXT: dwarf-eh-prepare
+; CHECK-NEXT: inline-asm-prepare
+; CHECK-NEXT: safe-stack
+; CHECK-NEXT: stack-protector
+; CHECK-NEXT: verify
+; CHECK-NEXT: riscv-asm-printer-begin
+; CHECK-NEXT: function
+; CHECK-NEXT: machine-function
+; CHECK-NEXT: riscv-isel
+; CHECK-NEXT: finalize-isel
+; CHECK-NEXT: early-machinelicm
+; CHECK-NEXT: early-tailduplication
+; CHECK-NEXT: opt-phis
+; CHECK-NEXT: stack-coloring
+; CHECK-NEXT: localstackalloc
+; CHECK-NEXT: dead-mi-elimination
+; CHECK-NEXT: early-machinelicm
+; CHECK-NEXT: machine-cse
+; CHECK-NEXT: machine-sink
+; CHECK-NEXT: peephole-opt
+; CHECK-NEXT: dead-mi-elimination
+; CHECK-NEXT: detect-dead-lanes
+; CHECK-NEXT: init-undef
+; CHECK-NEXT: process-imp-defs
+; CHECK-NEXT: unreachable-mbb-elimination
+; CHECK-NEXT: require<live-vars>
+; CHECK-NEXT: require<machine-loops>
+; CHECK-NEXT: phi-node-elimination
+; CHECK-NEXT: two-address-instruction
+; CHECK-NEXT: register-coalescer
+; CHECK-NEXT: rename-independent-subregs
+; CHECK-NEXT: machine-scheduler
+; CHECK-NEXT: greedy<all>
+; CHECK-NEXT: virt-reg-rewriter
+; CHECK-NEXT: stack-slot-coloring
+; CHECK-NEXT: machine-cp
+; CHECK-NEXT: machinelicm
+; CHECK-NEXT: remove-redundant-debug-values
+; CHECK-NEXT: fixup-statepoint-caller-saved
+; CHECK-NEXT: postra-machine-sink
+; CHECK-NEXT: shrink-wrap
+; CHECK-NEXT: prolog-epilog
+; CHECK-NEXT: machine-latecleanup
+; CHECK-NEXT: branch-folder
+; CHECK-NEXT: tailduplication
+; CHECK-NEXT: machine-cp
+; CHECK-NEXT: post-ra-pseudos
+; CHECK-NEXT: kcfi
+; CHECK-NEXT: post-RA-sched
+; CHECK-NEXT: block-placement
+; CHECK-NEXT: fentry-insert
+; CHECK-NEXT: xray-instrumentation
+; CHECK-NEXT: patchable-function
+; CHECK-NEXT: branch-relaxation
+; CHECK-NEXT: FuncletLayoutPass
+; CHECK-NEXT: remove-loads-into-fake-uses
+; CHECK-NEXT: StackMapLivenessPass
+; CHECK-NEXT: live-debug-values<emit-debug-entry-values>
+; CHECK-NEXT: machine-sanmd
+; CHECK-NEXT: MachineOutlinerPass
+; CHECK-NEXT: function
+; CHECK-NEXT: machine-function
+; CHECK-NEXT: stack-frame-layout
+; CHECK-NEXT: unpack-mi-bundles
+; CHECK-NEXT: verify
+; CHECK-NEXT: riscv-asm-printer
+; CHECK-NEXT: free-machine-function
+; CHECK-NEXT: riscv-asm-printer-end
+
+define void @f() {
+ ret void
+}
diff --git a/llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll
new file mode 100644
index 0000000000000..8fc45d046384e
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll
@@ -0,0 +1,108 @@
+; RUN: llc -enable-new-pm -mtriple=riscv32 -O3 -print-pipeline-passes=tree < %s 2>&1 \
+; RUN: | FileCheck %s
+; RUN: llc -enable-new-pm -mtriple=riscv64 -O3 -print-pipeline-passes=tree < %s 2>&1 \
+; RUN: | FileCheck %s
+
+; CHECK: require<MachineModuleAnalysis>
+; CHECK-NEXT: require<profile-summary>
+; CHECK-NEXT: require<collector-metadata>
+; CHECK-NEXT: require<runtime-libcall-info>
+; CHECK-NEXT: require<libcall-lowering-info>
+; CHECK-NEXT: function
+; CHECK-NEXT: objc-arc-contract
+; CHECK-NEXT: pre-isel-intrinsic-lowering
+; CHECK-NEXT: function
+; CHECK-NEXT: expand-ir-insts<O3>
+; CHECK-NEXT: atomic-expand
+; CHECK-NEXT: loop-data-prefetch
+; CHECK-NEXT: interleaved-access
+; CHECK-NEXT: riscv-codegenprepare
+; CHECK-NEXT: verify
+; CHECK-NEXT: loop
+; CHECK-NEXT: canon-freeze
+; CHECK-NEXT: loop-reduce
+; CHECK-NEXT: gc-lowering
+; CHECK-NEXT: shadow-stack-gc-lowering
+; CHECK-NEXT: function
+; CHECK-NEXT: unreachableblockelim
+; CHECK-NEXT: consthoist
+; CHECK-NEXT: replace-with-veclib
+; CHECK-NEXT: partially-inline-libcalls
+; CHECK-NEXT: ee-instrument<post-inline>
+; CHECK-NEXT: scalarize-masked-mem-intrin
+; CHECK-NEXT: expand-reductions
+; CHECK-NEXT: typepromotion
+; CHECK-NEXT: codegenprepare
+; CHECK-NEXT: dwarf-eh-prepare
+; CHECK-NEXT: inline-asm-prepare
+; CHECK-NEXT: safe-stack
+; CHECK-NEXT: stack-protector
+; CHECK-NEXT: verify
+; CHECK-NEXT: riscv-asm-printer-begin
+; CHECK-NEXT: function
+; CHECK-NEXT: machine-function
+; CHECK-NEXT: riscv-isel
+; CHECK-NEXT: finalize-isel
+; CHECK-NEXT: early-machinelicm
+; CHECK-NEXT: early-tailduplication
+; CHECK-NEXT: opt-phis
+; CHECK-NEXT: stack-coloring
+; CHECK-NEXT: localstackalloc
+; CHECK-NEXT: dead-mi-elimination
+; CHECK-NEXT: early-machinelicm
+; CHECK-NEXT: machine-cse
+; CHECK-NEXT: machine-sink
+; CHECK-NEXT: peephole-opt
+; CHECK-NEXT: dead-mi-elimination
+; CHECK-NEXT: detect-dead-lanes
+; CHECK-NEXT: init-undef
+; CHECK-NEXT: process-imp-defs
+; CHECK-NEXT: unreachable-mbb-elimination
+; CHECK-NEXT: require<live-vars>
+; CHECK-NEXT: require<machine-loops>
+; CHECK-NEXT: phi-node-elimination
+; CHECK-NEXT: two-address-instruction
+; CHECK-NEXT: register-coalescer
+; CHECK-NEXT: rename-independent-subregs
+; CHECK-NEXT: machine-scheduler
+; CHECK-NEXT: greedy<all>
+; CHECK-NEXT: virt-reg-rewriter
+; CHECK-NEXT: stack-slot-coloring
+; CHECK-NEXT: machine-cp
+; CHECK-NEXT: machinelicm
+; CHECK-NEXT: remove-redundant-debug-values
+; CHECK-NEXT: fixup-statepoint-caller-saved
+; CHECK-NEXT: postra-machine-sink
+; CHECK-NEXT: shrink-wrap
+; CHECK-NEXT: prolog-epilog
+; CHECK-NEXT: machine-latecleanup
+; CHECK-NEXT: branch-folder
+; CHECK-NEXT: tailduplication
+; CHECK-NEXT: machine-cp
+; CHECK-NEXT: post-ra-pseudos
+; CHECK-NEXT: kcfi
+; CHECK-NEXT: post-RA-sched
+; CHECK-NEXT: block-placement
+; CHECK-NEXT: fentry-insert
+; CHECK-NEXT: xray-instrumentation
+; CHECK-NEXT: patchable-function
+; CHECK-NEXT: machine-cp
+; CHECK-NEXT: branch-relaxation
+; CHECK-NEXT: FuncletLayoutPass
+; CHECK-NEXT: remove-loads-into-fake-uses
+; CHECK-NEXT: StackMapLivenessPass
+; CHECK-NEXT: live-debug-values<emit-debug-entry-values>
+; CHECK-NEXT: machine-sanmd
+; CHECK-NEXT: MachineOutlinerPass
+; CHECK-NEXT: function
+; CHECK-NEXT: machine-function
+; CHECK-NEXT: stack-frame-layout
+; CHECK-NEXT: unpack-mi-bundles
+; CHECK-NEXT: verify
+; CHECK-NEXT: riscv-asm-printer
+; CHECK-NEXT: free-machine-function
+; CHECK-NEXT: riscv-asm-printer-end
+
+define void @f() {
+ ret void
+}
>From aecd6aa6206e396f2e96f0c65bb6ee03d792843d Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Thu, 30 Jul 2026 13:22:31 -0700
Subject: [PATCH 2/4] clang-format
---
llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp b/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
index e7951918bf632..4a8e865f1a977 100644
--- a/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
@@ -27,8 +27,8 @@
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Target/CGPassBuilderOption.h"
-#include "llvm/Transforms/Vectorize/LoopIdiomVectorize.h"
#include "llvm/Transforms/Scalar/LoopDataPrefetch.h"
+#include "llvm/Transforms/Vectorize/LoopIdiomVectorize.h"
using namespace llvm;
>From c9d404f4a8dcdf781253c5c3eb4d63c80d3f6b77 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Thu, 30 Jul 2026 14:33:15 -0700
Subject: [PATCH 3/4] review feedback on RISC-V CGPB
---
llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp b/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
index 4a8e865f1a977..2ca1d1f6b483f 100644
--- a/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
/// \file
/// This file contains the RISC-V CodeGen pipeline builder.
-/// TODO: Port the remaining RISC-V CodeGen passes to the new pass manager.
//===----------------------------------------------------------------------===//
#include "RISCV.h"
@@ -53,9 +52,9 @@ class RISCVCodeGenPassBuilder
void addIRPasses(PassManagerWrapper &PMW) const;
void addCodeGenPrepare(PassManagerWrapper &PMW) const;
Error addInstSelector(PassManagerWrapper &PMW) const;
+ void addMachineSSAOptimization(PassManagerWrapper &PMW) const;
void addPreRegAlloc(PassManagerWrapper &PMW) const;
void addPostRegAlloc(PassManagerWrapper &PMW) const;
- void addMachineSSAOptimization(PassManagerWrapper &PMW) const;
void addPreSched2(PassManagerWrapper &PMW) const;
void addPreEmitPass(PassManagerWrapper &PMW) const;
void addPreEmitPass2(PassManagerWrapper &PMW) const;
>From 05b9c12f390d4c9a16bd0bde57ca0eb655aa9fd9 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Thu, 30 Jul 2026 14:47:38 -0700
Subject: [PATCH 4/4] Move function definition too
---
.../Target/RISCV/RISCVCodeGenPassBuilder.cpp | 46 ++++++++++---------
1 file changed, 24 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp b/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
index 2ca1d1f6b483f..7b0afc4561cec 100644
--- a/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
@@ -94,28 +94,6 @@ Error RISCVCodeGenPassBuilder::addInstSelector(PassManagerWrapper &PMW) const {
return Error::success();
}
-void RISCVCodeGenPassBuilder::addPreRegAlloc(PassManagerWrapper &PMW) const {
- // TODO: RISCVPreRAExpandPseudoPass
- if (getOptLevel() != CodeGenOptLevel::None) {
- // TODO: RISCVMergeBaseOffsetOptPass
- // TODO: RISCVPreAllocZilsdOptPass
- }
-
- // TODO: RISCVInsertReadWriteCSRPass
- // TODO: RISCVInsertWriteVXRMPass
- // TODO: RISCVLandingPadSetupPass
-
- // TODO: MachinePipelinerPass (no new pass manager port exists yet)
-
- // TODO: RISCVVMV0EliminationPass
-}
-
-void RISCVCodeGenPassBuilder::addPostRegAlloc(PassManagerWrapper &PMW) const {
- if (getOptLevel() != CodeGenOptLevel::None) {
- // TODO: RISCVRedundantCopyEliminationPass
- }
-}
-
void RISCVCodeGenPassBuilder::addMachineSSAOptimization(
PassManagerWrapper &PMW) const {
// It's beneficial to reduce the VL to enable more
@@ -141,6 +119,30 @@ void RISCVCodeGenPassBuilder::addMachineSSAOptimization(
}
}
+void RISCVCodeGenPassBuilder::addPreRegAlloc(PassManagerWrapper &PMW) const {
+ // TODO: RISCVPreRAExpandPseudoPass
+ if (getOptLevel() != CodeGenOptLevel::None) {
+ // TODO: RISCVMergeBaseOffsetOptPass
+ // TODO: RISCVPreAllocZilsdOptPass
+ }
+
+ // TODO: RISCVInsertReadWriteCSRPass
+ // TODO: RISCVInsertWriteVXRMPass
+ // TODO: RISCVLandingPadSetupPass
+
+ // TODO: MachinePipelinerPass (no new pass manager port exists yet)
+
+ // TODO: RISCVVMV0EliminationPass
+}
+
+void RISCVCodeGenPassBuilder::addPostRegAlloc(PassManagerWrapper &PMW) const {
+ if (getOptLevel() != CodeGenOptLevel::None) {
+ // TODO: RISCVRedundantCopyEliminationPass
+ }
+}
+
+
+
void RISCVCodeGenPassBuilder::addPreSched2(PassManagerWrapper &PMW) const {
// TODO: RISCVPostRAExpandPseudoPass
More information about the llvm-commits
mailing list