[llvm] [GISel][NewPM] Port LoadStoreOpt (PR #217190)
Aiden Grossman via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 18 18:51:02 PDT 2026
https://github.com/boomanaiden154 created https://github.com/llvm/llvm-project/pull/217190
Standard NewPM pass porting.
>From d822c75ee2952379b04b6f2bfe0aae3c24caaa59 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <aidengrossman at google.com>
Date: Wed, 19 Aug 2026 01:50:50 +0000
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
=?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.7
---
.../llvm/CodeGen/GlobalISel/LoadStoreOpt.h | 37 ++++++---
llvm/include/llvm/InitializePasses.h | 2 +-
.../llvm/Passes/MachinePassRegistry.def | 1 +
llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp | 2 +-
llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp | 82 ++++++++++++-------
llvm/lib/Passes/PassBuilder.cpp | 1 +
.../Target/AArch64/AArch64TargetMachine.cpp | 4 +-
.../GlobalISel/merge-stores-truncating.mir | 2 +-
.../GlobalISel/store-merging-debug.mir | 2 +-
.../AArch64/GlobalISel/store-merging.mir | 3 +-
10 files changed, 88 insertions(+), 48 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LoadStoreOpt.h b/llvm/include/llvm/CodeGen/GlobalISel/LoadStoreOpt.h
index 30ee0c57c8807..7965071ebf3e3 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LoadStoreOpt.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LoadStoreOpt.h
@@ -22,6 +22,7 @@
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
@@ -75,11 +76,24 @@ LLVM_ABI bool instMayAlias(const MachineInstr &MI, const MachineInstr &Other,
using namespace GISelAddressing;
-class LLVM_ABI LoadStoreOpt : public MachineFunctionPass {
+class LLVM_ABI LoadStoreOptLegacy : public MachineFunctionPass {
public:
static char ID;
-private:
+ LoadStoreOptLegacy();
+
+ StringRef getPassName() const override { return "LoadStoreOpt"; }
+
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().setIsSSA();
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+};
+
+class LoadStoreOptImpl {
MachineRegisterInfo *MRI = nullptr;
const TargetLowering *TLI = nullptr;
MachineFunction *MF = nullptr;
@@ -89,7 +103,7 @@ class LLVM_ABI LoadStoreOpt : public MachineFunctionPass {
MachineIRBuilder Builder;
/// Initialize the field members using \p MF.
- void init(MachineFunction &MF);
+ void init(MachineFunction &MF, function_ref<AliasAnalysis *()> GetAA);
class StoreMergeCandidate {
public:
@@ -161,17 +175,14 @@ class LLVM_ABI LoadStoreOpt : public MachineFunctionPass {
SmallPtrSet<MachineInstr *, 16> InstsToErase;
public:
- LoadStoreOpt();
-
- StringRef getPassName() const override { return "LoadStoreOpt"; }
-
- MachineFunctionProperties getRequiredProperties() const override {
- return MachineFunctionProperties().setIsSSA();
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override;
+ bool runOnMachineFunction(MachineFunction &MF,
+ function_ref<AliasAnalysis *()> GetAA);
+};
- bool runOnMachineFunction(MachineFunction &MF) override;
+class LoadStoreOptPass : public RequiredPassInfoMixin<LoadStoreOptPass> {
+public:
+ PreservedAnalyses run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM);
};
} // End namespace llvm.
diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index 0d2b0e0a6a274..3b069b6904e26 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/include/llvm/InitializePasses.h
@@ -168,7 +168,7 @@ LLVM_ABI void initializeLiveRangeShrinkPass(PassRegistry &);
LLVM_ABI void initializeLiveRegMatrixWrapperLegacyPass(PassRegistry &);
LLVM_ABI void initializeLiveStacksWrapperLegacyPass(PassRegistry &);
LLVM_ABI void initializeLiveVariablesWrapperPassPass(PassRegistry &);
-LLVM_ABI void initializeLoadStoreOptPass(PassRegistry &);
+LLVM_ABI void initializeLoadStoreOptLegacyPass(PassRegistry &);
LLVM_ABI void initializeLoadStoreVectorizerLegacyPassPass(PassRegistry &);
LLVM_ABI void initializeLocalStackSlotPassPass(PassRegistry &);
LLVM_ABI void initializeLocalizerPass(PassRegistry &);
diff --git a/llvm/include/llvm/Passes/MachinePassRegistry.def b/llvm/include/llvm/Passes/MachinePassRegistry.def
index 87c5f54bf2055..ba0948b925f04 100644
--- a/llvm/include/llvm/Passes/MachinePassRegistry.def
+++ b/llvm/include/llvm/Passes/MachinePassRegistry.def
@@ -84,6 +84,7 @@ MACHINE_FUNCTION_PASS("ir-translator", IRTranslatorPass(TM->getOptLevel()))
MACHINE_FUNCTION_PASS("kcfi", MachineKCFIPass())
MACHINE_FUNCTION_PASS("gc-empty-basic-blocks", GCEmptyBasicBlocksPass())
MACHINE_FUNCTION_PASS("legalizer", LegalizerPass())
+MACHINE_FUNCTION_PASS("load-store-opt", LoadStoreOptPass())
MACHINE_FUNCTION_PASS("localstackalloc", LocalStackSlotAllocationPass())
MACHINE_FUNCTION_PASS("machine-cp", MachineCopyPropagationPass())
MACHINE_FUNCTION_PASS("machine-cse", MachineCSEPass())
diff --git a/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp b/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp
index 3a6283483de24..85508f40e580b 100644
--- a/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp
@@ -17,7 +17,7 @@ using namespace llvm;
void llvm::initializeGlobalISel(PassRegistry &Registry) {
initializeIRTranslatorLegacyPass(Registry);
initializeLegalizerLegacyPass(Registry);
- initializeLoadStoreOptPass(Registry);
+ initializeLoadStoreOptLegacyPass(Registry);
initializeLocalizerPass(Registry);
initializeRegBankSelectPass(Registry);
initializeInstructionSelectPass(Registry);
diff --git a/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp b/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp
index 4d1adaed270fb..9901c8a29f52c 100644
--- a/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp
@@ -24,12 +24,15 @@
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
+#include "llvm/CodeGen/MachinePassManager.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Register.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetOpcodes.h"
+#include "llvm/IR/Analysis.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Casting.h"
@@ -37,7 +40,7 @@
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
-#define DEBUG_TYPE "loadstore-opt"
+#define DEBUG_TYPE "load-store-opt"
using namespace llvm;
using namespace ore;
@@ -47,18 +50,19 @@ STATISTIC(NumStoresMerged, "Number of stores merged");
const unsigned MaxStoreSizeToForm = 128;
-char LoadStoreOpt::ID = 0;
-INITIALIZE_PASS_BEGIN(LoadStoreOpt, DEBUG_TYPE, "Generic memory optimizations",
- false, false)
-INITIALIZE_PASS_END(LoadStoreOpt, DEBUG_TYPE, "Generic memory optimizations",
- false, false)
+char LoadStoreOptLegacy::ID = 0;
+INITIALIZE_PASS_BEGIN(LoadStoreOptLegacy, DEBUG_TYPE,
+ "Generic memory optimizations", false, false)
+INITIALIZE_PASS_END(LoadStoreOptLegacy, DEBUG_TYPE,
+ "Generic memory optimizations", false, false)
-LoadStoreOpt::LoadStoreOpt() : MachineFunctionPass(ID) {}
+LoadStoreOptLegacy::LoadStoreOptLegacy() : MachineFunctionPass(ID) {}
-void LoadStoreOpt::init(MachineFunction &MF) {
+void LoadStoreOptImpl::init(MachineFunction &MF,
+ function_ref<AliasAnalysis *()> GetAA) {
this->MF = &MF;
MRI = &MF.getRegInfo();
- AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
+ AA = GetAA();
TLI = MF.getSubtarget().getTargetLowering();
LI = MF.getSubtarget().getLegalizerInfo();
Builder.setMF(MF);
@@ -66,7 +70,7 @@ void LoadStoreOpt::init(MachineFunction &MF) {
InstsToErase.clear();
}
-void LoadStoreOpt::getAnalysisUsage(AnalysisUsage &AU) const {
+void LoadStoreOptLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<AAResultsWrapperPass>();
AU.setPreservesAll();
getSelectionDAGFallbackAnalysisUsage(AU);
@@ -295,7 +299,7 @@ static bool isInstHardMergeHazard(MachineInstr &MI) {
return MI.hasUnmodeledSideEffects() || MI.hasOrderedMemoryRef();
}
-bool LoadStoreOpt::mergeStores(SmallVectorImpl<GStore *> &StoresToMerge) {
+bool LoadStoreOptImpl::mergeStores(SmallVectorImpl<GStore *> &StoresToMerge) {
// Try to merge all the stores in the vector, splitting into separate segments
// as necessary.
assert(StoresToMerge.size() > 1 && "Expected multiple stores to merge");
@@ -340,8 +344,8 @@ bool LoadStoreOpt::mergeStores(SmallVectorImpl<GStore *> &StoresToMerge) {
return AnyMerged;
}
-bool LoadStoreOpt::isLegalOrBeforeLegalizer(const LegalityQuery &Query,
- MachineFunction &MF) const {
+bool LoadStoreOptImpl::isLegalOrBeforeLegalizer(const LegalityQuery &Query,
+ MachineFunction &MF) const {
auto Action = LI->getAction(Query).Action;
// If the instruction is unsupported, it can't be legalized at all.
if (Action == LegalizeActions::Unsupported)
@@ -349,7 +353,7 @@ bool LoadStoreOpt::isLegalOrBeforeLegalizer(const LegalityQuery &Query,
return IsPreLegalizer || Action == LegalizeAction::Legal;
}
-bool LoadStoreOpt::doSingleStoreMerge(SmallVectorImpl<GStore *> &Stores) {
+bool LoadStoreOptImpl::doSingleStoreMerge(SmallVectorImpl<GStore *> &Stores) {
assert(Stores.size() > 1);
// We know that all the stores are consecutive and there are no aliasing
// operations in the range. However, the values that are being stored may be
@@ -429,7 +433,7 @@ bool LoadStoreOpt::doSingleStoreMerge(SmallVectorImpl<GStore *> &Stores) {
return true;
}
-bool LoadStoreOpt::processMergeCandidate(StoreMergeCandidate &C) {
+bool LoadStoreOptImpl::processMergeCandidate(StoreMergeCandidate &C) {
if (C.Stores.size() < 2) {
C.reset();
return false;
@@ -489,8 +493,8 @@ bool LoadStoreOpt::processMergeCandidate(StoreMergeCandidate &C) {
return mergeStores(StoresToMerge);
}
-bool LoadStoreOpt::operationAliasesWithCandidate(MachineInstr &MI,
- StoreMergeCandidate &C) {
+bool LoadStoreOptImpl::operationAliasesWithCandidate(MachineInstr &MI,
+ StoreMergeCandidate &C) {
if (C.Stores.empty())
return false;
return llvm::any_of(C.Stores, [&](MachineInstr *OtherMI) {
@@ -498,12 +502,13 @@ bool LoadStoreOpt::operationAliasesWithCandidate(MachineInstr &MI,
});
}
-void LoadStoreOpt::StoreMergeCandidate::addPotentialAlias(MachineInstr &MI) {
+void LoadStoreOptImpl::StoreMergeCandidate::addPotentialAlias(
+ MachineInstr &MI) {
PotentialAliases.emplace_back(std::make_pair(&MI, Stores.size() - 1));
}
-bool LoadStoreOpt::addStoreToCandidate(GStore &StoreMI,
- StoreMergeCandidate &C) {
+bool LoadStoreOptImpl::addStoreToCandidate(GStore &StoreMI,
+ StoreMergeCandidate &C) {
// Check if the given store writes to an adjacent address, and other
// requirements.
LLT ValueTy = MRI->getType(StoreMI.getValueReg());
@@ -573,7 +578,7 @@ bool LoadStoreOpt::addStoreToCandidate(GStore &StoreMI,
return true;
}
-bool LoadStoreOpt::mergeBlockStores(MachineBasicBlock &MBB) {
+bool LoadStoreOptImpl::mergeBlockStores(MachineBasicBlock &MBB) {
bool Changed = false;
// Walk through the block bottom-up, looking for merging candidates.
StoreMergeCandidate Candidate;
@@ -701,8 +706,8 @@ getTruncStoreByteOffset(GStore &Store, Register &SrcVal,
/// p[3] = (val >> 0) & 0xFF;
/// =>
/// *((i32)p) = BSWAP(val);
-bool LoadStoreOpt::mergeTruncStore(GStore &StoreMI,
- SmallPtrSetImpl<GStore *> &DeletedStores) {
+bool LoadStoreOptImpl::mergeTruncStore(
+ GStore &StoreMI, SmallPtrSetImpl<GStore *> &DeletedStores) {
LLT MemTy = StoreMI.getMMO().getMemoryType();
// We only handle merging simple stores of 1-4 bytes.
@@ -896,7 +901,7 @@ bool LoadStoreOpt::mergeTruncStore(GStore &StoreMI,
return true;
}
-bool LoadStoreOpt::mergeTruncStoresBlock(MachineBasicBlock &BB) {
+bool LoadStoreOptImpl::mergeTruncStoresBlock(MachineBasicBlock &BB) {
bool Changed = false;
SmallVector<GStore *, 16> Stores;
SmallPtrSet<GStore *, 8> DeletedStores;
@@ -914,7 +919,7 @@ bool LoadStoreOpt::mergeTruncStoresBlock(MachineBasicBlock &BB) {
return Changed;
}
-bool LoadStoreOpt::mergeFunctionStores(MachineFunction &MF) {
+bool LoadStoreOptImpl::mergeFunctionStores(MachineFunction &MF) {
bool Changed = false;
for (auto &BB : MF){
Changed |= mergeBlockStores(BB);
@@ -934,7 +939,7 @@ bool LoadStoreOpt::mergeFunctionStores(MachineFunction &MF) {
return Changed;
}
-void LoadStoreOpt::initializeStoreMergeTargetInfo(unsigned AddrSpace) {
+void LoadStoreOptImpl::initializeStoreMergeTargetInfo(unsigned AddrSpace) {
// Query the legalizer info to record what store types are legal.
// We record this because we don't want to bother trying to merge stores into
// illegal ones, which would just result in being split again.
@@ -967,7 +972,8 @@ void LoadStoreOpt::initializeStoreMergeTargetInfo(unsigned AddrSpace) {
LegalStoreSizes[AddrSpace] = std::move(LegalSizes);
}
-bool LoadStoreOpt::runOnMachineFunction(MachineFunction &MF) {
+bool LoadStoreOptImpl::runOnMachineFunction(
+ MachineFunction &MF, function_ref<AliasAnalysis *()> GetAA) {
// If the ISel pipeline failed, do not bother running that pass.
if (MF.getProperties().hasFailedISel())
return false;
@@ -975,10 +981,30 @@ bool LoadStoreOpt::runOnMachineFunction(MachineFunction &MF) {
LLVM_DEBUG(dbgs() << "Begin memory optimizations for: " << MF.getName()
<< '\n');
- init(MF);
+ init(MF, GetAA);
bool Changed = false;
Changed |= mergeFunctionStores(MF);
LegalStoreSizes.clear();
return Changed;
}
+
+bool LoadStoreOptLegacy::runOnMachineFunction(MachineFunction &MF) {
+ LoadStoreOptImpl Impl;
+ return Impl.runOnMachineFunction(MF, [&]() {
+ return &getAnalysis<AAResultsWrapperPass>().getAAResults();
+ });
+}
+
+PreservedAnalyses LoadStoreOptPass::run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM) {
+ MFPropsModifier<LoadStoreOptPass> _(*this, MF);
+ LoadStoreOptImpl Impl;
+ Impl.runOnMachineFunction(MF, [&]() {
+ FunctionAnalysisManager &FAM =
+ MFAM.getResult<FunctionAnalysisManagerMachineFunctionProxy>(MF)
+ .getManager();
+ return &FAM.getResult<AAManager>(MF.getFunction());
+ });
+ return PreservedAnalyses::all();
+}
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 697eb5a372264..6956a01a95c4d 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -106,6 +106,7 @@
#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
#include "llvm/CodeGen/GlobalISel/Legalizer.h"
+#include "llvm/CodeGen/GlobalISel/LoadStoreOpt.h"
#include "llvm/CodeGen/GlobalMerge.h"
#include "llvm/CodeGen/GlobalMergeFunctions.h"
#include "llvm/CodeGen/HardwareLoops.h"
diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
index 0fb3cee4a265f..862bf13369f87 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
@@ -781,7 +781,7 @@ void AArch64PassConfig::addPreLegalizeMachineIR() {
addPass(createAArch64PreLegalizerCombiner());
addPass(new Localizer());
if (EnableGISelLoadStoreOptPreLegal)
- addPass(new LoadStoreOpt());
+ addPass(new LoadStoreOptLegacy());
}
}
@@ -796,7 +796,7 @@ void AArch64PassConfig::addPreRegBankSelect() {
if (!IsGlobalISelOptNone) {
addPass(createAArch64PostLegalizerCombinerLegacy(IsGlobalISelOptNone));
if (EnableGISelLoadStoreOptPostLegal)
- addPass(new LoadStoreOpt());
+ addPass(new LoadStoreOptLegacy());
}
addPass(createAArch64PostLegalizerLowering());
}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/merge-stores-truncating.mir b/llvm/test/CodeGen/AArch64/GlobalISel/merge-stores-truncating.mir
index de2143d413c81..1d045dc0426cc 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/merge-stores-truncating.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/merge-stores-truncating.mir
@@ -1,5 +1,5 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple aarch64 -run-pass=loadstore-opt -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -mtriple aarch64 -run-pass=load-store-opt -verify-machineinstrs %s -o - | FileCheck %s
---
name: trunc_i16_to_i8
alignment: 4
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/store-merging-debug.mir b/llvm/test/CodeGen/AArch64/GlobalISel/store-merging-debug.mir
index 3621530faab23..49e9930aec9bd 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/store-merging-debug.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/store-merging-debug.mir
@@ -1,5 +1,5 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=aarch64-apple-ios -global-isel -global-isel-abort=1 -run-pass=loadstore-opt %s -o - | FileCheck %s
+# RUN: llc -mtriple=aarch64-apple-ios -global-isel -global-isel-abort=1 -run-pass=load-store-opt %s -o - | FileCheck %s
--- |
source_filename = "store-merging-debug.mir"
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/store-merging.mir b/llvm/test/CodeGen/AArch64/GlobalISel/store-merging.mir
index 2cd0b172f415f..7e6c595779101 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/store-merging.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/store-merging.mir
@@ -1,5 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=aarch64-- -run-pass=loadstore-opt -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -mtriple=aarch64-- -run-pass=load-store-opt -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -mtriple=aarch64-- -passes=load-store-opt %s -o - | FileCheck %s
--- |
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64"
More information about the llvm-commits
mailing list