[llvm] [AArch64] Extend SBC combine to handle CSET HI (PR #192708)

via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 17 11:12:21 PDT 2026


https://github.com/edisongz created https://github.com/llvm/llvm-project/pull/192708

The `performSubWithBorrowCombine` previously only matched `CSET LO` (unsigned <). 
This extends it to also handle `CSET HI` (unsigned >) by swapping the `SUBS` 
operands, since `a > b` is equivalent to `b < a`.

This resolves the FIXME left in the test from #165271.

>From ef9243852d46559795249d8ca1c811490c492aba Mon Sep 17 00:00:00 2001
From: Yijie Jiang <edisongz123 at gmail.com>
Date: Sat, 18 Apr 2026 02:05:31 +0800
Subject: [PATCH] [AArch64] Extend SBC combine to handle CSET HI

The `performSubWithBorrowCombine` previously only matched `CSET LO` (unsigned <).
This extends it to also handle `CSET HI` (unsigned >) by swapping the `SUBS`
operands, since `a > b` is equivalent to `b < a`.

This resolves the FIXME left in the test from #165271.
---
 llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 12 +++++++++++-
 llvm/test/CodeGen/AArch64/sbc.ll                |  7 ++-----
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 24d5ce1b9e167..d1a82254606b8 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -23100,6 +23100,7 @@ static SDValue performExtBinopLoadFold(SDNode *N, SelectionDAG &DAG) {
 // Attempt to combine the following patterns:
 //   SUB x, (CSET LO, (CMP a, b)) -> SBC x, 0, (CMP a, b)
 //   SUB (SUB x, y), (CSET LO, (CMP a, b)) -> SBC x, y, (CMP a, b)
+// Also handles CSET HI by swapping the CMP operands (a > b ≡ b < a).
 // The CSET may be preceded by a ZEXT.
 static SDValue performSubWithBorrowCombine(SDNode *N, SelectionDAG &DAG) {
   if (N->getOpcode() != ISD::SUB)
@@ -23112,13 +23113,22 @@ static SDValue performSubWithBorrowCombine(SDNode *N, SelectionDAG &DAG) {
   SDValue N1 = N->getOperand(1);
   if (N1.getOpcode() == ISD::ZERO_EXTEND && N1.hasOneUse())
     N1 = N1.getOperand(0);
-  if (!N1.hasOneUse() || getCSETCondCode(N1) != AArch64CC::LO)
+  auto CC = getCSETCondCode(N1);
+  if (!N1.hasOneUse() || (CC != AArch64CC::LO && CC != AArch64CC::HI))
     return SDValue();
 
   SDValue Flags = N1.getOperand(3);
   if (Flags.getOpcode() != AArch64ISD::SUBS)
     return SDValue();
 
+  // For HI (unsigned >), swap the SUBS operands to obtain LO (unsigned <).
+  if (CC == AArch64CC::HI) {
+    Flags = DAG.getNode(AArch64ISD::SUBS, SDLoc(Flags),
+                        DAG.getVTList(VT, FlagsVT),
+                        Flags.getOperand(1), Flags.getOperand(0));
+    Flags = Flags.getValue(1);
+  }
+
   SDLoc DL(N);
   SDValue N0 = N->getOperand(0);
   if (N0->getOpcode() == ISD::SUB)
diff --git a/llvm/test/CodeGen/AArch64/sbc.ll b/llvm/test/CodeGen/AArch64/sbc.ll
index fff63c1709218..08f90eda41ff6 100644
--- a/llvm/test/CodeGen/AArch64/sbc.ll
+++ b/llvm/test/CodeGen/AArch64/sbc.ll
@@ -129,14 +129,11 @@ define i32 @test_sext_add(i32 %a, i32 %b, i32 %x, i32 %y) {
   ret i32 %res
 }
 
-; FIXME: This case could be supported with reversed operands to the CMP.
 define i32 @test_ugt(i32 %a, i32 %b, i32 %x, i32 %y) {
 ; CHECK-SD-LABEL: test_ugt:
 ; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    cmp w0, w1
-; CHECK-SD-NEXT:    sub w8, w2, w3
-; CHECK-SD-NEXT:    cset w9, hi
-; CHECK-SD-NEXT:    sub w0, w8, w9
+; CHECK-SD-NEXT:    cmp w1, w0
+; CHECK-SD-NEXT:    sbc w0, w2, w3
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: test_ugt:



More information about the llvm-commits mailing list