[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