[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