[llvm] Use umin for x != 0 when +cssc is enabled (PR #169159)

via llvm-commits llvm-commits at lists.llvm.org
Sat Nov 22 02:43:11 PST 2025


https://github.com/clingfei updated https://github.com/llvm/llvm-project/pull/169159

>From 51d75337f6dd3a008529ca306e56d6921eef0abe Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Sat, 22 Nov 2025 18:36:17 +0800
Subject: [PATCH] Use umin for x != 0 when +cssc is enabled

---
 .../Target/AArch64/AArch64ISelLowering.cpp    | 10 ++-
 .../test/CodeGen/AArch64/aarch64-isel-umin.ll | 82 +++++++++++++++++++
 llvm/test/CodeGen/AArch64/arm64-popcnt.ll     |  4 +-
 3 files changed, 92 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/aarch64-isel-umin.ll

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index ac3745ea5c274..fdea0d2dfd268 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -26375,7 +26375,8 @@ performVecReduceBitwiseCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
 
 static SDValue performSETCCCombine(SDNode *N,
                                    TargetLowering::DAGCombinerInfo &DCI,
-                                   SelectionDAG &DAG) {
+                                   SelectionDAG &DAG,
+                                   const AArch64Subtarget *Subtarget) {
   assert(N->getOpcode() == ISD::SETCC && "Unexpected opcode!");
   SDValue LHS = N->getOperand(0);
   SDValue RHS = N->getOperand(1);
@@ -26417,6 +26418,11 @@ static SDValue performSETCCCombine(SDNode *N,
       return DAG.getNode(ISD::SETCC, DL, VT, TST, RHS, N->getOperand(2));
     }
   }
+  if (Subtarget->hasCSSC() && Cond == ISD::SETNE && isNullConstant(RHS)) {
+    SDValue One = DAG.getConstant(1, DL, LHS.getValueType());
+    auto UMin = DAG.getNode(ISD::UMIN, DL, LHS.getValueType(), LHS, One);
+    return DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, UMin);
+  }
 
   // setcc (iN (bitcast (vNi1 X))), 0, (eq|ne)
   //   ==> setcc (iN (zext (i1 (vecreduce_or (vNi1 X))))), 0, (eq|ne)
@@ -28180,7 +28186,7 @@ SDValue AArch64TargetLowering::PerformDAGCombine(SDNode *N,
   case ISD::VSELECT:
     return performVSelectCombine(N, DCI.DAG);
   case ISD::SETCC:
-    return performSETCCCombine(N, DCI, DAG);
+    return performSETCCCombine(N, DCI, DAG, Subtarget);
   case ISD::LOAD:
     return performLOADCombine(N, DCI, DAG, Subtarget);
   case ISD::STORE:
diff --git a/llvm/test/CodeGen/AArch64/aarch64-isel-umin.ll b/llvm/test/CodeGen/AArch64/aarch64-isel-umin.ll
new file mode 100644
index 0000000000000..87b827aaaa3db
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/aarch64-isel-umin.ll
@@ -0,0 +1,82 @@
+; RUN: llc -mtriple=aarch64-- -o - < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64-- -mattr=+cssc -o - < %s | FileCheck %s --check-prefixes=CHECK,CHECK-CSSC
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux-gnu"
+
+; auto icmpi64(long x0) { return x0 != 0; }
+define i1 @icmpi64(i64 noundef %0) {
+; CHECK-SD-LABEL: icmpi64:
+; CHECK-SD:       // %bb.0: // %entry
+; CHECK-SD-NEXT:    cmp x0, #0
+; CHECK-SD-NEXT:    cset w0, ne
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-CSSC-LABEL: icmpi64:
+; CHECK-CSSC:       // %bb.0: // %entry
+; CHECK-CSSC-NEXT:    umin x0, x0, #1
+; CHECK-CSSC-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-CSSC-NEXT:    ret
+;
+entry:
+  %2 = icmp ne i64 %0, 0
+  ret i1 %2
+}
+
+; auto icmpi32(int x0) { return x0 != 0; }
+define i1 @icmpi32(i32 noundef %0) {
+; CHECK-SD-LABEL: icmpi32:
+; CHECK-SD:       // %bb.0: // %entry
+; CHECK-SD-NEXT:    cmp w0, #0
+; CHECK-SD-NEXT:    cset w0, ne
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-CSSC-LABEL: icmpi32:
+; CHECK-CSSC:       // %bb.0: // %entry
+; CHECK-CSSC-NEXT:    umin w0, w0, #1
+; CHECK-CSSC-NEXT:    ret
+;
+entry:
+  %2 = icmp ne i32 %0, 0
+  ret i1 %2
+}
+
+; auto icmpi16(short x0) { return x0 != 0; }
+define i1 @icmpi16(i16 noundef %0) {
+; CHECK-SD-LABEL: icmpi16:
+; CHECK-SD:       // %bb.0: // %entry
+; CHECK-SD-NEXT:    tst w0, #0xffff
+; CHECK-SD-NEXT:    cset w0, ne
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-CSSC-LABEL: icmpi16:
+; CHECK-CSSC:       // %bb.0: // %entry
+; CHECK-CSSC-NEXT:    and	w8, w0, #0xffff
+; CHECK-CSSC-NEXT:    umin w0, w8, #1
+; CHECK-CSSC-NEXT:    ret
+;
+entry:
+  %2 = icmp ne i16 %0, 0
+  ret i1 %2
+}
+
+; auto icmpi8(char x0) { return x0 != 0; }
+define i1 @icmpi8(i8 noundef %0) {
+; CHECK-SD-LABEL: icmpi8:
+; CHECK-SD:       // %bb.0: // %entry
+; CHECK-SD-NEXT:    tst w0, #0xff
+; CHECK-SD-NEXT:    cset w0, ne
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-CSSC-LABEL: icmpi8:
+; CHECK-CSSC:       // %bb.0: // %entry
+; CHECK-CSSC-NEXT:    and w8, w0, #0xff
+; CHECK-CSSC-NEXT:    umin w0, w8, #1
+; CHECK-CSSC-NEXT:    ret
+;
+entry:
+  %2 = icmp ne i8 %0, 0
+  ret i1 %2
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
\ No newline at end of file
diff --git a/llvm/test/CodeGen/AArch64/arm64-popcnt.ll b/llvm/test/CodeGen/AArch64/arm64-popcnt.ll
index d06e42f5405ef..3d6cc814d157d 100644
--- a/llvm/test/CodeGen/AArch64/arm64-popcnt.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-popcnt.ll
@@ -414,8 +414,8 @@ define i1 @ctpop32_ne_one_nonzero(i32 %x) {
 ; CHECK-CSSC-LABEL: ctpop32_ne_one_nonzero:
 ; CHECK-CSSC:       // %bb.0: // %entry
 ; CHECK-CSSC-NEXT:    sub w8, w0, #1
-; CHECK-CSSC-NEXT:    tst w0, w8
-; CHECK-CSSC-NEXT:    cset w0, ne
+; CHECK-CSSC-NEXT:    and	w8, w0, w8
+; CHECK-CSSC-NEXT:    umin w0, w8, #1
 ; CHECK-CSSC-NEXT:    ret
 ;
 ; CHECK-BE-LABEL: ctpop32_ne_one_nonzero:



More information about the llvm-commits mailing list