[llvm] [LAA] Don't check for free in evaluatePtrAddRecAtMaxBTCWillNotWrap() (PR #202341)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 8 07:01:20 PDT 2026


https://github.com/nikic created https://github.com/llvm/llvm-project/pull/202341

The fact that an object of a certain size existed at the the location at some point is sufficient to prove the desired nowrap fact. Whether the object still exists there doesn't matter in this context.

>From 48991606218f2213fee22e1e036a8d6d7b8cf77d Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 8 Jun 2026 15:56:05 +0200
Subject: [PATCH] [LAA] Don't check for free in
 evaluatePtrAddRecAtMaxBTCWillNotWrap()

The fact that an object of a certain size existed at the the location
at some point is sufficient to prove the desired nowrap fact.
Whether the object still exists there doesn't matter in this context.
---
 llvm/lib/Analysis/LoopAccessAnalysis.cpp                   | 7 +++----
 .../LoopAccessAnalysis/early-exit-runtime-checks.ll        | 5 +++--
 llvm/test/Transforms/LoopVectorize/early-exit-calls.ll     | 1 +
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 60e15b2a5bd82..74f0fa8a954da 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -222,10 +222,12 @@ static bool evaluatePtrAddRecAtMaxBTCWillNotWrap(
   const Loop *L = AR->getLoop();
   bool CheckForNonNull, CheckForFreed;
   Value *StartPtrV = StartPtr->getValue();
+  // We can ignore frees, as the fact that an object of a certain size existed
+  // at the location *at some point* is sufficient to derive the nowrap fact.
   uint64_t DerefBytes = StartPtrV->getPointerDereferenceableBytes(
       DL, CheckForNonNull, CheckForFreed);
 
-  if (DerefBytes && (CheckForNonNull || CheckForFreed))
+  if (DerefBytes && CheckForNonNull)
     return false;
 
   const SCEV *Step = AR->getStepRecurrence(SE);
@@ -243,9 +245,6 @@ static bool evaluatePtrAddRecAtMaxBTCWillNotWrap(
                        [&](RetainedKnowledge RK, Instruction *Assume, auto) {
                          if (!isValidAssumeForContext(Assume, CtxI, DT))
                            return false;
-                         if (StartPtrV->canBeFreed() &&
-                             !willNotFreeBetween(Assume, CtxI))
-                           return false;
                          DerefRK = std::max(DerefRK, RK);
                          return true;
                        });
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/early-exit-runtime-checks.ll b/llvm/test/Analysis/LoopAccessAnalysis/early-exit-runtime-checks.ll
index 05aad8a6118d2..1b9f22c53e1f9 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/early-exit-runtime-checks.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/early-exit-runtime-checks.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -passes='print<access-info>' -disable-output %s 2>&1 | FileCheck %s
+; RUN: opt -passes='print<access-info>' -use-dereferenceable-at-point-semantics -disable-output %s 2>&1 | FileCheck %s
 
 define void @all_exits_dominate_latch_countable_exits_at_most_500_iterations_known_deref(ptr dereferenceable(2000) %A, ptr dereferenceable(2000) %B) {
 ; CHECK-LABEL: 'all_exits_dominate_latch_countable_exits_at_most_500_iterations_known_deref'
@@ -830,10 +831,10 @@ define void @all_exits_dominate_latch_countable_exits_at_most_500_iterations_kno
 ; CHECK-NEXT:          %gep.A = getelementptr inbounds i32, ptr %A, i64 %iv
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
-; CHECK-NEXT:          (Low: %B High: inttoptr (i64 -1 to ptr))
+; CHECK-NEXT:          (Low: %B High: (2000 + %B))
 ; CHECK-NEXT:            Member: {%B,+,4}<nuw><%loop.header>
 ; CHECK-NEXT:        Group GRP1:
-; CHECK-NEXT:          (Low: %A High: inttoptr (i64 -1 to ptr))
+; CHECK-NEXT:          (Low: %A High: (2000 + %A))
 ; CHECK-NEXT:            Member: {%A,+,4}<nuw><%loop.header>
 ; CHECK-EMPTY:
 ; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
diff --git a/llvm/test/Transforms/LoopVectorize/early-exit-calls.ll b/llvm/test/Transforms/LoopVectorize/early-exit-calls.ll
index 29bd33e24309c..5f56f5d797589 100644
--- a/llvm/test/Transforms/LoopVectorize/early-exit-calls.ll
+++ b/llvm/test/Transforms/LoopVectorize/early-exit-calls.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 6
 ; RUN: opt -passes=loop-vectorize -force-vector-width=4 -S %s | FileCheck %s
+; RUN: opt -passes=loop-vectorize -force-vector-width=4 -use-dereferenceable-at-point-semantics -S %s | FileCheck %s
 
 define i32 @early_exit_with_extractvalue(ptr dereferenceable(1024) align 8 %src, i32 noundef %x) {
 ; CHECK-LABEL: define i32 @early_exit_with_extractvalue(



More information about the llvm-commits mailing list