[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