-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[DAG] Fold (umin (sub a b) a) -> (usubo a b); (select usubo.1 a usubo.0) #161651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
/cc @RKSimon |
@llvm/pr-subscribers-backend-aarch64 @llvm/pr-subscribers-backend-x86 Author: Chaitanya Koparkar (ckoparkar) ChangesFixes #161036. Full diff: https://github.com/llvm/llvm-project/pull/161651.diff 2 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 558c5a0390228..99d7000c3b62e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -6199,6 +6199,28 @@ 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_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);
+ 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..2416bcb909485
--- /dev/null
+++ b/llvm/test/CodeGen/X86/underflow-compare-fold.ll
@@ -0,0 +1,16 @@
+; 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
+; CHECK-NEXT: retq
+entry:
+ %sub = sub i64 %a, %b
+ %cond = tail call i64 @llvm.umin.i64(i64 %sub, i64 %a)
+ ret i64 %cond
+}
|
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MVT::i1 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'll always be MVT::i1 unless umin is applied to a vector? And the vector case is already handled here, so we shouldn't see a vector type after that line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add aarch64 test coverage
@RKSimon this is ready for another review. |
if (N0.getOpcode() == ISD::SUB) { | ||
SDValue A, B; | ||
if (sd_match(N, m_UMin(m_Sub(m_Value(A), m_Value(B)), m_Deferred(A)))) { | ||
if (TLI.isOperationLegalOrCustom(ISD::USUBO, VT)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worried this might break after legalize; probably should use getSetCCResultType instead of i1
SDValue A, B; | ||
if (sd_match(N, m_UMin(m_Sub(m_Value(A), m_Value(B)), m_Deferred(A)))) { | ||
if (TLI.isOperationLegalOrCustom(ISD::USUBO, VT)) { | ||
SDVTList VTs = DAG.getVTList(VT, MVT::i1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Broken for vectors?
return SD; | ||
|
||
// (umin (sub a, b) a) -> (usubo a, b); (select usubo.1, a, usubo.0) | ||
if (N0.getOpcode() == ISD::SUB) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're matching the opcode here and in the pattern, so pick one way or the other
%sub = sub i64 %a, %b | ||
%cond = tail call i64 @llvm.umin.i64(i64 %sub, i64 %a) | ||
ret i64 %cond | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test same pattern with vectors. Also add multiple use test, and illegal type
Apologies, I was traveling for a few days. I'll update this today. |
Fixes #161036.