[llvm] e5c143f - [SLP]Drop nsw when reordering a sub feeding icmp eq/ne 0

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 16 16:03:03 PDT 2026


Author: Alexey Bataev
Date: 2026-07-16T19:02:58-04:00
New Revision: e5c143f96b37f2215a0b07d46df7600d06a372f4

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

LOG: [SLP]Drop nsw when reordering a sub feeding icmp eq/ne 0

A sub used only by icmp eq/ne 0 is treated as commutative, so SLP may
swap its operands, and nsw does not survive a - b -> b - a (a - b can
be INT_MIN while b - a overflows).

Fixes #210177

Reviewers: 

Pull Request: https://github.com/llvm/llvm-project/pull/210205

Added: 
    

Modified: 
    llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
    llvm/test/Transforms/SLPVectorizer/sub-nsw-icmp-eq-zero-reorder.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index ef144aa2403e7..6698395bf963b 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -23483,6 +23483,21 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
            return !SI || isCommutative(SI);
          })))
       I->setHasNoUnsignedWrap(/*b=*/false);
+    // A sub feeding icmp eq/ne 0 may have its operands swapped; nsw does not
+    // survive a - b -> b - a (a - b can be INT_MIN while b - a overflows).
+    if (!MinBWs.contains(E) && Opcode == Instruction::Sub &&
+        any_of(Scalars, [](Value *Scalar) {
+          auto *SI = dyn_cast<Instruction>(Scalar);
+          if (!SI || SI->getOpcode() != Instruction::Sub || !isCommutative(SI))
+            return false;
+          return any_of(SI->uses(), [](const Use &U) {
+            CmpPredicate Pred;
+            return match(U.getUser(),
+                         m_ICmp(Pred, m_Specific(U.get()), m_Zero())) &&
+                   ICmpInst::isEquality(Pred);
+          });
+        }))
+      I->setHasNoSignedWrap(/*b=*/false);
     // Interchanging add/sub negates the constant: nsw only survives if the
     // constant isn't INT_MIN (negating it would overflow); nuw never
     // survives a nonzero constant, since that flips the valid range from

diff  --git a/llvm/test/Transforms/SLPVectorizer/sub-nsw-icmp-eq-zero-reorder.ll b/llvm/test/Transforms/SLPVectorizer/sub-nsw-icmp-eq-zero-reorder.ll
index 344ad155110b6..4b2730d64cfc8 100644
--- a/llvm/test/Transforms/SLPVectorizer/sub-nsw-icmp-eq-zero-reorder.ll
+++ b/llvm/test/Transforms/SLPVectorizer/sub-nsw-icmp-eq-zero-reorder.ll
@@ -14,7 +14,7 @@ define <4 x i1> @sub_nsw_icmp_eq_zero(i8 %a0, i8 %a1, i8 %a2, i8 %a3, ptr %pl) {
 ; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <4 x i8> [[TMP1]], i8 [[A1]], i64 1
 ; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <4 x i8> [[TMP2]], i8 [[A2]], i64 2
 ; CHECK-NEXT:    [[TMP4:%.*]] = insertelement <4 x i8> [[TMP3]], i8 [[A3]], i64 3
-; CHECK-NEXT:    [[TMP5:%.*]] = sub nsw <4 x i8> [[TMP0]], [[TMP4]]
+; CHECK-NEXT:    [[TMP5:%.*]] = sub <4 x i8> [[TMP0]], [[TMP4]]
 ; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq <4 x i8> [[TMP5]], zeroinitializer
 ; CHECK-NEXT:    ret <4 x i1> [[TMP6]]
 ;


        


More information about the llvm-commits mailing list