[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