[llvm] [LAA] Avoid std::abs(INT64_MIN) signed-overflow UB in stride scaling. (PR #215640)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 11 13:52:14 PDT 2026


https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/215640

>From 39de7489649ee967f4ef6404ae4add5733c6eda4 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Mon, 3 Aug 2026 21:52:03 +0100
Subject: [PATCH] [LAA] Avoid std::abs(INT64_MIN) signed-overflow UB in stride
 scaling

getDependenceDistanceStrideAndSize scaled the strides via
std::abs(StridePtrInt), which is UB for INT64_MIN. Use
llvm::AbsoluteValue, which negates in the unsigned domain.

Fixes an UBSan failure for the added test case.
---
 llvm/lib/Analysis/LoopAccessAnalysis.cpp      |  5 ++-
 .../LoopAccessAnalysis/int64-min-stride.ll    | 40 +++++++++++++++++++
 2 files changed, 43 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/Analysis/LoopAccessAnalysis/int64-min-stride.ll

diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index e248b22de7d43..4650d630fd0ba 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -57,6 +57,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <cassert>
@@ -2210,8 +2211,8 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
   uint64_t BSz = DL.getTypeAllocSize(BTy);
   uint64_t TypeByteSize = (AStoreSz == BStoreSz) ? BSz : 0;
 
-  uint64_t StrideAScaled = std::abs(StrideAPtrInt) * ASz;
-  uint64_t StrideBScaled = std::abs(StrideBPtrInt) * BSz;
+  uint64_t StrideAScaled = AbsoluteValue(StrideAPtrInt) * ASz;
+  uint64_t StrideBScaled = AbsoluteValue(StrideBPtrInt) * BSz;
 
   uint64_t MaxStride = std::max(StrideAScaled, StrideBScaled);
 
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/int64-min-stride.ll b/llvm/test/Analysis/LoopAccessAnalysis/int64-min-stride.ll
new file mode 100644
index 0000000000000..9201203ee52b4
--- /dev/null
+++ b/llvm/test/Analysis/LoopAccessAnalysis/int64-min-stride.ll
@@ -0,0 +1,40 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes='print<access-info>' -S -disable-output %s 2>&1 | FileCheck %s
+
+define void @int64_min_stride(ptr %A, i64 %n) {
+; CHECK-LABEL: 'int64_min_stride'
+; CHECK-NEXT:    loop:
+; CHECK-NEXT:      Memory dependences are safe
+; CHECK-NEXT:      Dependences:
+; CHECK-NEXT:      Run-time memory checks:
+; CHECK-NEXT:      Grouped accesses:
+; CHECK-NEXT:        Group GRP0:
+; CHECK-NEXT:          (Low: (-9223372036854775808 + (-9223372036854775808 * %n) + %A) High: (5 + %A))
+; CHECK-NEXT:            Member: {(4 + %A),+,-9223372036854775808}<%loop>
+; CHECK-NEXT:            Member: {%A,+,-9223372036854775808}<%loop>
+; CHECK-EMPTY:
+; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
+; CHECK-NEXT:      SCEV assumptions:
+; CHECK-NEXT:      {%A,+,-9223372036854775808}<%loop> Added Flags: <nusw>
+; CHECK-NEXT:      {(4 + %A),+,-9223372036854775808}<%loop> Added Flags: <nusw>
+; CHECK-EMPTY:
+; CHECK-NEXT:      Expressions re-written:
+;
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %off = mul i64 %iv, -9223372036854775808
+  %off2 = add i64 %off, 4
+  %a = getelementptr i8, ptr %A, i64 %off
+  %a2 = getelementptr i8, ptr %A, i64 %off2
+  %v = load i8, ptr %a2
+  store i8 %v, ptr %a
+  %iv.next = add i64 %iv, 1
+  %ec = icmp eq i64 %iv.next, %n
+  br i1 %ec, label %exit, label %loop
+
+exit:
+  ret void
+}



More information about the llvm-commits mailing list