[llvm] [MemoryDependenceAnalysis] Migrate `isStorePreservingMemoryLocation` to Loads (NFC) (PR #223700)
Antonio Frighetto via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 16 01:07:16 PDT 2026
https://github.com/antoniofrighetto updated https://github.com/llvm/llvm-project/pull/223700
>From 48c7bf132df56294ef1d96411af1ce089fb283ec Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Tue, 15 Sep 2026 15:23:51 +0200
Subject: [PATCH] [MemoryDependenceAnalysis] Migrate
`isStorePreservingMemoryLocation` to Loads (NFC)
Minor opportunity to expose the helper and move it out of MDA.
---
llvm/include/llvm/Analysis/Loads.h | 11 ++++++
llvm/lib/Analysis/Loads.cpp | 30 ++++++++++++++++
.../lib/Analysis/MemoryDependenceAnalysis.cpp | 36 ++-----------------
3 files changed, 43 insertions(+), 34 deletions(-)
diff --git a/llvm/include/llvm/Analysis/Loads.h b/llvm/include/llvm/Analysis/Loads.h
index 22ce31d61ddb8..b6075082d34ef 100644
--- a/llvm/include/llvm/Analysis/Loads.h
+++ b/llvm/include/llvm/Analysis/Loads.h
@@ -33,6 +33,7 @@ class MemoryLocation;
class SCEV;
class ScalarEvolution;
class SCEVPredicate;
+class StoreInst;
template <typename T> class SmallVectorImpl;
class TargetLibraryInfo;
@@ -165,6 +166,16 @@ LLVM_ABI Value *
FindAvailableLoadedValue(LoadInst *Load, BatchAAResults &AA, bool *IsLoadCSE,
unsigned MaxInstsToScan = DefMaxInstsToScan);
+/// Check whether \p SI, which may alias \p MemLoc, can be safely skipped.
+/// This is possible when \p SI does only MustAlias or NoAlias \p MemLoc (no
+/// partial overlap possible), and it stores the value \p MemLoc currently
+/// holds (loaded before the store and not modified in between).
+LLVM_ABI bool isStorePreservingMemoryLocation(const StoreInst *SI,
+ const MemoryLocation &MemLoc,
+ Align MemLocAlign,
+ BatchAAResults &AA,
+ unsigned ScanLimit);
+
/// Scan backwards to see if we have the value of the given pointer available
/// locally within a small number of instructions.
///
diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp
index de9022c540d42..13a5585c1fa3f 100644
--- a/llvm/lib/Analysis/Loads.cpp
+++ b/llvm/lib/Analysis/Loads.cpp
@@ -813,6 +813,36 @@ Value *llvm::FindAvailableLoadedValue(LoadInst *Load, BatchAAResults &AA,
return Available;
}
+bool llvm::isStorePreservingMemoryLocation(const StoreInst *SI,
+ const MemoryLocation &MemLoc,
+ Align MemLocAlign,
+ BatchAAResults &AA,
+ unsigned ScanLimit) {
+ // Ensure no partial overlap is possible, and that the stored value is the
+ // current content of MemLoc.
+ if (!MemLoc.Size.hasValue() || MemLoc.Size.isScalable())
+ return false;
+ if (MemoryLocation::get(SI).Size != MemLoc.Size)
+ return false;
+ if (std::min(MemLocAlign, SI->getAlign()).value() <
+ MemLoc.Size.getValue().getFixedValue())
+ return false;
+
+ auto *LI = dyn_cast<LoadInst>(SI->getValueOperand());
+ if (!LI || LI->getParent() != SI->getParent())
+ return false;
+ if (AA.alias(MemoryLocation::get(LI), MemLoc) != AliasResult::MustAlias)
+ return false;
+
+ // No memory operation in between may modify MemLoc.
+ unsigned NumVisited = 0;
+ for (const Instruction *I = LI; I != SI; I = I->getNextNode())
+ if (++NumVisited > ScanLimit || isModSet(AA.getModRefInfo(I, MemLoc)))
+ return false;
+
+ return true;
+}
+
// Returns true if a use is either in an ICmp/PtrToInt or a Phi/Select that only
// feeds into them.
static bool isPointerUseReplaceable(const Use &U, bool HasNonAddressBits) {
diff --git a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
index a58608b53bb1f..a5a178c6f2583 100644
--- a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
@@ -351,39 +351,6 @@ MemoryDependenceResults::getInvariantGroupPointerDependency(LoadInst *LI,
return MemDepResult::getNonLocal();
}
-// Check if SI that may alias with MemLoc can be safely skipped. This is
-// possible in case if SI can only must alias or no alias with MemLoc (no
-// partial overlapping possible) and it writes the same value that MemLoc
-// contains now (it was loaded before this store and was not modified in
-// between).
-static bool canSkipClobberingStore(const StoreInst *SI,
- const MemoryLocation &MemLoc,
- Align MemLocAlign, BatchAAResults &BatchAA,
- unsigned ScanLimit) {
- if (!MemLoc.Size.hasValue())
- return false;
- if (MemoryLocation::get(SI).Size != MemLoc.Size)
- return false;
- if (MemLoc.Size.isScalable())
- return false;
- if (std::min(MemLocAlign, SI->getAlign()).value() <
- MemLoc.Size.getValue().getKnownMinValue())
- return false;
-
- auto *LI = dyn_cast<LoadInst>(SI->getValueOperand());
- if (!LI || LI->getParent() != SI->getParent())
- return false;
- if (BatchAA.alias(MemoryLocation::get(LI), MemLoc) != AliasResult::MustAlias)
- return false;
- unsigned NumVisitedInsts = 0;
- for (const Instruction *I = LI; I != SI; I = I->getNextNode())
- if (++NumVisitedInsts > ScanLimit ||
- isModSet(BatchAA.getModRefInfo(I, MemLoc)))
- return false;
-
- return true;
-}
-
MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
const MemoryLocation &MemLoc, bool isLoad, BasicBlock::iterator ScanIt,
BasicBlock *BB, Instruction *QueryInst, unsigned *Limit,
@@ -598,7 +565,8 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
return MemDepResult::getDef(Inst);
if (isInvariantLoad)
continue;
- if (canSkipClobberingStore(SI, MemLoc, MemLocAlign, BatchAA, *Limit))
+ if (isStorePreservingMemoryLocation(SI, MemLoc, MemLocAlign, BatchAA,
+ *Limit))
continue;
return MemDepResult::getClobber(Inst);
}
More information about the llvm-commits
mailing list