[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