[llvm] [SDAG] Combine select into ABD?, for const (PR #173581)

via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 25 14:02:37 PST 2025


https://github.com/DaKnig created https://github.com/llvm/llvm-project/pull/173581

(select (setcc ...) (sub a, b) (sub b, a))

When b is const, the `sub a, b` becomes `add a, -b` which we take care
of in this patch


>From 3d9e0c66c36ae4bc0854b10e2079261a10d1566c Mon Sep 17 00:00:00 2001
From: DaKnig <37626476+DaKnig at users.noreply.github.com>
Date: Thu, 25 Dec 2025 23:59:54 +0200
Subject: [PATCH 1/3] [SDAG] ABD? from select const

(select (setcc ...) (sub a, b) (sub b, a))

When b is const, the `sub a, b` becomes `add a, -b` which we take care
of in this patch

>From b3c14f1b0fb1615baaf7d23039c8f5ec6d8f7ab3 Mon Sep 17 00:00:00 2001
From: DaKnig <37626476+DaKnig at users.noreply.github.com>
Date: Fri, 26 Dec 2025 00:00:11 +0200
Subject: [PATCH 2/3] New test

---
 llvm/test/CodeGen/AArch64/arm64-vabs.ll | 115 ++++++++++++++++++++++++
 1 file changed, 115 insertions(+)

diff --git a/llvm/test/CodeGen/AArch64/arm64-vabs.ll b/llvm/test/CodeGen/AArch64/arm64-vabs.ll
index 4d5542ab2d2e6..ace22b5e5b527 100644
--- a/llvm/test/CodeGen/AArch64/arm64-vabs.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-vabs.ll
@@ -2019,6 +2019,121 @@ define <16 x i16> @uabd16b_i16(<16 x i8> %a, <16 x i8> %b) {
   ret <16 x i16> %absel
 }
 
+
+define <16 x i16> @uabd16b_i16_const_select(<16 x i8> %a) {
+; CHECK-SD-LABEL: uabd16b_i16_const_select:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    adrp x8, .LCPI106_1
+; CHECK-SD-NEXT:    ushll2.8h v4, v0, #0
+; CHECK-SD-NEXT:    ushll.8h v2, v0, #0
+; CHECK-SD-NEXT:    ldr q1, [x8, :lo12:.LCPI106_1]
+; CHECK-SD-NEXT:    adrp x8, .LCPI106_2
+; CHECK-SD-NEXT:    ldr q3, [x8, :lo12:.LCPI106_2]
+; CHECK-SD-NEXT:    adrp x8, .LCPI106_3
+; CHECK-SD-NEXT:    ldr q5, [x8, :lo12:.LCPI106_3]
+; CHECK-SD-NEXT:    adrp x8, .LCPI106_0
+; CHECK-SD-NEXT:    cmhi.8h v2, v1, v2
+; CHECK-SD-NEXT:    ldr q6, [x8, :lo12:.LCPI106_0]
+; CHECK-SD-NEXT:    uaddw2.8h v3, v3, v0
+; CHECK-SD-NEXT:    usubw.8h v7, v1, v0
+; CHECK-SD-NEXT:    uaddw.8h v5, v5, v0
+; CHECK-SD-NEXT:    cmhi.8h v4, v6, v4
+; CHECK-SD-NEXT:    usubw2.8h v0, v6, v0
+; CHECK-SD-NEXT:    mov.16b v1, v4
+; CHECK-SD-NEXT:    bsl.16b v1, v0, v3
+; CHECK-SD-NEXT:    mov.16b v0, v2
+; CHECK-SD-NEXT:    bsl.16b v0, v7, v5
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: uabd16b_i16_const_select:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI106_1
+; CHECK-GI-NEXT:    mov d3, v0[1]
+; CHECK-GI-NEXT:    ushll.8h v4, v0, #0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI106_1]
+; CHECK-GI-NEXT:    adrp x8, .LCPI106_0
+; CHECK-GI-NEXT:    ushll2.8h v6, v0, #0
+; CHECK-GI-NEXT:    ldr d2, [x8, :lo12:.LCPI106_0]
+; CHECK-GI-NEXT:    ushll.8h v5, v1, #0
+; CHECK-GI-NEXT:    usubl.8h v16, v0, v1
+; CHECK-GI-NEXT:    usubl.8h v1, v1, v0
+; CHECK-GI-NEXT:    ushll.8h v7, v2, #0
+; CHECK-GI-NEXT:    usubl.8h v2, v3, v2
+; CHECK-GI-NEXT:    cmhi.8h v3, v5, v4
+; CHECK-GI-NEXT:    cmhi.8h v4, v7, v6
+; CHECK-GI-NEXT:    usubw2.8h v5, v7, v0
+; CHECK-GI-NEXT:    mov.16b v0, v3
+; CHECK-GI-NEXT:    bsl.16b v0, v1, v16
+; CHECK-GI-NEXT:    mov.16b v1, v4
+; CHECK-GI-NEXT:    bsl.16b v1, v5, v2
+; CHECK-GI-NEXT:    ret
+  %aext = zext <16 x i8> %a to <16 x i16>
+  %bext = zext <16 x i8> <i8 39, i8 42, i8 51, i8 51, i8 0, i8 0, i8 54, i8 57, i8 66, i8 69, i8 75, i8 69, i8 75, i8 81, i8 255, i8 99> to <16 x i16>
+  %neg.bext = sub <16 x i16> splat (i16 0), %bext
+  %abdiff = add nsw <16 x i16> %aext, %neg.bext
+  %abcmp = icmp ult <16 x i16> %aext, %bext
+  %ababs = sub nsw <16 x i16> %bext, %aext
+  %absel = select <16 x i1> %abcmp, <16 x i16> %ababs, <16 x i16> %abdiff
+  ret <16 x i16> %absel
+}
+
+define <16 x i16> @sabd16b_i16_const_select(<16 x i8> %a) {
+; CHECK-SD-LABEL: sabd16b_i16_const_select:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    adrp x8, .LCPI107_1
+; CHECK-SD-NEXT:    sshll2.8h v4, v0, #0
+; CHECK-SD-NEXT:    sshll.8h v2, v0, #0
+; CHECK-SD-NEXT:    ldr q1, [x8, :lo12:.LCPI107_1]
+; CHECK-SD-NEXT:    adrp x8, .LCPI107_2
+; CHECK-SD-NEXT:    ldr q3, [x8, :lo12:.LCPI107_2]
+; CHECK-SD-NEXT:    adrp x8, .LCPI107_3
+; CHECK-SD-NEXT:    ldr q5, [x8, :lo12:.LCPI107_3]
+; CHECK-SD-NEXT:    adrp x8, .LCPI107_0
+; CHECK-SD-NEXT:    cmgt.8h v2, v1, v2
+; CHECK-SD-NEXT:    ldr q6, [x8, :lo12:.LCPI107_0]
+; CHECK-SD-NEXT:    saddw2.8h v3, v3, v0
+; CHECK-SD-NEXT:    ssubw.8h v7, v1, v0
+; CHECK-SD-NEXT:    saddw.8h v5, v5, v0
+; CHECK-SD-NEXT:    cmgt.8h v4, v6, v4
+; CHECK-SD-NEXT:    ssubw2.8h v0, v6, v0
+; CHECK-SD-NEXT:    mov.16b v1, v4
+; CHECK-SD-NEXT:    bsl.16b v1, v0, v3
+; CHECK-SD-NEXT:    mov.16b v0, v2
+; CHECK-SD-NEXT:    bsl.16b v0, v7, v5
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: sabd16b_i16_const_select:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI107_1
+; CHECK-GI-NEXT:    mov d3, v0[1]
+; CHECK-GI-NEXT:    sshll.8h v4, v0, #0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI107_1]
+; CHECK-GI-NEXT:    adrp x8, .LCPI107_0
+; CHECK-GI-NEXT:    sshll2.8h v6, v0, #0
+; CHECK-GI-NEXT:    ldr d2, [x8, :lo12:.LCPI107_0]
+; CHECK-GI-NEXT:    sshll.8h v5, v1, #0
+; CHECK-GI-NEXT:    ssubl.8h v16, v0, v1
+; CHECK-GI-NEXT:    ssubl.8h v1, v1, v0
+; CHECK-GI-NEXT:    sshll.8h v7, v2, #0
+; CHECK-GI-NEXT:    ssubl.8h v2, v3, v2
+; CHECK-GI-NEXT:    cmgt.8h v3, v5, v4
+; CHECK-GI-NEXT:    cmgt.8h v4, v7, v6
+; CHECK-GI-NEXT:    ssubw2.8h v5, v7, v0
+; CHECK-GI-NEXT:    mov.16b v0, v3
+; CHECK-GI-NEXT:    bsl.16b v0, v1, v16
+; CHECK-GI-NEXT:    mov.16b v1, v4
+; CHECK-GI-NEXT:    bsl.16b v1, v5, v2
+; CHECK-GI-NEXT:    ret
+  %aext = sext <16 x i8> %a to <16 x i16>
+  %bext = sext <16 x i8> <i8 -39, i8 42, i8 -51, i8 51, i8 0, i8 0, i8 -54, i8 57, i8 -66, i8 69, i8 75, i8 69, i8 75, i8 81, i8 -128, i8 99> to <16 x i16>
+  %neg.bext = sub <16 x i16> splat (i16 0), %bext
+  %abdiff = add nsw <16 x i16> %aext, %neg.bext
+  %abcmp = icmp slt <16 x i16> %aext, %bext
+  %ababs = sub nsw <16 x i16> %bext, %aext
+  %absel = select <16 x i1> %abcmp, <16 x i16> %ababs, <16 x i16> %abdiff
+  ret <16 x i16> %absel
+}
+
 define <16 x i16> @sabd16b_i16_ext(<16 x i16> %aext, <16 x i8> %b) {
 ; CHECK-SD-LABEL: sabd16b_i16_ext:
 ; CHECK-SD:       // %bb.0:

>From 94a355d4573208b6fbd14b440638fa153099fb66 Mon Sep 17 00:00:00 2001
From: DaKnig <37626476+DaKnig at users.noreply.github.com>
Date: Fri, 26 Dec 2025 00:00:18 +0200
Subject: [PATCH 3/3] pattern

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 30 ++++++++---
 llvm/test/CodeGen/AArch64/arm64-vabs.ll       | 52 +++++--------------
 2 files changed, 36 insertions(+), 46 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index ff1e8af8b6c2e..ff56b534b3630 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -12360,17 +12360,27 @@ SDValue DAGCombiner::foldSelectToABD(SDValue LHS, SDValue RHS, SDValue True,
 
   if (LegalOperations && !hasOperation(ABDOpc, VT))
     return SDValue();
+  if (!VT.isInteger())
+    return SDValue();
+
+  // Hack to support constants. (sub a, const) becomes (add a, -const)
+  SDValue NegRHS = DAG.getNegative(RHS, SDLoc(RHS), VT),
+          NegLHS = DAG.getNegative(LHS, SDLoc(LHS), VT);
 
   switch (CC) {
   case ISD::SETGT:
   case ISD::SETGE:
   case ISD::SETUGT:
   case ISD::SETUGE:
-    if (sd_match(True, m_Sub(m_Specific(LHS), m_Specific(RHS))) &&
-        sd_match(False, m_Sub(m_Specific(RHS), m_Specific(LHS))))
+    if (sd_match(True, m_AnyOf(m_Sub(m_Specific(LHS), m_Specific(RHS)),
+                               m_Add(m_Specific(LHS), m_Specific(NegRHS)))) &&
+        sd_match(False, m_AnyOf(m_Sub(m_Specific(RHS), m_Specific(LHS)),
+                                m_Add(m_Specific(RHS), m_Specific(NegLHS)))))
       return DAG.getNode(ABDOpc, DL, VT, LHS, RHS);
-    if (sd_match(True, m_Sub(m_Specific(RHS), m_Specific(LHS))) &&
-        sd_match(False, m_Sub(m_Specific(LHS), m_Specific(RHS))) &&
+    if (sd_match(True, m_AnyOf(m_Sub(m_Specific(RHS), m_Specific(LHS)),
+                               m_Add(m_Specific(RHS), m_Specific(NegLHS)))) &&
+        sd_match(False, m_AnyOf(m_Sub(m_Specific(LHS), m_Specific(RHS)),
+                                m_Add(m_Specific(LHS), m_Specific(NegRHS)))) &&
         hasOperation(ABDOpc, VT))
       return DAG.getNegative(DAG.getNode(ABDOpc, DL, VT, LHS, RHS), DL, VT);
     break;
@@ -12378,11 +12388,15 @@ SDValue DAGCombiner::foldSelectToABD(SDValue LHS, SDValue RHS, SDValue True,
   case ISD::SETLE:
   case ISD::SETULT:
   case ISD::SETULE:
-    if (sd_match(True, m_Sub(m_Specific(RHS), m_Specific(LHS))) &&
-        sd_match(False, m_Sub(m_Specific(LHS), m_Specific(RHS))))
+    if (sd_match(True, m_AnyOf(m_Sub(m_Specific(RHS), m_Specific(LHS)),
+                               m_Add(m_Specific(RHS), m_Specific(NegLHS)))) &&
+        sd_match(False, m_AnyOf(m_Sub(m_Specific(LHS), m_Specific(RHS)),
+                                m_Add(m_Specific(LHS), m_Specific(NegRHS)))))
       return DAG.getNode(ABDOpc, DL, VT, LHS, RHS);
-    if (sd_match(True, m_Sub(m_Specific(LHS), m_Specific(RHS))) &&
-        sd_match(False, m_Sub(m_Specific(RHS), m_Specific(LHS))) &&
+    if (sd_match(True, m_AnyOf(m_Sub(m_Specific(LHS), m_Specific(RHS)),
+                               m_Add(m_Specific(LHS), m_Specific(NegRHS)))) &&
+        sd_match(False, m_AnyOf(m_Sub(m_Specific(RHS), m_Specific(LHS)),
+                                m_Add(m_Specific(RHS), m_Specific(NegLHS)))) &&
         hasOperation(ABDOpc, VT))
       return DAG.getNegative(DAG.getNode(ABDOpc, DL, VT, LHS, RHS), DL, VT);
     break;
diff --git a/llvm/test/CodeGen/AArch64/arm64-vabs.ll b/llvm/test/CodeGen/AArch64/arm64-vabs.ll
index ace22b5e5b527..3271b2f49cbbf 100644
--- a/llvm/test/CodeGen/AArch64/arm64-vabs.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-vabs.ll
@@ -2023,26 +2023,14 @@ define <16 x i16> @uabd16b_i16(<16 x i8> %a, <16 x i8> %b) {
 define <16 x i16> @uabd16b_i16_const_select(<16 x i8> %a) {
 ; CHECK-SD-LABEL: uabd16b_i16_const_select:
 ; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    adrp x8, .LCPI106_1
-; CHECK-SD-NEXT:    ushll2.8h v4, v0, #0
-; CHECK-SD-NEXT:    ushll.8h v2, v0, #0
-; CHECK-SD-NEXT:    ldr q1, [x8, :lo12:.LCPI106_1]
-; CHECK-SD-NEXT:    adrp x8, .LCPI106_2
-; CHECK-SD-NEXT:    ldr q3, [x8, :lo12:.LCPI106_2]
-; CHECK-SD-NEXT:    adrp x8, .LCPI106_3
-; CHECK-SD-NEXT:    ldr q5, [x8, :lo12:.LCPI106_3]
 ; CHECK-SD-NEXT:    adrp x8, .LCPI106_0
-; CHECK-SD-NEXT:    cmhi.8h v2, v1, v2
-; CHECK-SD-NEXT:    ldr q6, [x8, :lo12:.LCPI106_0]
-; CHECK-SD-NEXT:    uaddw2.8h v3, v3, v0
-; CHECK-SD-NEXT:    usubw.8h v7, v1, v0
-; CHECK-SD-NEXT:    uaddw.8h v5, v5, v0
-; CHECK-SD-NEXT:    cmhi.8h v4, v6, v4
-; CHECK-SD-NEXT:    usubw2.8h v0, v6, v0
-; CHECK-SD-NEXT:    mov.16b v1, v4
-; CHECK-SD-NEXT:    bsl.16b v1, v0, v3
-; CHECK-SD-NEXT:    mov.16b v0, v2
-; CHECK-SD-NEXT:    bsl.16b v0, v7, v5
+; CHECK-SD-NEXT:    ushll.8h v2, v0, #0
+; CHECK-SD-NEXT:    ushll2.8h v0, v0, #0
+; CHECK-SD-NEXT:    adrp x9, .LCPI106_1
+; CHECK-SD-NEXT:    ldr q3, [x8, :lo12:.LCPI106_0]
+; CHECK-SD-NEXT:    ldr q1, [x9, :lo12:.LCPI106_1]
+; CHECK-SD-NEXT:    uabd.8h v1, v0, v1
+; CHECK-SD-NEXT:    uabd.8h v0, v2, v3
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: uabd16b_i16_const_select:
@@ -2080,26 +2068,14 @@ define <16 x i16> @uabd16b_i16_const_select(<16 x i8> %a) {
 define <16 x i16> @sabd16b_i16_const_select(<16 x i8> %a) {
 ; CHECK-SD-LABEL: sabd16b_i16_const_select:
 ; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    adrp x8, .LCPI107_1
-; CHECK-SD-NEXT:    sshll2.8h v4, v0, #0
-; CHECK-SD-NEXT:    sshll.8h v2, v0, #0
-; CHECK-SD-NEXT:    ldr q1, [x8, :lo12:.LCPI107_1]
-; CHECK-SD-NEXT:    adrp x8, .LCPI107_2
-; CHECK-SD-NEXT:    ldr q3, [x8, :lo12:.LCPI107_2]
-; CHECK-SD-NEXT:    adrp x8, .LCPI107_3
-; CHECK-SD-NEXT:    ldr q5, [x8, :lo12:.LCPI107_3]
 ; CHECK-SD-NEXT:    adrp x8, .LCPI107_0
-; CHECK-SD-NEXT:    cmgt.8h v2, v1, v2
-; CHECK-SD-NEXT:    ldr q6, [x8, :lo12:.LCPI107_0]
-; CHECK-SD-NEXT:    saddw2.8h v3, v3, v0
-; CHECK-SD-NEXT:    ssubw.8h v7, v1, v0
-; CHECK-SD-NEXT:    saddw.8h v5, v5, v0
-; CHECK-SD-NEXT:    cmgt.8h v4, v6, v4
-; CHECK-SD-NEXT:    ssubw2.8h v0, v6, v0
-; CHECK-SD-NEXT:    mov.16b v1, v4
-; CHECK-SD-NEXT:    bsl.16b v1, v0, v3
-; CHECK-SD-NEXT:    mov.16b v0, v2
-; CHECK-SD-NEXT:    bsl.16b v0, v7, v5
+; CHECK-SD-NEXT:    sshll.8h v2, v0, #0
+; CHECK-SD-NEXT:    sshll2.8h v0, v0, #0
+; CHECK-SD-NEXT:    adrp x9, .LCPI107_1
+; CHECK-SD-NEXT:    ldr q3, [x8, :lo12:.LCPI107_0]
+; CHECK-SD-NEXT:    ldr q1, [x9, :lo12:.LCPI107_1]
+; CHECK-SD-NEXT:    sabd.8h v1, v0, v1
+; CHECK-SD-NEXT:    sabd.8h v0, v2, v3
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: sabd16b_i16_const_select:



More information about the llvm-commits mailing list