[llvm] 0d9f87e - [GVN] Limit MemorySSA reaching-value block scans (#217945)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 24 04:51:26 PDT 2026
Author: Madhur Amilkanthwar
Date: 2026-08-24T17:21:20+05:30
New Revision: 0d9f87ea61558d56673587373df608227fb1e496
URL: https://github.com/llvm/llvm-project/commit/0d9f87ea61558d56673587373df608227fb1e496
DIFF: https://github.com/llvm/llvm-project/commit/0d9f87ea61558d56673587373df608227fb1e496.diff
LOG: [GVN] Limit MemorySSA reaching-value block scans (#217945)
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.
Added:
llvm/test/Transforms/GVN/mssa-reach-block-limit.ll
Modified:
llvm/lib/Transforms/Scalar/GVN.cpp
Removed:
################################################################################
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
+}
More information about the llvm-commits
mailing list