[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