[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