[llvm] [RISCV] Port VL Optimizer to NewPM (PR #215670)

Sam Elliott via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 11 19:56:57 PDT 2026


https://github.com/lenary updated https://github.com/llvm/llvm-project/pull/215670

>From 9b25bfbdfa748a0ce35c5ab34a3d572ee3415593 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Fri, 7 Aug 2026 16:30:42 -0700
Subject: [PATCH 1/2] [RISCV] Port VL Optimizer to NewPM

Assisted-by: AI
---
 llvm/lib/Target/RISCV/RISCV.h                 |  4 +-
 .../Target/RISCV/RISCVCodeGenPassBuilder.cpp  |  3 +-
 llvm/lib/Target/RISCV/RISCVPassRegistry.def   |  1 +
 llvm/lib/Target/RISCV/RISCVTargetMachine.cpp  |  3 +-
 llvm/lib/Target/RISCV/RISCVVLOptimizer.cpp    | 87 ++++++++++++-------
 llvm/lib/Target/RISCV/RISCVVLOptimizer.h      | 36 ++++++++
 llvm/test/CodeGen/RISCV/O1-newpm-pipeline.ll  |  1 +
 llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll  |  1 +
 llvm/test/CodeGen/RISCV/rvv/vl-opt.mir        |  1 +
 9 files changed, 101 insertions(+), 36 deletions(-)
 create mode 100644 llvm/lib/Target/RISCV/RISCVVLOptimizer.h

diff --git a/llvm/lib/Target/RISCV/RISCV.h b/llvm/lib/Target/RISCV/RISCV.h
index 18887f3a9d120..990531c7e6163 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/MachineFunctionAnalysisManager.h"
 #include "llvm/CodeGen/SelectionDAGISel.h"
 #include "llvm/Target/TargetMachine.h"
 
@@ -139,9 +140,6 @@ void initializeRISCVPreLegalizerCombinerPass(PassRegistry &);
 ModulePass *createRISCVPromoteConstantPass();
 void initializeRISCVPromoteConstantPass(PassRegistry &);
 
-FunctionPass *createRISCVVLOptimizerPass();
-void initializeRISCVVLOptimizerPass(PassRegistry &);
-
 FunctionPass *createRISCVVMV0EliminationPass();
 void initializeRISCVVMV0EliminationPass(PassRegistry &);
 
diff --git a/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp b/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
index 652d545bfee60..4398814b8826b 100644
--- a/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/RISCV/RISCVCodeGenPassBuilder.cpp
@@ -13,6 +13,7 @@
 #include "RISCVAsmPrinter.h"
 #include "RISCVGatherScatterLowering.h"
 #include "RISCVTargetMachine.h"
+#include "RISCVVLOptimizer.h"
 #include "llvm/CodeGen/AtomicExpand.h"
 #include "llvm/CodeGen/BranchRelaxation.h"
 #include "llvm/CodeGen/InterleavedAccess.h"
@@ -107,7 +108,7 @@ void RISCVCodeGenPassBuilder::addMachineSSAOptimization(
     // vsetvli toggles, and still requires the MachineLoopInfo analysis to be
     // run.
     addMachineFunctionPass(EarlyMachineLICMPass(), PMW);
-    // TODO: RISCVVLOptimizerPass
+    addMachineFunctionPass(RISCVVLOptimizerPass(), PMW);
   }
 
   // TODO: RISCVVectorPeepholePass
diff --git a/llvm/lib/Target/RISCV/RISCVPassRegistry.def b/llvm/lib/Target/RISCV/RISCVPassRegistry.def
index cb8e31724f82b..e64d84832aada 100644
--- a/llvm/lib/Target/RISCV/RISCVPassRegistry.def
+++ b/llvm/lib/Target/RISCV/RISCVPassRegistry.def
@@ -26,4 +26,5 @@ FUNCTION_PASS("riscv-zacas-abi-fix", RISCVZacasABIFixPass(this))
 #define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS)
 #endif
 MACHINE_FUNCTION_PASS("riscv-isel", RISCVISelDAGToDAGPass(*this, getOptLevel()))
+MACHINE_FUNCTION_PASS("riscv-vl-optimizer", RISCVVLOptimizerPass())
 #undef MACHINE_FUNCTION_PASS
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index 9e12dbbe752a1..101917c7435ad 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -18,6 +18,7 @@
 #include "RISCVMachineScheduler.h"
 #include "RISCVTargetObjectFile.h"
 #include "RISCVTargetTransformInfo.h"
+#include "RISCVVLOptimizer.h"
 #include "TargetInfo/RISCVTargetInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/CodeGen/GlobalISel/CSEInfo.h"
@@ -138,7 +139,7 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
   initializeRISCVPreRAExpandPseudoPass(*PR);
   initializeRISCVExpandPseudoPass(*PR);
   initializeRISCVVectorPeepholePass(*PR);
-  initializeRISCVVLOptimizerPass(*PR);
+  initializeRISCVVLOptimizerLegacyPass(*PR);
   initializeRISCVVMV0EliminationPass(*PR);
   initializeRISCVInsertVSETVLIPass(*PR);
   initializeRISCVInsertReadWriteCSRPass(*PR);
diff --git a/llvm/lib/Target/RISCV/RISCVVLOptimizer.cpp b/llvm/lib/Target/RISCV/RISCVVLOptimizer.cpp
index f4a70ba4e52fb..418938c3148f3 100644
--- a/llvm/lib/Target/RISCV/RISCVVLOptimizer.cpp
+++ b/llvm/lib/Target/RISCV/RISCVVLOptimizer.cpp
@@ -26,7 +26,7 @@
 //
 //===---------------------------------------------------------------------===//
 
-#include "RISCV.h"
+#include "RISCVVLOptimizer.h"
 #include "RISCVSubtarget.h"
 #include "llvm/ADT/PostOrderIterator.h"
 #include "llvm/ADT/SetVector.h"
@@ -63,26 +63,15 @@ struct DemandedVL {
   }
 };
 
-class RISCVVLOptimizer : public MachineFunctionPass {
+class RISCVVLOptimizerImpl {
   MachineRegisterInfo *MRI;
   const MachineDominatorTree *MDT;
   const TargetInstrInfo *TII;
 
 public:
-  static char ID;
-
-  RISCVVLOptimizer() : MachineFunctionPass(ID) {}
+  RISCVVLOptimizerImpl(const MachineDominatorTree *MDT) : MDT(MDT) {}
 
-  bool runOnMachineFunction(MachineFunction &MF) override;
-
-  void getAnalysisUsage(AnalysisUsage &AU) const override {
-    AU.setPreservesCFG();
-    AU.addRequired<MachineDominatorTreeWrapperPass>();
-    AU.addPreserved<MachineRegisterClassInfoWrapperPass>();
-    MachineFunctionPass::getAnalysisUsage(AU);
-  }
-
-  StringRef getPassName() const override { return PASS_NAME; }
+  bool run(MachineFunction &MF);
 
 private:
   DemandedVL getMinimumVLForUser(const MachineOperand &UserOp) const;
@@ -107,6 +96,24 @@ class RISCVVLOptimizer : public MachineFunctionPass {
   }
 };
 
+class RISCVVLOptimizerLegacy : public MachineFunctionPass {
+public:
+  static char ID;
+
+  RISCVVLOptimizerLegacy() : MachineFunctionPass(ID) {}
+
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesCFG();
+    AU.addRequired<MachineDominatorTreeWrapperPass>();
+    AU.addPreserved<MachineRegisterClassInfoWrapperPass>();
+    MachineFunctionPass::getAnalysisUsage(AU);
+  }
+
+  StringRef getPassName() const override { return PASS_NAME; }
+};
+
 /// Represents the EMUL and EEW of a MachineOperand.
 struct OperandInfo {
   // Represent as 1,2,4,8, ... and fractional indicator. This is because
@@ -151,13 +158,14 @@ struct OperandInfo {
 
 } // end anonymous namespace
 
-char RISCVVLOptimizer::ID = 0;
-INITIALIZE_PASS_BEGIN(RISCVVLOptimizer, DEBUG_TYPE, PASS_NAME, false, false)
+char RISCVVLOptimizerLegacy::ID = 0;
+INITIALIZE_PASS_BEGIN(RISCVVLOptimizerLegacy, DEBUG_TYPE, PASS_NAME, false,
+                      false)
 INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
-INITIALIZE_PASS_END(RISCVVLOptimizer, DEBUG_TYPE, PASS_NAME, false, false)
+INITIALIZE_PASS_END(RISCVVLOptimizerLegacy, DEBUG_TYPE, PASS_NAME, false, false)
 
 FunctionPass *llvm::createRISCVVLOptimizerPass() {
-  return new RISCVVLOptimizer();
+  return new RISCVVLOptimizerLegacy();
 }
 
 [[maybe_unused]]
@@ -901,7 +909,7 @@ static std::optional<OperandInfo> getOperandInfo(const MachineOperand &MO) {
 static bool isTupleInsertInstr(const MachineInstr &MI);
 
 /// Return true if we can reason about demanded VLs elementwise for \p MI.
-bool RISCVVLOptimizer::isSupportedInstr(const MachineInstr &MI) const {
+bool RISCVVLOptimizerImpl::isSupportedInstr(const MachineInstr &MI) const {
   if (MI.isPHI() || MI.isFullCopy() || isTupleInsertInstr(MI))
     return true;
 
@@ -963,7 +971,7 @@ static bool isVectorOpUsedAsScalarOp(const MachineOperand &MO) {
   }
 }
 
-bool RISCVVLOptimizer::isCandidate(const MachineInstr &MI) const {
+bool RISCVVLOptimizerImpl::isCandidate(const MachineInstr &MI) const {
   const MCInstrDesc &Desc = MI.getDesc();
   if (!RISCVII::hasVLOp(Desc.TSFlags) || !RISCVII::hasSEWOp(Desc.TSFlags))
     return false;
@@ -1045,7 +1053,7 @@ getMinimumVLForVSLIDEDOWN_VX(const MachineOperand &UserOp,
 }
 
 DemandedVL
-RISCVVLOptimizer::getMinimumVLForUser(const MachineOperand &UserOp) const {
+RISCVVLOptimizerImpl::getMinimumVLForUser(const MachineOperand &UserOp) const {
   const MachineInstr &UserMI = *UserOp.getParent();
   const MCInstrDesc &Desc = UserMI.getDesc();
 
@@ -1148,7 +1156,7 @@ static bool isSegmentedStoreInstr(const MachineInstr &MI) {
   }
 }
 
-bool RISCVVLOptimizer::checkUsers(const MachineInstr &MI) const {
+bool RISCVVLOptimizerImpl::checkUsers(const MachineInstr &MI) const {
   if (MI.isPHI() || MI.isFullCopy() || isTupleInsertInstr(MI))
     return true;
 
@@ -1223,8 +1231,8 @@ bool RISCVVLOptimizer::checkUsers(const MachineInstr &MI) const {
   return true;
 }
 
-bool RISCVVLOptimizer::tryReduceVL(MachineInstr &MI,
-                                   MachineOperand CommonVL) const {
+bool RISCVVLOptimizerImpl::tryReduceVL(MachineInstr &MI,
+                                       MachineOperand CommonVL) const {
   LLVM_DEBUG(dbgs() << "Trying to reduce VL for " << MI);
 
   unsigned VLOpNum = RISCVII::getVLOpNum(MI.getDesc());
@@ -1294,7 +1302,7 @@ static bool isPhysical(const MachineOperand &MO) {
 }
 
 /// Look through \p MI's operands and propagate what it demands to its uses.
-void RISCVVLOptimizer::transfer(const MachineInstr &MI) {
+void RISCVVLOptimizerImpl::transfer(const MachineInstr &MI) {
   if (!isSupportedInstr(MI) || !checkUsers(MI) || any_of(MI.defs(), isPhysical))
     DemandedVLs[&MI] = DemandedVL::vlmax();
 
@@ -1307,12 +1315,8 @@ void RISCVVLOptimizer::transfer(const MachineInstr &MI) {
   }
 }
 
-bool RISCVVLOptimizer::runOnMachineFunction(MachineFunction &MF) {
-  if (skipFunction(MF.getFunction()))
-    return false;
-
+bool RISCVVLOptimizerImpl::run(MachineFunction &MF) {
   MRI = &MF.getRegInfo();
-  MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
 
   const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();
   if (!ST.hasVInstructions())
@@ -1352,3 +1356,24 @@ bool RISCVVLOptimizer::runOnMachineFunction(MachineFunction &MF) {
   DemandedVLs.clear();
   return MadeChange;
 }
+
+bool RISCVVLOptimizerLegacy::runOnMachineFunction(MachineFunction &MF) {
+  if (skipFunction(MF.getFunction()))
+    return false;
+
+  auto *MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
+  return RISCVVLOptimizerImpl(MDT).run(MF);
+}
+
+PreservedAnalyses
+RISCVVLOptimizerPass::run(MachineFunction &MF,
+                          MachineFunctionAnalysisManager &MFAM) {
+  auto *MDT = &MFAM.getResult<MachineDominatorTreeAnalysis>(MF);
+  bool Changed = RISCVVLOptimizerImpl(MDT).run(MF);
+  if (!Changed)
+    return PreservedAnalyses::all();
+
+  PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
+  PA.preserveSet<CFGAnalyses>();
+  return PA;
+}
diff --git a/llvm/lib/Target/RISCV/RISCVVLOptimizer.h b/llvm/lib/Target/RISCV/RISCVVLOptimizer.h
new file mode 100644
index 0000000000000..941ad09e8cedb
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVVLOptimizer.h
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 declares the RISC-V VL optimizer passes.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_RISCV_RISCVVLOPTIMIZER_H
+#define LLVM_LIB_TARGET_RISCV_RISCVVLOPTIMIZER_H
+
+#include "llvm/CodeGen/MachinePassManager.h"
+
+namespace llvm {
+
+class FunctionPass;
+class PassRegistry;
+
+class RISCVVLOptimizerPass
+    : public OptionalPassInfoMixin<RISCVVLOptimizerPass> {
+public:
+  PreservedAnalyses run(MachineFunction &MF,
+                        MachineFunctionAnalysisManager &MFAM);
+};
+
+FunctionPass *createRISCVVLOptimizerPass();
+void initializeRISCVVLOptimizerLegacyPass(PassRegistry &);
+
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_RISCV_RISCVVLOPTIMIZER_H
diff --git a/llvm/test/CodeGen/RISCV/O1-newpm-pipeline.ll b/llvm/test/CodeGen/RISCV/O1-newpm-pipeline.ll
index 57fc4ce5bd9c5..28778276eea09 100644
--- a/llvm/test/CodeGen/RISCV/O1-newpm-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O1-newpm-pipeline.ll
@@ -46,6 +46,7 @@
 ; CHECK-NEXT:     riscv-isel
 ; CHECK-NEXT:     finalize-isel
 ; CHECK-NEXT:     early-machinelicm
+; CHECK-NEXT:     riscv-vl-optimizer
 ; CHECK-NEXT:     early-tailduplication
 ; CHECK-NEXT:     opt-phis
 ; CHECK-NEXT:     stack-coloring
diff --git a/llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll
index 6f6edc02ea7bd..7af9a28c0aa35 100644
--- a/llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll
@@ -46,6 +46,7 @@
 ; CHECK-NEXT:     riscv-isel
 ; CHECK-NEXT:     finalize-isel
 ; CHECK-NEXT:     early-machinelicm
+; CHECK-NEXT:     riscv-vl-optimizer
 ; CHECK-NEXT:     early-tailduplication
 ; CHECK-NEXT:     opt-phis
 ; CHECK-NEXT:     stack-coloring
diff --git a/llvm/test/CodeGen/RISCV/rvv/vl-opt.mir b/llvm/test/CodeGen/RISCV/rvv/vl-opt.mir
index d2b6ba33e5982..f932c78000753 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vl-opt.mir
+++ b/llvm/test/CodeGen/RISCV/rvv/vl-opt.mir
@@ -1,5 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
 # RUN: llc %s -o - -mtriple=riscv64 -mattr=+v,+zvfbfmin -run-pass=riscv-vl-optimizer -verify-machineinstrs | FileCheck %s
+# RUN: llc %s -o - -mtriple=riscv64 -mattr=+v,+zvfbfmin -passes=riscv-vl-optimizer -verify-machineinstrs | FileCheck %s
 
 ---
 name: vnsrl_wv_user

>From f922643543008758091ea3624ab7e6cac8721d79 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Tue, 11 Aug 2026 15:45:41 -0700
Subject: [PATCH 2/2] Remove useless header

---
 llvm/lib/Target/RISCV/RISCV.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCV.h b/llvm/lib/Target/RISCV/RISCV.h
index 990531c7e6163..f845e712981fd 100644
--- a/llvm/lib/Target/RISCV/RISCV.h
+++ b/llvm/lib/Target/RISCV/RISCV.h
@@ -15,7 +15,6 @@
 #define LLVM_LIB_TARGET_RISCV_RISCV_H
 
 #include "MCTargetDesc/RISCVBaseInfo.h"
-#include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
 #include "llvm/CodeGen/SelectionDAGISel.h"
 #include "llvm/Target/TargetMachine.h"
 



More information about the llvm-commits mailing list