[llvm] [SCEV] Bail out on wider AddRecs in SCEVWrapPrediacte::implies. (PR #191498)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 11 06:44:27 PDT 2026
https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/191498
>From af0403bcd988b8db56147db34ee6ae7339f38a56 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Fri, 10 Apr 2026 16:20:52 +0100
Subject: [PATCH] [SCEV] Bail out on wider AddRecs in
SCEVWrapPrediacte::implies.
NSSW/NUSW on a wider AddRec does not imply NSSW/NUSW on a narrower
AddRec.
Fixes https://github.com/llvm/llvm-project/issues/191382.
---
llvm/lib/Analysis/ScalarEvolution.cpp | 6 ++++++
.../Analysis/LoopAccessAnalysis/nssw-predicate-implied.ll | 3 ++-
llvm/test/Analysis/LoopAccessAnalysis/nusw-predicates.ll | 7 ++++++-
.../LoopVectorize/runtime-check-small-clamped-bounds.ll | 6 ++++--
4 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 2862acfedb91d..9f362deb7cca9 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -15335,6 +15335,12 @@ bool SCEVWrapPredicate::implies(const SCEVPredicate *N,
if (Start->getType()->isPointerTy() && Start->getType() != OpStart->getType())
return false;
+ // NUSW/NSSW on a wider-type AddRec does not imply the same on a
+ // narrower-type AddRec.
+ if (SE.getTypeSizeInBits(AR->getType()) >
+ SE.getTypeSizeInBits(Op->AR->getType()))
+ return false;
+
const SCEV *Step = AR->getStepRecurrence(SE);
const SCEV *OpStep = Op->AR->getStepRecurrence(SE);
if (!SE.isKnownPositive(Step) || !SE.isKnownPositive(OpStep))
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/nssw-predicate-implied.ll b/llvm/test/Analysis/LoopAccessAnalysis/nssw-predicate-implied.ll
index 8299df310ce1f..168e9a867d217 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/nssw-predicate-implied.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/nssw-predicate-implied.ll
@@ -333,7 +333,7 @@ exit:
ret void
}
-; FIXME: NSSW on the wider i32 AddRec does not imply NSSW on a narrower i8 AddRec.
+; NSSW on the wider i32 AddRec does not imply NSSW on a narrower i8 AddRec.
; Test for https://github.com/llvm/llvm-project/issues/191382.
define void @wider_i32_nssw_does_not_imply_narrower_i8_nssw(ptr %dst, ptr %src, i32 %N) {
; CHECK-LABEL: 'wider_i32_nssw_does_not_imply_narrower_i8_nssw'
@@ -358,6 +358,7 @@ define void @wider_i32_nssw_does_not_imply_narrower_i8_nssw(ptr %dst, ptr %src,
; CHECK-NEXT: SCEV assumptions:
; CHECK-NEXT: Equal predicate: (zext i1 (trunc i32 %N to i1) to i32) == 0
; CHECK-NEXT: {0,+,2}<%loop> Added Flags: <nssw>
+; CHECK-NEXT: {0,+,1}<%loop> Added Flags: <nssw>
; CHECK-EMPTY:
; CHECK-NEXT: Expressions re-written:
; CHECK-NEXT: [PSE] %gep.dst = getelementptr inbounds i32, ptr %dst, i64 %ext.iv.1:
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/nusw-predicates.ll b/llvm/test/Analysis/LoopAccessAnalysis/nusw-predicates.ll
index 9d932c9bb4809..87b25140949b9 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/nusw-predicates.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/nusw-predicates.ll
@@ -159,19 +159,24 @@ loop:
ret void
}
-; FIXME: NUSW on the wider i32 AddRec does not imply NUSW on a narrower i8 AddRec.
+; NUSW on the wider i32 AddRec does not imply NUSW on a narrower i8 AddRec.
; Test for https://github.com/llvm/llvm-project/issues/191382.
define void @wider_i32_nusw_does_not_imply_narrower_i4_nusw(ptr %dst, i64 %n) {
; CHECK-LABEL: 'wider_i32_nusw_does_not_imply_narrower_i4_nusw'
; CHECK-NEXT: loop:
; CHECK-NEXT: Memory dependences are safe
; CHECK-NEXT: Dependences:
+; CHECK-NEXT: Forward:
+; CHECK-NEXT: %l.dst = load i8, ptr %gep.dst, align 1 ->
+; CHECK-NEXT: store i8 %xor, ptr %gep.dst, align 1
+; 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-NEXT: {1,+,1}<%loop> Added Flags: <nusw>
+; CHECK-NEXT: {0,+,1}<%loop> Added Flags: <nusw>
; CHECK-EMPTY:
; CHECK-NEXT: Expressions re-written:
; CHECK-NEXT: [PSE] %gep.dst = getelementptr inbounds nuw i8, ptr %dst, i64 %iv.mod.zext:
diff --git a/llvm/test/Transforms/LoopVectorize/runtime-check-small-clamped-bounds.ll b/llvm/test/Transforms/LoopVectorize/runtime-check-small-clamped-bounds.ll
index c3bf402071ade..c14a2495c5c3f 100644
--- a/llvm/test/Transforms/LoopVectorize/runtime-check-small-clamped-bounds.ll
+++ b/llvm/test/Transforms/LoopVectorize/runtime-check-small-clamped-bounds.ll
@@ -407,7 +407,7 @@ exit:
ret void
}
-; FIXME: NUSW on the wider i32 AddRec does no imply NUSW on a narrower i8 AddRec.
+; NUSW on the wider i32 AddRec does no imply NUSW on a narrower i8 AddRec.
; Test for https://github.com/llvm/llvm-project/issues/191382.
define void @wider_nusw_does_not_imply_narrower(ptr %dst, i64 %n) {
; CHECK-LABEL: @wider_nusw_does_not_imply_narrower(
@@ -424,7 +424,9 @@ define void @wider_nusw_does_not_imply_narrower(ptr %dst, i64 %n) {
; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 1
; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i64 [[TMP0]], 4294967295
; CHECK-NEXT: [[TMP8:%.*]] = or i1 [[TMP3]], [[TMP4]]
-; CHECK-NEXT: br i1 [[TMP8]], label [[SCALAR_PH]], label [[VECTOR_MEMCHECK:%.*]]
+; CHECK-NEXT: [[TMP7:%.*]] = icmp ugt i64 [[TMP0]], 15
+; CHECK-NEXT: [[TMP9:%.*]] = or i1 [[TMP8]], [[TMP7]]
+; CHECK-NEXT: br i1 [[TMP9]], label [[SCALAR_PH]], label [[VECTOR_MEMCHECK:%.*]]
; CHECK: vector.ph:
; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP5]], 4
; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP5]], [[N_MOD_VF]]
More information about the llvm-commits
mailing list