[llvm] [DAG] Fold (umin (sub a b) a) -> (usubo a b); (select usubo.1 a usubo.0) (PR #161651)

Chaitanya Koparkar via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 2 06:28:25 PDT 2025


https://github.com/ckoparkar updated https://github.com/llvm/llvm-project/pull/161651

>From 3a24f85aebb329f3ccc7272114e61201ef4ff161 Mon Sep 17 00:00:00 2001
From: Chaitanya Koparkar <ckoparkar at gmail.com>
Date: Thu, 2 Oct 2025 07:29:30 -0400
Subject: [PATCH 1/3] [DAG] Fold (umin (sub a b) a) -> (usubo a b); (select
 usubo.1 a usubo.0)

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 24 +++++++++++++++
 .../CodeGen/X86/underflow-compare-fold.ll     | 29 +++++++++++++++++++
 2 files changed, 53 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/underflow-compare-fold.ll

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 558c5a0390228..c188ab49f2821 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -6199,6 +6199,30 @@ SDValue DAGCombiner::visitIMINMAX(SDNode *N) {
                                         SDLoc(N), VT, N0, N1))
     return SD;
 
+  // (umin (sub a, b) a) -> (usubo a, b); (select usubo.1, a, usubo.0)
+  //
+  // IR:
+  //   %sub  = sub %a, %b
+  //   %cond = umin %sub, %a
+  //   ->
+  //   %usubo    = usubo %a, %b
+  //   %overflow = extractvalue %usubo, 1
+  //   %sub      = extractvalue %usubo, 0
+  //   %cond     = select %overflow, %a, %sub
+  if (N0.getOpcode() == ISD::SUB) {
+    SDValue A, B, C;
+    if (sd_match(N,
+                 m_AnyOf(m_UMin(m_Sub(m_Value(A), m_Value(B)), m_Value(C)),
+                         m_SMin(m_Sub(m_Value(A), m_Value(B)), m_Value(C))))) {
+      EVT AVT = A.getValueType();
+      if (A == C && TLI.isOperationLegalOrCustom(ISD::USUBO, AVT)) {
+        SDVTList VTs = DAG.getVTList(AVT, MVT::i1);
+        SDValue USO = DAG.getNode(ISD::USUBO, DL, VTs, A, B);
+        return DAG.getSelect(DL, VT, USO.getValue(1), A, USO.getValue(0));
+      }
+    }
+  }
+
   // Simplify the operands using demanded-bits information.
   if (SimplifyDemandedBits(SDValue(N, 0)))
     return SDValue(N, 0);
diff --git a/llvm/test/CodeGen/X86/underflow-compare-fold.ll b/llvm/test/CodeGen/X86/underflow-compare-fold.ll
new file mode 100644
index 0000000000000..1d1cfa4f97c50
--- /dev/null
+++ b/llvm/test/CodeGen/X86/underflow-compare-fold.ll
@@ -0,0 +1,29 @@
+; RUN: llc < %s -mtriple=x86_64 | FileCheck %s
+
+; GitHub issue #161036
+
+define i64 @subIfNoUnderflow_umin(i64 %a, i64 %b) {
+; CHECK-LABEL: subIfNoUnderflow_umin
+; CHECK-LABEL: %bb.0
+; CHECK-NEXT: movq    %rdi, %rax
+; CHECK-NEXT: subq    %rsi, %rax
+; CHECK-NEXT: cmovbq  %rdi, %rax
+; retq
+entry:
+  %sub = sub i64 %a, %b
+  %cond = tail call i64 @llvm.umin.i64(i64 %sub, i64 %a)
+  ret i64 %cond
+}
+
+define i64 @subIfNoUnderflow_smin(i64 %a, i64 %b) {
+; CHECK-LABEL: subIfNoUnderflow_smin
+; CHECK-LABEL: %bb.0
+; CHECK-NEXT: movq    %rdi, %rax
+; CHECK-NEXT: subq    %rsi, %rax
+; CHECK-NEXT: cmovbq  %rdi, %rax
+; retq
+entry:
+  %sub = sub i64 %a, %b
+  %cond = tail call i64 @llvm.smin.i64(i64 %sub, i64 %a)
+  ret i64 %cond
+}

>From 0db4bf0442f37a26a577b974d69962332e19d378 Mon Sep 17 00:00:00 2001
From: Chaitanya Koparkar <ckoparkar at gmail.com>
Date: Thu, 2 Oct 2025 08:30:36 -0400
Subject: [PATCH 2/3] Remove smin pattern, it might not be correct

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp   |  4 +---
 llvm/test/CodeGen/X86/underflow-compare-fold.ll | 13 -------------
 2 files changed, 1 insertion(+), 16 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index c188ab49f2821..99d7000c3b62e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -6211,9 +6211,7 @@ SDValue DAGCombiner::visitIMINMAX(SDNode *N) {
   //   %cond     = select %overflow, %a, %sub
   if (N0.getOpcode() == ISD::SUB) {
     SDValue A, B, C;
-    if (sd_match(N,
-                 m_AnyOf(m_UMin(m_Sub(m_Value(A), m_Value(B)), m_Value(C)),
-                         m_SMin(m_Sub(m_Value(A), m_Value(B)), m_Value(C))))) {
+    if (sd_match(N, m_UMin(m_Sub(m_Value(A), m_Value(B)), m_Value(C)))) {
       EVT AVT = A.getValueType();
       if (A == C && TLI.isOperationLegalOrCustom(ISD::USUBO, AVT)) {
         SDVTList VTs = DAG.getVTList(AVT, MVT::i1);
diff --git a/llvm/test/CodeGen/X86/underflow-compare-fold.ll b/llvm/test/CodeGen/X86/underflow-compare-fold.ll
index 1d1cfa4f97c50..4dcaefc7a5586 100644
--- a/llvm/test/CodeGen/X86/underflow-compare-fold.ll
+++ b/llvm/test/CodeGen/X86/underflow-compare-fold.ll
@@ -14,16 +14,3 @@ entry:
   %cond = tail call i64 @llvm.umin.i64(i64 %sub, i64 %a)
   ret i64 %cond
 }
-
-define i64 @subIfNoUnderflow_smin(i64 %a, i64 %b) {
-; CHECK-LABEL: subIfNoUnderflow_smin
-; CHECK-LABEL: %bb.0
-; CHECK-NEXT: movq    %rdi, %rax
-; CHECK-NEXT: subq    %rsi, %rax
-; CHECK-NEXT: cmovbq  %rdi, %rax
-; retq
-entry:
-  %sub = sub i64 %a, %b
-  %cond = tail call i64 @llvm.smin.i64(i64 %sub, i64 %a)
-  ret i64 %cond
-}

>From c0ba3fd77bd8e7d8e3ce7fbe09cb50a6e211e0d7 Mon Sep 17 00:00:00 2001
From: Chaitanya Koparkar <ckoparkar at gmail.com>
Date: Thu, 2 Oct 2025 09:28:15 -0400
Subject: [PATCH 3/3] Fix check for retq

---
 llvm/test/CodeGen/X86/underflow-compare-fold.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/X86/underflow-compare-fold.ll b/llvm/test/CodeGen/X86/underflow-compare-fold.ll
index 4dcaefc7a5586..2416bcb909485 100644
--- a/llvm/test/CodeGen/X86/underflow-compare-fold.ll
+++ b/llvm/test/CodeGen/X86/underflow-compare-fold.ll
@@ -8,7 +8,7 @@ define i64 @subIfNoUnderflow_umin(i64 %a, i64 %b) {
 ; CHECK-NEXT: movq    %rdi, %rax
 ; CHECK-NEXT: subq    %rsi, %rax
 ; CHECK-NEXT: cmovbq  %rdi, %rax
-; retq
+; CHECK-NEXT: retq
 entry:
   %sub = sub i64 %a, %b
   %cond = tail call i64 @llvm.umin.i64(i64 %sub, i64 %a)



More information about the llvm-commits mailing list