[llvm] [GVN] Limit MemorySSA reaching-value block scans (PR #217945)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 21 11:25:34 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Madhur Amilkanthwar (madhur13490)

<details>
<summary>Changes</summary>

Cap expensive non-local MemorySSA queries at the same 200-block limit used by MemDep. On an internal workload, this closes the majority of the compile-time gap between the MemorySSA and MemDep GVN paths.
Runtime remains almost flat.

---
Full diff: https://github.com/llvm/llvm-project/pull/217945.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/Scalar/GVN.cpp (+8) 
- (added) llvm/test/Transforms/GVN/mssa-reach-block-limit.ll (+47) 


``````````diff
diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index 64fd14fcba1c5..ddd8e62f393ee 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -128,6 +128,11 @@ static cl::opt<uint32_t> MaxNumDeps(
     "gvn-max-num-deps", cl::Hidden, cl::init(100),
     cl::desc("Max number of dependences to attempt Load PRE (default = 100)"));
 
+static cl::opt<uint32_t> MaxNumReachingBlocks(
+    "gvn-max-num-reaching-blocks", cl::Hidden, cl::init(200),
+    cl::desc("Max number of blocks scanned per load in the MemorySSA "
+             "reaching-value analysis (default = 200)"));
+
 // This is based on IsValueFullyAvailableInBlockNumSpeculationsMax stat.
 static cl::opt<uint32_t> MaxBBSpeculations(
     "gvn-max-block-speculations", cl::Hidden, cl::init(600),
@@ -2665,6 +2670,9 @@ bool GVNPass::findReachingValuesForLoad(LoadInst *L,
   // Do a bottom-up DFS.
   auto Worklist = InitialWorklist;
   while (!Worklist.empty()) {
+    // Match MemDep's cutoff for expensive non-local queries.
+    if (Blocks.size() > MaxNumReachingBlocks)
+      return false;
     auto *BB = Worklist.pop_back_val();
     DependencyBlockInfo &Info = Blocks.find(BB)->second;
 
diff --git a/llvm/test/Transforms/GVN/mssa-reach-block-limit.ll b/llvm/test/Transforms/GVN/mssa-reach-block-limit.ll
new file mode 100644
index 0000000000000..13c6fb1202955
--- /dev/null
+++ b/llvm/test/Transforms/GVN/mssa-reach-block-limit.ll
@@ -0,0 +1,47 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes='gvn<memoryssa>' -S %s | FileCheck %s --check-prefix=DEFAULT
+; RUN: opt -passes='gvn<memoryssa>' -gvn-max-num-reaching-blocks=1 -S %s \
+; RUN:   | FileCheck %s --check-prefix=LIMIT
+
+; The limit abandons expensive non-local queries without changing the IR.
+define i32 @load_from_predecessors(ptr %ptr, i1 %cond) {
+; DEFAULT-LABEL: @load_from_predecessors(
+; DEFAULT-NEXT:  entry:
+; DEFAULT-NEXT:    br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; DEFAULT:       left:
+; DEFAULT-NEXT:    store i32 1, ptr [[PTR:%.*]], align 4
+; DEFAULT-NEXT:    br label [[MERGE:%.*]]
+; DEFAULT:       right:
+; DEFAULT-NEXT:    store i32 1, ptr [[PTR]], align 4
+; DEFAULT-NEXT:    br label [[MERGE]]
+; DEFAULT:       merge:
+; DEFAULT-NEXT:    ret i32 1
+;
+; LIMIT-LABEL: @load_from_predecessors(
+; LIMIT-NEXT:  entry:
+; LIMIT-NEXT:    br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; LIMIT:       left:
+; LIMIT-NEXT:    store i32 1, ptr [[PTR:%.*]], align 4
+; LIMIT-NEXT:    br label [[MERGE:%.*]]
+; LIMIT:       right:
+; LIMIT-NEXT:    store i32 1, ptr [[PTR]], align 4
+; LIMIT-NEXT:    br label [[MERGE]]
+; LIMIT:       merge:
+; LIMIT-NEXT:    [[VALUE:%.*]] = load i32, ptr [[PTR]], align 4
+; LIMIT-NEXT:    ret i32 [[VALUE]]
+;
+entry:
+  br i1 %cond, label %left, label %right
+
+left:
+  store i32 1, ptr %ptr
+  br label %merge
+
+right:
+  store i32 1, ptr %ptr
+  br label %merge
+
+merge:
+  %value = load i32, ptr %ptr
+  ret i32 %value
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/217945


More information about the llvm-commits mailing list