[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