[llvm] 5566928 - [LAA] Bail out of dependence analysis when distance exceeds 64 bits. (#209052)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 12 13:39:40 PDT 2026


Author: Florian Hahn
Date: 2026-07-12T20:39:36Z
New Revision: 5566928ef0b0788da6582ea3bcc8ab9ae416e80f

URL: https://github.com/llvm/llvm-project/commit/5566928ef0b0788da6582ea3bcc8ab9ae416e80f
DIFF: https://github.com/llvm/llvm-project/commit/5566928ef0b0788da6582ea3bcc8ab9ae416e80f.diff

LOG: [LAA] Bail out of dependence analysis when distance exceeds 64 bits. (#209052)

isDependent extracts the dependence distance into 64 bit integers.

Bail out conservatively when the constant distance or the signed minimum
distance needs more than 64 bits.

Added: 
    llvm/test/Analysis/LoopAccessAnalysis/wide-pointer-index-distance.ll

Modified: 
    llvm/lib/Analysis/LoopAccessAnalysis.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index f28b570d6191b..8d3c66c8fe321 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -2261,11 +2261,16 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
           DL, SE, *(PSE.getSymbolicMaxBackedgeTakenCount()), *Dist, MaxStride))
     return Dependence::NoDep;
 
-  // The rest of this function relies on ConstDist being at most 64-bits, which
-  // is checked earlier. Will assert if the calling code changes.
   const APInt *APDist = nullptr;
-  uint64_t ConstDist =
-      match(Dist, m_scev_APInt(APDist)) ? APDist->abs().getZExtValue() : 0;
+  uint64_t ConstDist = 0;
+  if (match(Dist, m_scev_APInt(APDist))) {
+    std::optional<uint64_t> Val = APDist->abs().tryZExtValue();
+    if (!Val) {
+      LLVM_DEBUG(dbgs() << "LAA: Constant distance does not fit in 64 bits.\n");
+      return Dependence::Unknown;
+    }
+    ConstDist = *Val;
+  }
 
   // Attempt to prove strided accesses independent.
   if (APDist) {
@@ -2321,7 +2326,13 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
     return Dependence::Forward;
   }
 
-  int64_t MinDistance = SE.getSignedRangeMin(Dist).getSExtValue();
+  std::optional<int64_t> MinDistanceOpt =
+      SE.getSignedRangeMin(Dist).trySExtValue();
+  if (!MinDistanceOpt) {
+    LLVM_DEBUG(dbgs() << "LAA: Minimum distance does not fit in 64 bits.\n");
+    return Dependence::Unknown;
+  }
+  int64_t MinDistance = *MinDistanceOpt;
   // Below we only handle strictly positive distances.
   if (MinDistance <= 0) {
     return CheckCompletelyBeforeOrAfter() ? Dependence::NoDep

diff  --git a/llvm/test/Analysis/LoopAccessAnalysis/wide-pointer-index-distance.ll b/llvm/test/Analysis/LoopAccessAnalysis/wide-pointer-index-distance.ll
new file mode 100644
index 0000000000000..54f6766f10ca0
--- /dev/null
+++ b/llvm/test/Analysis/LoopAccessAnalysis/wide-pointer-index-distance.ll
@@ -0,0 +1,85 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes='print<access-info>' -disable-output %s 2>&1 | FileCheck %s
+
+target datalayout = "e-p:128:128:128-i64:64-i128:128-n8:16:32:64-S128"
+
+; Constant distance whose byte value needs more than 64 bits.
+define void @i128_const_dist(ptr %A, i128 %n) {
+; CHECK-LABEL: 'i128_const_dist'
+; CHECK-NEXT:    loop:
+; CHECK-NEXT:      Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
+; CHECK-NEXT:  Unknown data dependence.
+; CHECK-NEXT:      Dependences:
+; CHECK-NEXT:        Unknown:
+; CHECK-NEXT:            %v = load i32, ptr %gep.load, align 4 ->
+; CHECK-NEXT:            store i32 %v, ptr %gep.store, align 4
+; CHECK-EMPTY:
+; CHECK-NEXT:      Run-time memory checks:
+; CHECK-NEXT:      Grouped accesses:
+; CHECK-EMPTY:
+; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
+; CHECK-NEXT:      SCEV assumptions:
+; CHECK-EMPTY:
+; CHECK-NEXT:      Expressions re-written:
+;
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i128 [ 0, %entry ], [ %iv.next, %loop ]
+  %gep.load = getelementptr inbounds i32, ptr %A, i128 %iv
+  %v = load i32, ptr %gep.load, align 4
+  ; Offset whose byte distance needs > 64 bits (~2^66 elements).
+  %idx.store = add i128 %iv, 73786976294838206464
+  %gep.store = getelementptr inbounds i32, ptr %A, i128 %idx.store
+  store i32 %v, ptr %gep.store, align 4
+  %iv.next = add i128 %iv, 1
+  %ec = icmp eq i128 %iv.next, %n
+  br i1 %ec, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+; Non-constant distance with a 128-bit type.
+define void @i128_nonconst_dist(ptr %A, i128 %n, i128 %offset) {
+; CHECK-LABEL: 'i128_nonconst_dist'
+; CHECK-NEXT:    loop:
+; CHECK-NEXT:      Memory dependences are safe with run-time checks
+; CHECK-NEXT:      Dependences:
+; CHECK-NEXT:      Run-time memory checks:
+; CHECK-NEXT:      Check 0:
+; CHECK-NEXT:        Comparing group GRP0:
+; CHECK-NEXT:          %gep.store = getelementptr inbounds i32, ptr %A, i128 %idx.store
+; CHECK-NEXT:        Against group GRP1:
+; CHECK-NEXT:          %gep.load = getelementptr inbounds i32, ptr %A, i128 %iv
+; CHECK-NEXT:      Grouped accesses:
+; CHECK-NEXT:        Group GRP0:
+; CHECK-NEXT:          (Low: ((4 * %offset) + %A) High: ((4 * %n) + (4 * %offset) + %A))
+; CHECK-NEXT:            Member: {((4 * %offset) + %A),+,4}<%loop>
+; CHECK-NEXT:        Group GRP1:
+; CHECK-NEXT:          (Low: %A High: ((4 * %n) + %A))
+; CHECK-NEXT:            Member: {%A,+,4}<%loop>
+; CHECK-EMPTY:
+; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
+; CHECK-NEXT:      SCEV assumptions:
+; CHECK-EMPTY:
+; CHECK-NEXT:      Expressions re-written:
+;
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i128 [ 0, %entry ], [ %iv.next, %loop ]
+  %idx.store = add i128 %iv, %offset
+  %gep.load = getelementptr inbounds i32, ptr %A, i128 %iv
+  %v = load i32, ptr %gep.load, align 4
+  %gep.store = getelementptr inbounds i32, ptr %A, i128 %idx.store
+  store i32 %v, ptr %gep.store, align 4
+  %iv.next = add i128 %iv, 1
+  %ec = icmp eq i128 %iv.next, %n
+  br i1 %ec, label %exit, label %loop
+
+exit:
+  ret void
+}


        


More information about the llvm-commits mailing list