[llvm] [SDAG] Allow S/Zext in select-abd pattern (PR #191207)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 6 04:48:43 PDT 2026
https://github.com/DaKnig updated https://github.com/llvm/llvm-project/pull/191207
>From 126fe8bbf1720d850efb8edc84cc8dadc5e35a9b Mon Sep 17 00:00:00 2001
From: DaKnig <ZannyKnig at disroot.org>
Date: Thu, 9 Apr 2026 17:39:02 +0300
Subject: [PATCH 1/3] [SDAG] Allow S/Zext in select-abd pattern
(select (setcc a, b, s??), (sub (*sext* a), (*sext* b)),
(sub (*sext* b), (*sext* a)))
Into: (zext (abds a, b))
>From 141310a106581561fd3ea0b683f793b141622db5 Mon Sep 17 00:00:00 2001
From: DaKnig <ZannyKnig at disroot.org>
Date: Thu, 9 Apr 2026 17:39:28 +0300
Subject: [PATCH 2/3] lit
---
llvm/test/CodeGen/AArch64/abd-combine.ll | 79 ++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/llvm/test/CodeGen/AArch64/abd-combine.ll b/llvm/test/CodeGen/AArch64/abd-combine.ll
index 8ceac6b69865a..f5f133c6d0a2c 100644
--- a/llvm/test/CodeGen/AArch64/abd-combine.ll
+++ b/llvm/test/CodeGen/AArch64/abd-combine.ll
@@ -538,6 +538,85 @@ define <4 x i32> @abdu_const_poison(<4 x i8> %x) {
ret <4 x i32> %abs
}
+define <4 x i32> @abd_select_sext(<4 x i16> %a, <4 x i16> %b) {
+; CHECK-LABEL: abd_select_sext:
+; CHECK: // %bb.0:
+; CHECK-NEXT: cmgt v2.4h, v1.4h, v0.4h
+; CHECK-NEXT: ssubl v3.4s, v0.4h, v1.4h
+; CHECK-NEXT: ssubl v0.4s, v1.4h, v0.4h
+; CHECK-NEXT: sshll v2.4s, v2.4h, #0
+; CHECK-NEXT: bif v0.16b, v3.16b, v2.16b
+; CHECK-NEXT: ret
+ %conv = sext <4 x i16> %a to <4 x i32>
+ %conv1 = sext <4 x i16> %b to <4 x i32>
+ %sub.i = sub nsw <4 x i32> %conv, %conv1
+ %cmp.i = icmp sgt <4 x i16> %b, %a
+ %sub1.i = sub nsw <4 x i32> %conv1, %conv
+ %spec.select.i = select <4 x i1> %cmp.i, <4 x i32> %sub1.i, <4 x i32> %sub.i
+ ret <4 x i32> %spec.select.i
+}
+
+define <4 x i32> @abd_select_sext_add(<4 x i16> %a, <4 x i16> %b) {
+; CHECK-LABEL: abd_select_sext_add:
+; CHECK: // %bb.0:
+; CHECK-NEXT: cmgt v3.4h, v1.4h, v0.4h
+; CHECK-NEXT: ssubl v4.4s, v0.4h, v1.4h
+; CHECK-NEXT: ssubl v0.4s, v1.4h, v0.4h
+; CHECK-NEXT: movi v2.4s, #19
+; CHECK-NEXT: sshll v3.4s, v3.4h, #0
+; CHECK-NEXT: bif v0.16b, v4.16b, v3.16b
+; CHECK-NEXT: add v0.4s, v0.4s, v2.4s
+; CHECK-NEXT: ret
+ %conv = sext <4 x i16> %a to <4 x i32>
+ %conv1 = sext <4 x i16> %b to <4 x i32>
+ %sub.i = sub nsw <4 x i32> %conv, %conv1
+ %cmp.i = icmp sgt <4 x i16> %b, %a
+ %sub1.i = sub nsw <4 x i32> %conv1, %conv
+ %spec.select.i = select <4 x i1> %cmp.i, <4 x i32> %sub1.i, <4 x i32> %sub.i
+ %add = add nsw <4 x i32> %spec.select.i, splat (i32 19)
+ ret <4 x i32> %add
+}
+
+define <4 x i32> @abd_select_zext_add(<4 x i16> %a, <4 x i16> %b) {
+; CHECK-LABEL: abd_select_zext_add:
+; CHECK: // %bb.0:
+; CHECK-NEXT: cmhi v3.4h, v1.4h, v0.4h
+; CHECK-NEXT: usubl v4.4s, v0.4h, v1.4h
+; CHECK-NEXT: usubl v0.4s, v1.4h, v0.4h
+; CHECK-NEXT: movi v2.4s, #19
+; CHECK-NEXT: sshll v3.4s, v3.4h, #0
+; CHECK-NEXT: bif v0.16b, v4.16b, v3.16b
+; CHECK-NEXT: add v0.4s, v0.4s, v2.4s
+; CHECK-NEXT: ret
+ %conv = zext <4 x i16> %a to <4 x i32>
+ %conv1 = zext <4 x i16> %b to <4 x i32>
+ %sub.i = sub nsw <4 x i32> %conv, %conv1
+ %cmp.i = icmp ugt <4 x i16> %b, %a
+ %sub1.i = sub nsw <4 x i32> %conv1, %conv
+ %spec.select.i = select <4 x i1> %cmp.i, <4 x i32> %sub1.i, <4 x i32> %sub.i
+ %add = add nsw <4 x i32> %spec.select.i, splat (i32 19)
+ ret <4 x i32> %add
+}
+
+define <4 x i32> @neg_abd_select_sext(<4 x i16> %a, <4 x i16> %b) {
+; CHECK-LABEL: neg_abd_select_sext:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: cmgt v2.4h, v1.4h, v0.4h
+; CHECK-NEXT: ssubl v3.4s, v0.4h, v1.4h
+; CHECK-NEXT: ssubl v0.4s, v1.4h, v0.4h
+; CHECK-NEXT: sshll v2.4s, v2.4h, #0
+; CHECK-NEXT: bit v0.16b, v3.16b, v2.16b
+; CHECK-NEXT: ret
+entry:
+ %conv = sext <4 x i16> %a to <4 x i32>
+ %conv1 = sext <4 x i16> %b to <4 x i32>
+ %cmp = icmp slt <4 x i16> %a, %b
+ %sub = sub nsw <4 x i32> %conv, %conv1
+ %sub7 = sub nsw <4 x i32> %conv1, %conv
+ %cond = select <4 x i1> %cmp, <4 x i32> %sub, <4 x i32> %sub7
+ ret <4 x i32> %cond
+}
+
declare <8 x i8> @llvm.aarch64.neon.umax.v8i8(<8 x i8>, <8 x i8>)
declare <1 x i64> @llvm.aarch64.neon.saddlp.v1i64.v2i32(<2 x i32>)
declare <8 x i8> @llvm.aarch64.neon.uabd.v8i8(<8 x i8>, <8 x i8>)
>From f4067e863a284a6fc58d9a8dc8b8b1421742969f Mon Sep 17 00:00:00 2001
From: DaKnig <ZannyKnig at disroot.org>
Date: Thu, 9 Apr 2026 18:02:22 +0300
Subject: [PATCH 3/3] code
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 38 ++++++++++++-------
llvm/test/CodeGen/AArch64/abd-combine.ll | 29 ++++----------
2 files changed, 31 insertions(+), 36 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 48f6a5feef2b3..d6874d78cf609 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -13236,9 +13236,10 @@ SDValue DAGCombiner::foldSelectToABD(SDValue LHS, SDValue RHS, SDValue True,
const SDLoc &DL) {
bool IsSigned = isSignedIntSetCC(CC);
unsigned ABDOpc = IsSigned ? ISD::ABDS : ISD::ABDU;
- EVT VT = LHS.getValueType();
+ EVT VT = True.getValueType();
+ EVT AbdVT = LHS.getValueType();
- if (LegalOperations && !hasOperation(ABDOpc, VT))
+ if (LegalOperations && !hasOperation(ABDOpc, AbdVT))
return SDValue();
// (setcc 0, b set???) --> (setcc b, 0, set???)
@@ -13260,38 +13261,47 @@ SDValue DAGCombiner::foldSelectToABD(SDValue LHS, SDValue RHS, SDValue True,
TLI.isTypeLegal(VT) || TLI.getTypeAction(*DAG.getContext(), VT) ==
TargetLowering::TypePromoteInteger;
+ auto LHSPat =
+ IsSigned ? m_SExtOrSelf(m_Specific(LHS)) : m_ZExtOrSelf(m_Specific(LHS));
+ auto RHSPat =
+ IsSigned ? m_SExtOrSelf(m_Specific(RHS)) : m_ZExtOrSelf(m_Specific(RHS));
+ auto GetAbdNode = [&] {
+ auto AbdNode = DAG.getNode(ABDOpc, DL, AbdVT, LHS, RHS);
+ return DAG.getZExtOrTrunc(AbdNode, DL, VT);
+ };
+
switch (CC) {
case ISD::SETGT:
case ISD::SETGE:
case ISD::SETUGT:
case ISD::SETUGE:
- if (sd_match(True, m_AnyOf(m_Sub(m_Specific(LHS), m_Specific(RHS)),
+ if (sd_match(True, m_AnyOf(m_Sub(LHSPat, RHSPat),
m_Add(m_Specific(LHS), m_SpecificNeg(RHS)))) &&
- sd_match(False, m_AnyOf(m_Sub(m_Specific(RHS), m_Specific(LHS)),
+ sd_match(False, m_AnyOf(m_Sub(RHSPat, LHSPat),
m_Add(m_Specific(RHS), m_SpecificNeg(LHS)))))
- return DAG.getNode(ABDOpc, DL, VT, LHS, RHS);
- if (sd_match(True, m_AnyOf(m_Sub(m_Specific(RHS), m_Specific(LHS)),
+ return GetAbdNode();
+ if (sd_match(True, m_AnyOf(m_Sub(RHSPat, LHSPat),
m_Add(m_Specific(RHS), m_SpecificNeg(LHS)))) &&
- sd_match(False, m_AnyOf(m_Sub(m_Specific(LHS), m_Specific(RHS)),
+ sd_match(False, m_AnyOf(m_Sub(LHSPat, RHSPat),
m_Add(m_Specific(LHS), m_SpecificNeg(RHS)))) &&
IsTypeLegalOrPromote)
- return DAG.getNegative(DAG.getNode(ABDOpc, DL, VT, LHS, RHS), DL, VT);
+ return DAG.getNegative(GetAbdNode(), DL, VT);
break;
case ISD::SETLT:
case ISD::SETLE:
case ISD::SETULT:
case ISD::SETULE:
- if (sd_match(True, m_AnyOf(m_Sub(m_Specific(RHS), m_Specific(LHS)),
+ if (sd_match(True, m_AnyOf(m_Sub(RHSPat, LHSPat),
m_Add(m_Specific(RHS), m_SpecificNeg(LHS)))) &&
- sd_match(False, m_AnyOf(m_Sub(m_Specific(LHS), m_Specific(RHS)),
+ sd_match(False, m_AnyOf(m_Sub(LHSPat, RHSPat),
m_Add(m_Specific(LHS), m_SpecificNeg(RHS)))))
- return DAG.getNode(ABDOpc, DL, VT, LHS, RHS);
- if (sd_match(True, m_AnyOf(m_Sub(m_Specific(LHS), m_Specific(RHS)),
+ return GetAbdNode();
+ if (sd_match(True, m_AnyOf(m_Sub(LHSPat, RHSPat),
m_Add(m_Specific(LHS), m_SpecificNeg(RHS)))) &&
- sd_match(False, m_AnyOf(m_Sub(m_Specific(RHS), m_Specific(LHS)),
+ sd_match(False, m_AnyOf(m_Sub(RHSPat, LHSPat),
m_Add(m_Specific(RHS), m_SpecificNeg(LHS)))) &&
IsTypeLegalOrPromote)
- return DAG.getNegative(DAG.getNode(ABDOpc, DL, VT, LHS, RHS), DL, VT);
+ return DAG.getNegative(GetAbdNode(), DL, VT);
break;
default:
break;
diff --git a/llvm/test/CodeGen/AArch64/abd-combine.ll b/llvm/test/CodeGen/AArch64/abd-combine.ll
index f5f133c6d0a2c..2fc21c1d97b31 100644
--- a/llvm/test/CodeGen/AArch64/abd-combine.ll
+++ b/llvm/test/CodeGen/AArch64/abd-combine.ll
@@ -541,11 +541,7 @@ define <4 x i32> @abdu_const_poison(<4 x i8> %x) {
define <4 x i32> @abd_select_sext(<4 x i16> %a, <4 x i16> %b) {
; CHECK-LABEL: abd_select_sext:
; CHECK: // %bb.0:
-; CHECK-NEXT: cmgt v2.4h, v1.4h, v0.4h
-; CHECK-NEXT: ssubl v3.4s, v0.4h, v1.4h
-; CHECK-NEXT: ssubl v0.4s, v1.4h, v0.4h
-; CHECK-NEXT: sshll v2.4s, v2.4h, #0
-; CHECK-NEXT: bif v0.16b, v3.16b, v2.16b
+; CHECK-NEXT: sabdl v0.4s, v1.4h, v0.4h
; CHECK-NEXT: ret
%conv = sext <4 x i16> %a to <4 x i32>
%conv1 = sext <4 x i16> %b to <4 x i32>
@@ -559,13 +555,9 @@ define <4 x i32> @abd_select_sext(<4 x i16> %a, <4 x i16> %b) {
define <4 x i32> @abd_select_sext_add(<4 x i16> %a, <4 x i16> %b) {
; CHECK-LABEL: abd_select_sext_add:
; CHECK: // %bb.0:
-; CHECK-NEXT: cmgt v3.4h, v1.4h, v0.4h
-; CHECK-NEXT: ssubl v4.4s, v0.4h, v1.4h
-; CHECK-NEXT: ssubl v0.4s, v1.4h, v0.4h
; CHECK-NEXT: movi v2.4s, #19
-; CHECK-NEXT: sshll v3.4s, v3.4h, #0
-; CHECK-NEXT: bif v0.16b, v4.16b, v3.16b
-; CHECK-NEXT: add v0.4s, v0.4s, v2.4s
+; CHECK-NEXT: sabal v2.4s, v1.4h, v0.4h
+; CHECK-NEXT: mov v0.16b, v2.16b
; CHECK-NEXT: ret
%conv = sext <4 x i16> %a to <4 x i32>
%conv1 = sext <4 x i16> %b to <4 x i32>
@@ -580,13 +572,9 @@ define <4 x i32> @abd_select_sext_add(<4 x i16> %a, <4 x i16> %b) {
define <4 x i32> @abd_select_zext_add(<4 x i16> %a, <4 x i16> %b) {
; CHECK-LABEL: abd_select_zext_add:
; CHECK: // %bb.0:
-; CHECK-NEXT: cmhi v3.4h, v1.4h, v0.4h
-; CHECK-NEXT: usubl v4.4s, v0.4h, v1.4h
-; CHECK-NEXT: usubl v0.4s, v1.4h, v0.4h
; CHECK-NEXT: movi v2.4s, #19
-; CHECK-NEXT: sshll v3.4s, v3.4h, #0
-; CHECK-NEXT: bif v0.16b, v4.16b, v3.16b
-; CHECK-NEXT: add v0.4s, v0.4s, v2.4s
+; CHECK-NEXT: uabal v2.4s, v1.4h, v0.4h
+; CHECK-NEXT: mov v0.16b, v2.16b
; CHECK-NEXT: ret
%conv = zext <4 x i16> %a to <4 x i32>
%conv1 = zext <4 x i16> %b to <4 x i32>
@@ -601,11 +589,8 @@ define <4 x i32> @abd_select_zext_add(<4 x i16> %a, <4 x i16> %b) {
define <4 x i32> @neg_abd_select_sext(<4 x i16> %a, <4 x i16> %b) {
; CHECK-LABEL: neg_abd_select_sext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: cmgt v2.4h, v1.4h, v0.4h
-; CHECK-NEXT: ssubl v3.4s, v0.4h, v1.4h
-; CHECK-NEXT: ssubl v0.4s, v1.4h, v0.4h
-; CHECK-NEXT: sshll v2.4s, v2.4h, #0
-; CHECK-NEXT: bit v0.16b, v3.16b, v2.16b
+; CHECK-NEXT: sabdl v0.4s, v0.4h, v1.4h
+; CHECK-NEXT: neg v0.4s, v0.4s
; CHECK-NEXT: ret
entry:
%conv = sext <4 x i16> %a to <4 x i32>
More information about the llvm-commits
mailing list