[llvm] a3b12f0 - [MemDep] Remove cached non-local defs referencing deleted instructions (#219929)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 8 05:46:59 PDT 2026
Author: Oscar Priego
Date: 2026-09-08T14:46:54+02:00
New Revision: a3b12f0cd5337230199fc9c6319cc2c4614f75b8
URL: https://github.com/llvm/llvm-project/commit/a3b12f0cd5337230199fc9c6319cc2c4614f75b8
DIFF: https://github.com/llvm/llvm-project/commit/a3b12f0cd5337230199fc9c6319cc2c4614f75b8.diff
LOG: [MemDep] Remove cached non-local defs referencing deleted instructions (#219929)
MemoryDependenceResults::removeInstruction() removed entries from
NonLocalDefsCache when the removed non-pointer instruction was itself a
cache key, but did not remove entries where that instruction was the cached
dependency result.
This could leave a stale instruction reachable through NonLocalDefsCache
after GVN erased it. A later non-local load query could then consume the
dangling dependency and crash in GVN::analyzeLoadAvailability().
Use ReverseNonLocalDefsCache to remove forward cache entries whose
dependency result references the removed instruction, keeping both maps
consistent.
Related removal paths now use the existing reverse-map helper, with
consistency assertions to catch future map divergence.
Fixes #219885.
A downstream Mono integration has also hit #219885 in practice when
tagging non-pointer array-header loads with !invariant.group. They
currently gate those tags off as a temporary workaround pending the
upstream fix in this PR:
Phantomical/mono at 7e44c68
Added:
Modified:
llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
llvm/test/Transforms/GVN/pr46054-md-nonlocaldefcache-cleanup.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
index 0ccaadaa1dfb7..a58608b53bb1f 100644
--- a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
@@ -868,8 +868,9 @@ void MemoryDependenceResults::getNonLocalPointerDependency(
auto NonLocalDefIt = NonLocalDefsCache.find(QueryInst);
if (NonLocalDefIt != NonLocalDefsCache.end()) {
Result.push_back(NonLocalDefIt->second);
- ReverseNonLocalDefsCache[NonLocalDefIt->second.getResult().getInst()]
- .erase(QueryInst);
+ RemoveFromReverseMap<const Value *>(
+ ReverseNonLocalDefsCache, NonLocalDefIt->second.getResult().getInst(),
+ QueryInst);
NonLocalDefsCache.erase(NonLocalDefIt);
return;
}
@@ -1504,8 +1505,10 @@ void MemoryDependenceResults::removeCachedNonLocalPointerDependencies(
if (auto *I = dyn_cast<Instruction>(P.getPointer())) {
auto toRemoveIt = ReverseNonLocalDefsCache.find(I);
if (toRemoveIt != ReverseNonLocalDefsCache.end()) {
- for (const auto *entry : toRemoveIt->second)
- NonLocalDefsCache.erase(entry);
+ for (const auto *Entry : toRemoveIt->second) {
+ [[maybe_unused]] bool Removed = NonLocalDefsCache.erase(Entry);
+ assert(Removed && "Reverse non-local def map out of sync?");
+ }
ReverseNonLocalDefsCache.erase(toRemoveIt);
}
}
@@ -1587,12 +1590,22 @@ void MemoryDependenceResults::removeInstruction(Instruction *RemInst) {
if (toRemoveIt != NonLocalDefsCache.end()) {
assert(isa<LoadInst>(RemInst) &&
"only load instructions should be added directly");
- const Instruction *DepV = toRemoveIt->second.getResult().getInst();
- ReverseNonLocalDefsCache.find(DepV)->second.erase(RemInst);
+ Instruction *DepV = toRemoveIt->second.getResult().getInst();
+ RemoveFromReverseMap<const Value *>(ReverseNonLocalDefsCache, DepV,
+ RemInst);
NonLocalDefsCache.erase(toRemoveIt);
}
}
+ auto ReverseNonLocalDefIt = ReverseNonLocalDefsCache.find(RemInst);
+ if (ReverseNonLocalDefIt != ReverseNonLocalDefsCache.end()) {
+ for (const Value *QueryInst : ReverseNonLocalDefIt->second) {
+ [[maybe_unused]] bool Removed = NonLocalDefsCache.erase(QueryInst);
+ assert(Removed && "Reverse non-local def map out of sync?");
+ }
+ ReverseNonLocalDefsCache.erase(ReverseNonLocalDefIt);
+ }
+
// Loop over all of the things that depend on the instruction we're removing.
SmallVector<std::pair<Instruction *, Instruction *>, 8> ReverseDepsToAdd;
diff --git a/llvm/test/Transforms/GVN/pr46054-md-nonlocaldefcache-cleanup.ll b/llvm/test/Transforms/GVN/pr46054-md-nonlocaldefcache-cleanup.ll
index 6ed447a5f2f7b..66d59ed7e5982 100644
--- a/llvm/test/Transforms/GVN/pr46054-md-nonlocaldefcache-cleanup.ll
+++ b/llvm/test/Transforms/GVN/pr46054-md-nonlocaldefcache-cleanup.ll
@@ -78,4 +78,27 @@ declare void @fn.ptr(ptr)
declare noalias ptr @data.ptr()
+define i32 @test_non_pointer_load_deleted_as_cached_def(ptr %p, i1 %c) {
+; CHECK-LABEL: @test_non_pointer_load_deleted_as_cached_def(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[C:%.*]], label [[A:%.*]], label [[MID:%.*]]
+; CHECK: a:
+; CHECK-NEXT: br label [[MID]]
+; CHECK: mid:
+; CHECK-NEXT: [[Q:%.*]] = load atomic i32, ptr [[P:%.*]] unordered, align 4, !invariant.group !0
+; CHECK-NEXT: ret i32 [[Q]]
+;
+entry:
+ %x = load i32, ptr %p, align 4, !invariant.group !0
+ br i1 %c, label %a, label %mid
+
+a:
+ br label %mid
+
+mid:
+ %q = load atomic i32, ptr %p unordered, align 4, !invariant.group !0
+ %d = add i32 %x, 0
+ ret i32 %q
+}
+
!0 = distinct !{}
More information about the llvm-commits
mailing list