[llvm] [ARM] Add basic NPM support for LoadStoreOptimizer (PR #184139)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 2 06:47:35 PST 2026
https://github.com/davemgreen created https://github.com/llvm/llvm-project/pull/184139
This is similar to #184090 for ARM, porting the LoadStoreOptimizer to the new pass manager. The time there are both a pre-ra and post-ra variant that are ported.
>From 5bfcaa07fc125a29edf8fcce0b379c107c6052d2 Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Mon, 2 Mar 2026 14:45:54 +0000
Subject: [PATCH] [ARM] Add basic NPM support for LoadStoreOptimizer
This is similar to #184090 for ARM, porting the LoadStoreOptimizer to the new
pass manager. The time there are both a pre-ra and post-ra variant that are
ported.
---
llvm/lib/Target/ARM/ARM.h | 20 ++-
llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 149 ++++++++++++------
llvm/lib/Target/ARM/ARMTargetMachine.cpp | 18 ++-
llvm/lib/Target/ARM/ARMTargetMachine.h | 2 +
llvm/test/CodeGen/ARM/ARMLoadStoreDBG.mir | 1 +
llvm/test/CodeGen/ARM/prera-ldst-aliasing.mir | 1 +
6 files changed, 135 insertions(+), 56 deletions(-)
diff --git a/llvm/lib/Target/ARM/ARM.h b/llvm/lib/Target/ARM/ARM.h
index 3847f4e966afe..9681329f8b29b 100644
--- a/llvm/lib/Target/ARM/ARM.h
+++ b/llvm/lib/Target/ARM/ARM.h
@@ -14,6 +14,7 @@
#ifndef LLVM_LIB_TARGET_ARM_ARM_H
#define LLVM_LIB_TARGET_ARM_ARM_H
+#include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/CodeGen.h"
#include <functional>
@@ -38,7 +39,7 @@ Pass *createARMParallelDSPPass();
FunctionPass *createARMISelDag(ARMBaseTargetMachine &TM,
CodeGenOptLevel OptLevel);
FunctionPass *createA15SDOptimizerPass();
-FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false);
+FunctionPass *createARMLoadStoreOptLegacyPass(bool PreAlloc = false);
FunctionPass *createARMExpandPseudoPass();
FunctionPass *createARMBranchTargetsPass();
FunctionPass *createARMConstantIslandPass();
@@ -68,10 +69,10 @@ void initializeARMConstantIslandsPass(PassRegistry &);
void initializeARMDAGToDAGISelLegacyPass(PassRegistry &);
void initializeARMExpandPseudoPass(PassRegistry &);
void initializeARMFixCortexA57AES1742098Pass(PassRegistry &);
-void initializeARMLoadStoreOptPass(PassRegistry &);
+void initializeARMLoadStoreOptLegacyPass(PassRegistry &);
void initializeARMLowOverheadLoopsPass(PassRegistry &);
void initializeARMParallelDSPPass(PassRegistry &);
-void initializeARMPreAllocLoadStoreOptPass(PassRegistry &);
+void initializeARMPreAllocLoadStoreOptLegacyPass(PassRegistry &);
void initializeARMSLSHardeningPass(PassRegistry &);
void initializeMVEGatherScatterLoweringPass(PassRegistry &);
void initializeMVELaneInterleavingPass(PassRegistry &);
@@ -81,6 +82,19 @@ void initializeMVEVPTBlockPass(PassRegistry &);
void initializeThumb2ITBlockPass(PassRegistry &);
void initializeThumb2SizeReducePass(PassRegistry &);
+class ARMPreAllocLoadStoreOptPass
+ : public PassInfoMixin<ARMPreAllocLoadStoreOptPass> {
+public:
+ PreservedAnalyses run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM);
+};
+
+class ARMLoadStoreOptPass : public PassInfoMixin<ARMLoadStoreOptPass> {
+public:
+ PreservedAnalyses run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM);
+};
+
} // end namespace llvm
#endif // LLVM_LIB_TARGET_ARM_ARM_H
diff --git a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
index de56822565441..5999d1faca461 100644
--- a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
+++ b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
@@ -98,9 +98,7 @@ namespace {
/// Post- register allocation pass the combine load / store instructions to
/// form ldm / stm instructions.
-struct ARMLoadStoreOpt : public MachineFunctionPass {
- static char ID;
-
+struct ARMLoadStoreOpt {
const MachineFunction *MF;
const TargetInstrInfo *TII;
const TargetRegisterInfo *TRI;
@@ -114,15 +112,7 @@ struct ARMLoadStoreOpt : public MachineFunctionPass {
bool RegClassInfoValid;
bool isThumb1, isThumb2;
- ARMLoadStoreOpt() : MachineFunctionPass(ID) {}
-
- bool runOnMachineFunction(MachineFunction &Fn) override;
-
- MachineFunctionProperties getRequiredProperties() const override {
- return MachineFunctionProperties().setNoVRegs();
- }
-
- StringRef getPassName() const override { return ARM_LOAD_STORE_OPT_NAME; }
+ bool runOnMachineFunction(MachineFunction &Fn);
private:
/// A set of load/store MachineInstrs with same base register sorted by
@@ -196,12 +186,26 @@ struct ARMLoadStoreOpt : public MachineFunctionPass {
bool CombineMovBx(MachineBasicBlock &MBB);
};
-} // end anonymous namespace
+struct ARMLoadStoreOptLegacy : public MachineFunctionPass {
+ static char ID;
-char ARMLoadStoreOpt::ID = 0;
+ ARMLoadStoreOptLegacy() : MachineFunctionPass(ID) {}
-INITIALIZE_PASS(ARMLoadStoreOpt, "arm-ldst-opt", ARM_LOAD_STORE_OPT_NAME, false,
- false)
+ bool runOnMachineFunction(MachineFunction &Fn) override;
+
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().setNoVRegs();
+ }
+
+ StringRef getPassName() const override { return ARM_LOAD_STORE_OPT_NAME; }
+};
+
+char ARMLoadStoreOptLegacy::ID = 0;
+
+} // end anonymous namespace
+
+INITIALIZE_PASS(ARMLoadStoreOptLegacy, "arm-ldst-opt", ARM_LOAD_STORE_OPT_NAME,
+ false, false)
static bool definesCPSR(const MachineInstr &MI) {
for (const auto &MO : MI.operands()) {
@@ -2096,9 +2100,6 @@ bool ARMLoadStoreOpt::CombineMovBx(MachineBasicBlock &MBB) {
}
bool ARMLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
- if (skipFunction(Fn.getFunction()))
- return false;
-
MF = &Fn;
STI = &Fn.getSubtarget<ARMSubtarget>();
TL = STI->getTargetLowering();
@@ -2131,6 +2132,13 @@ bool ARMLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
return Modified;
}
+bool ARMLoadStoreOptLegacy::runOnMachineFunction(MachineFunction &MF) {
+ if (skipFunction(MF.getFunction()))
+ return false;
+ ARMLoadStoreOpt Impl;
+ return Impl.runOnMachineFunction(MF);
+}
+
#define ARM_PREALLOC_LOAD_STORE_OPT_NAME \
"ARM pre- register allocation load / store optimization pass"
@@ -2138,9 +2146,7 @@ namespace {
/// Pre- register allocation pass that move load / stores from consecutive
/// locations close to make it more likely they will be combined later.
-struct ARMPreAllocLoadStoreOpt : public MachineFunctionPass {
- static char ID;
-
+struct ARMPreAllocLoadStoreOpt {
AliasAnalysis *AA;
const DataLayout *TD;
const TargetInstrInfo *TII;
@@ -2150,20 +2156,8 @@ struct ARMPreAllocLoadStoreOpt : public MachineFunctionPass {
MachineDominatorTree *DT;
MachineFunction *MF;
- ARMPreAllocLoadStoreOpt() : MachineFunctionPass(ID) {}
-
- bool runOnMachineFunction(MachineFunction &Fn) override;
-
- StringRef getPassName() const override {
- return ARM_PREALLOC_LOAD_STORE_OPT_NAME;
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.addRequired<AAResultsWrapperPass>();
- AU.addRequired<MachineDominatorTreeWrapperPass>();
- AU.addPreserved<MachineDominatorTreeWrapperPass>();
- MachineFunctionPass::getAnalysisUsage(AU);
- }
+ bool runOnMachineFunction(MachineFunction &Fn, AliasAnalysis *AA,
+ MachineDominatorTree *DT);
private:
bool CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, DebugLoc &dl,
@@ -2179,14 +2173,33 @@ struct ARMPreAllocLoadStoreOpt : public MachineFunctionPass {
bool DistributeIncrements(Register Base);
};
-} // end anonymous namespace
+struct ARMPreAllocLoadStoreOptLegacy : public MachineFunctionPass {
+ static char ID;
+
+ ARMPreAllocLoadStoreOptLegacy() : MachineFunctionPass(ID) {}
+
+ bool runOnMachineFunction(MachineFunction &Fn) override;
+
+ StringRef getPassName() const override {
+ return ARM_PREALLOC_LOAD_STORE_OPT_NAME;
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<AAResultsWrapperPass>();
+ AU.addRequired<MachineDominatorTreeWrapperPass>();
+ AU.addPreserved<MachineDominatorTreeWrapperPass>();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+};
-char ARMPreAllocLoadStoreOpt::ID = 0;
+char ARMPreAllocLoadStoreOptLegacy::ID = 0;
+
+} // end anonymous namespace
-INITIALIZE_PASS_BEGIN(ARMPreAllocLoadStoreOpt, "arm-prera-ldst-opt",
+INITIALIZE_PASS_BEGIN(ARMPreAllocLoadStoreOptLegacy, "arm-prera-ldst-opt",
ARM_PREALLOC_LOAD_STORE_OPT_NAME, false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
-INITIALIZE_PASS_END(ARMPreAllocLoadStoreOpt, "arm-prera-ldst-opt",
+INITIALIZE_PASS_END(ARMPreAllocLoadStoreOptLegacy, "arm-prera-ldst-opt",
ARM_PREALLOC_LOAD_STORE_OPT_NAME, false, false)
// Limit the number of instructions to be rescheduled.
@@ -2194,18 +2207,20 @@ INITIALIZE_PASS_END(ARMPreAllocLoadStoreOpt, "arm-prera-ldst-opt",
static cl::opt<unsigned> InstReorderLimit("arm-prera-ldst-opt-reorder-limit",
cl::init(8), cl::Hidden);
-bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
- if (AssumeMisalignedLoadStores || skipFunction(Fn.getFunction()))
+bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn,
+ AliasAnalysis *AAIn,
+ MachineDominatorTree *DTIn) {
+ if (AssumeMisalignedLoadStores)
return false;
+ AA = AAIn;
+ DT = DTIn;
TD = &Fn.getDataLayout();
STI = &Fn.getSubtarget<ARMSubtarget>();
TII = STI->getInstrInfo();
TRI = STI->getRegisterInfo();
MRI = &Fn.getRegInfo();
- DT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
MF = &Fn;
- AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
bool Modified = DistributeIncrements();
for (MachineBasicBlock &MFI : Fn)
@@ -2214,6 +2229,17 @@ bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
return Modified;
}
+bool ARMPreAllocLoadStoreOptLegacy::runOnMachineFunction(MachineFunction &Fn) {
+ if (skipFunction(Fn.getFunction()))
+ return false;
+
+ ARMPreAllocLoadStoreOpt Impl;
+ AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
+ MachineDominatorTree *DT =
+ &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
+ return Impl.runOnMachineFunction(Fn, AA, DT);
+}
+
static bool IsSafeAndProfitableToMove(bool isLd, unsigned Base,
MachineBasicBlock::iterator I,
MachineBasicBlock::iterator E,
@@ -3299,8 +3325,37 @@ bool ARMPreAllocLoadStoreOpt::DistributeIncrements() {
}
/// Returns an instance of the load / store optimization pass.
-FunctionPass *llvm::createARMLoadStoreOptimizationPass(bool PreAlloc) {
+FunctionPass *llvm::createARMLoadStoreOptLegacyPass(bool PreAlloc) {
if (PreAlloc)
- return new ARMPreAllocLoadStoreOpt();
- return new ARMLoadStoreOpt();
+ return new ARMPreAllocLoadStoreOptLegacy();
+ return new ARMLoadStoreOptLegacy();
+}
+
+PreservedAnalyses
+ARMLoadStoreOptPass::run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM) {
+ ARMLoadStoreOpt Impl;
+ bool Changed = Impl.runOnMachineFunction(MF);
+ if (!Changed)
+ return PreservedAnalyses::all();
+ PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
+ PA.preserveSet<CFGAnalyses>();
+ return PA;
+}
+
+PreservedAnalyses
+ARMPreAllocLoadStoreOptPass::run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM) {
+ ARMPreAllocLoadStoreOpt Impl;
+ AliasAnalysis *AA =
+ &MFAM.getResult<FunctionAnalysisManagerMachineFunctionProxy>(MF)
+ .getManager()
+ .getResult<AAManager>(MF.getFunction());
+ MachineDominatorTree *DT = &MFAM.getResult<MachineDominatorTreeAnalysis>(MF);
+ bool Changed = Impl.runOnMachineFunction(MF, AA, DT);
+ if (!Changed)
+ return PreservedAnalyses::all();
+ PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
+ PA.preserveSet<CFGAnalyses>();
+ return PA;
}
diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
index d74d7737995a1..fc0dc636c7ecd 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
@@ -39,6 +39,7 @@
#include "llvm/IR/Function.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Pass.h"
+#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
@@ -93,8 +94,8 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMTarget() {
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeGlobalISel(Registry);
initializeARMAsmPrinterPass(Registry);
- initializeARMLoadStoreOptPass(Registry);
- initializeARMPreAllocLoadStoreOptPass(Registry);
+ initializeARMLoadStoreOptLegacyPass(Registry);
+ initializeARMPreAllocLoadStoreOptLegacyPass(Registry);
initializeARMParallelDSPPass(Registry);
initializeARMBranchTargetsPass(Registry);
initializeARMConstantIslandsPass(Registry);
@@ -334,11 +335,16 @@ char ARMExecutionDomainFix::ID;
} // end anonymous namespace
+void ARMBaseTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB){
+#define GET_PASS_REGISTRY "ARMPassRegistry.def"
+#include "llvm/Passes/TargetPassRegistry.inc"
+}
+
INITIALIZE_PASS_BEGIN(ARMExecutionDomainFix, "arm-execution-domain-fix",
- "ARM Execution Domain Fix", false, false)
+ "ARM Execution Domain Fix", false, false)
INITIALIZE_PASS_DEPENDENCY(ReachingDefInfoWrapperPass)
INITIALIZE_PASS_END(ARMExecutionDomainFix, "arm-execution-domain-fix",
- "ARM Execution Domain Fix", false, false)
+ "ARM Execution Domain Fix", false, false)
TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
return new ARMPassConfig(*this, PM);
@@ -468,7 +474,7 @@ void ARMPassConfig::addPreRegAlloc() {
addPass(createMLxExpansionPass());
if (EnableARMLoadStoreOpt)
- addPass(createARMLoadStoreOptimizationPass(/* pre-register alloc */ true));
+ addPass(createARMLoadStoreOptLegacyPass(/* pre-register alloc */ true));
if (!DisableA15SDOptimization)
addPass(createA15SDOptimizerPass());
@@ -478,7 +484,7 @@ void ARMPassConfig::addPreRegAlloc() {
void ARMPassConfig::addPreSched2() {
if (getOptLevel() != CodeGenOptLevel::None) {
if (EnableARMLoadStoreOpt)
- addPass(createARMLoadStoreOptimizationPass());
+ addPass(createARMLoadStoreOptLegacyPass());
addPass(new ARMExecutionDomainFix());
addPass(createBreakFalseDeps());
diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.h b/llvm/lib/Target/ARM/ARMTargetMachine.h
index 1f74e9fdd1dc9..215b541620acb 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.h
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.h
@@ -57,6 +57,8 @@ class ARMBaseTargetMachine : public CodeGenTargetMachineImpl {
// Pass Pipeline Configuration
TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
+ void registerPassBuilderCallbacks(PassBuilder &PB) override;
+
TargetLoweringObjectFile *getObjFileLowering() const override {
return TLOF.get();
}
diff --git a/llvm/test/CodeGen/ARM/ARMLoadStoreDBG.mir b/llvm/test/CodeGen/ARM/ARMLoadStoreDBG.mir
index a18023c297f1d..1db6e2571e80d 100644
--- a/llvm/test/CodeGen/ARM/ARMLoadStoreDBG.mir
+++ b/llvm/test/CodeGen/ARM/ARMLoadStoreDBG.mir
@@ -1,5 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple thumbv7 -verify-machineinstrs -run-pass arm-ldst-opt %s -o - | FileCheck %s
+# RUN: llc -mtriple thumbv7 -passes=arm-ldst-opt %s -o - | FileCheck %s
--- |
; ModuleID = '/Volumes/Data/llvm/test/CodeGen/ARM/sched-it-debug-nodes.ll'
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
diff --git a/llvm/test/CodeGen/ARM/prera-ldst-aliasing.mir b/llvm/test/CodeGen/ARM/prera-ldst-aliasing.mir
index cea8cf7fdb8a6..826bd7919e221 100644
--- a/llvm/test/CodeGen/ARM/prera-ldst-aliasing.mir
+++ b/llvm/test/CodeGen/ARM/prera-ldst-aliasing.mir
@@ -1,4 +1,5 @@
# RUN: llc -run-pass arm-prera-ldst-opt %s -o - | FileCheck %s
+# RUN: llc -passes=arm-prera-ldst-opt %s -o - | FileCheck %s
--- |
target triple = "thumbv7---eabi"
More information about the llvm-commits
mailing list