[llvm-branch-commits] [llvm] release/23.x: [SDAG] Fix invalid sign bit condition for abs(sub) -> abdu fold (#215548) (PR #217203)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Aug 18 20:53:40 PDT 2026


https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/217203

Backport 93030c3

Requested by: @Benjins

>From f655a787ad37d1b5db9c739c1e2cca301f95aa0d Mon Sep 17 00:00:00 2001
From: Benji Smith <6193112+Benjins at users.noreply.github.com>
Date: Mon, 17 Aug 2026 21:54:01 -0400
Subject: [PATCH] [SDAG] Fix invalid sign bit condition for abs(sub) -> abdu
 fold (#215548)

The fold here for (abs (sub x y)) -> (abdu x y) was proven in Alive,
assuming that both operands had a sign bit of zero. However, the code
was checking if x had a sign bit of zero and y had a sign bit of 1

Fixes https://github.com/llvm/llvm-project/issues/214942

Original Alive proof from
https://github.com/llvm/llvm-project/pull/186659 :
https://alive2.llvm.org/ce/z/HfPF5q
A variant that's explicitly (abs (sub x y)):
https://alive2.llvm.org/ce/z/QEgDaa
And changing the range to 32770 or higher there will break the
transformation

(cherry picked from commit 93030c36edb97a9efeca32eea9a8ca0c27a6be1a)
---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp |  4 +--
 llvm/test/CodeGen/X86/abdu.ll                 | 30 +++++++++++++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 5fd1b10d97f35..67e16dcb41c7f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -12126,8 +12126,8 @@ SDValue DAGCombiner::foldABSToABD(SDNode *N, const SDLoc &DL) {
       return CreateZextedAbd(ISD::ABDS);
 
     // fold (abs (sub x, y)) -> abdu(x, y)
-    bool Op1SignBitIsOne = DAG.computeKnownBits(Op1).isNegative();
-    bool AbsOpWillNUW = !IsAdd && DAG.SignBitIsZero(Op0) && Op1SignBitIsOne;
+    bool AbsOpWillNUW =
+        !IsAdd && DAG.SignBitIsZero(Op0) && DAG.SignBitIsZero(Op1);
 
     if (hasOperation(ISD::ABDU, VT) && AbsOpWillNUW)
       return CreateZextedAbd(ISD::ABDU);
diff --git a/llvm/test/CodeGen/X86/abdu.ll b/llvm/test/CodeGen/X86/abdu.ll
index b8bc3649773f2..520a6917aff53 100644
--- a/llvm/test/CodeGen/X86/abdu.ll
+++ b/llvm/test/CodeGen/X86/abdu.ll
@@ -949,6 +949,36 @@ define i128 @abd_select_i128(i128 %a, i128 %b) nounwind {
   ret i128 %sub
 }
 
+define i32 @abs_sub_abdu_sign_check(i32 %p0) {
+; X86-LABEL: abs_sub_abdu_sign_check:
+; X86:       # %bb.0: # %entry
+; X86-NEXT:    cmpl $0, {{[0-9]+}}(%esp)
+; X86-NEXT:    movl $1000000000, %eax # imm = 0x3B9ACA00
+; X86-NEXT:    movl $-2039640824, %ecx # imm = 0x866D8D08
+; X86-NEXT:    cmovel %eax, %ecx
+; X86-NEXT:    movl %ecx, %eax
+; X86-NEXT:    negl %eax
+; X86-NEXT:    cmovsl %ecx, %eax
+; X86-NEXT:    retl
+;
+; X64-LABEL: abs_sub_abdu_sign_check:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    testl %edi, %edi
+; X64-NEXT:    movl $1000000000, %eax # imm = 0x3B9ACA00
+; X64-NEXT:    movl $-2039640824, %ecx # imm = 0x866D8D08
+; X64-NEXT:    cmovel %eax, %ecx
+; X64-NEXT:    movl %ecx, %eax
+; X64-NEXT:    negl %eax
+; X64-NEXT:    cmovsl %ecx, %eax
+; X64-NEXT:    retq
+entry:
+  %cmp = icmp eq i32 %p0, 0
+  %v = select i1 %cmp, i32 0, i32 1255326472
+  %s = sub i32 %v, -1000000000
+  %a = call i32 @llvm.abs.i32(i32 %s, i1 false)
+  ret i32 %a
+}
+
 declare i8 @llvm.abs.i8(i8, i1)
 declare i16 @llvm.abs.i16(i16, i1)
 declare i32 @llvm.abs.i32(i32, i1)



More information about the llvm-branch-commits mailing list