[llvm] [LoopVectorize] - Add tighter runtime memory check threshold for inner loops. (PR #219489)
Pawan Nirpal via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 28 07:36:37 PDT 2026
https://github.com/pawan-nirpal-031 updated https://github.com/llvm/llvm-project/pull/219489
>From 9c4b619dcdc967cbeb0d819c7bde42b43f49df9b Mon Sep 17 00:00:00 2001
From: Pawan Nirpal <pnirpal at qti.qualcomm.com>
Date: Fri, 28 Aug 2026 07:03:53 -0700
Subject: [PATCH] [LoopVectorize] - Add tighter runtime memory check threshold
for inner loops
---
.../Transforms/Vectorize/LoopVectorize.cpp | 33 ++++++++++++++++---
1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 1f153afd6bedd..197a3f31a3e04 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -203,6 +203,16 @@ static cl::opt<unsigned> VectorizeMemoryCheckThreshold(
"vectorize-memory-check-threshold", cl::init(128), cl::Hidden,
cl::desc("The maximum allowed number of runtime memory checks"));
+// When the loop being vectorized is an inner loop whose runtime memory checks
+// are not loop-invariant w.r.t. an outer loop (i.e., the checks execute on
+// every outer iteration), use a tighter threshold. This prevents the
+// combinatorial explosion of pointer-pair checks that arises when inlining
+// exposes multiple memory streams to the vectorizer's outer-loop interleaving.
+static cl::opt<unsigned> VectorizeMemoryCheckInnerLoopThreshold(
+ "vectorize-memory-check-inner-loop-threshold", cl::init(12), cl::Hidden,
+ cl::desc("The maximum allowed number of runtime memory checks for inner "
+ "loops whose checks are not hoistable out of an outer loop"));
+
static cl::opt<bool> ForcePartialAliasingVectorization(
"force-partial-aliasing-vectorization", cl::init(false), cl::Hidden,
cl::desc("Replace pointer diff checks with alias masks."));
@@ -1588,8 +1598,19 @@ class GeneratedRTChecks {
// runtime checks needs to be generated.
// TODO: Skip cutoff if the loop is guaranteed to execute, e.g. due to
// profile info.
- CostTooHigh =
- LAI.getNumRuntimePointerChecks() > VectorizeMemoryCheckThreshold;
+ unsigned NumChecks = LAI.getNumRuntimePointerChecks();
+ unsigned EffectiveThreshold = VectorizeMemoryCheckThreshold;
+
+ // For inner loops, apply a tighter threshold. When an inner loop requires
+ // many runtime checks (e.g., due to outer-loop interleaving creating a
+ // combinatorial explosion of pointer-pair comparisons), the checks execute
+ // on every outer-loop iteration, causing severe overhead from both the
+ // check instructions themselves and the resulting register pressure.
+ if (L->getParentLoop() &&
+ NumChecks > VectorizeMemoryCheckInnerLoopThreshold)
+ EffectiveThreshold = VectorizeMemoryCheckInnerLoopThreshold;
+
+ CostTooHigh = NumChecks > EffectiveThreshold;
if (CostTooHigh) {
// Mark runtime checks as never succeeding when they exceed the threshold.
MemRuntimeCheckCond = ConstantInt::getTrue(L->getHeader()->getContext());
@@ -1598,9 +1619,13 @@ class GeneratedRTChecks {
return OptimizationRemarkAnalysisAliasing(
DEBUG_TYPE, "TooManyMemoryRuntimeChecks", L->getStartLoc(),
L->getHeader())
- << "loop not vectorized: too many memory checks needed";
+ << "loop not vectorized: too many memory checks needed"
+ << (NumChecks > VectorizeMemoryCheckThreshold
+ ? ""
+ : " (inner loop threshold exceeded)");
});
- LLVM_DEBUG(dbgs() << "LV: Too many memory checks needed.\n");
+ LLVM_DEBUG(dbgs() << "LV: Too many memory checks needed (" << NumChecks
+ << " > " << EffectiveThreshold << ").\n");
return;
}
More information about the llvm-commits
mailing list