[llvm] [LLVM][CodeGen][SVE] Add isel for zext(setcc(x,0,ne)) -> umin(x,1). (PR #209452)

Paul Walker via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 14 04:50:48 PDT 2026


https://github.com/paulwalker-arm created https://github.com/llvm/llvm-project/pull/209452

None

>From da1306a593dc1e584e8befe59faa4c498339c295 Mon Sep 17 00:00:00 2001
From: Paul Walker <paul.walker at arm.com>
Date: Fri, 10 Jul 2026 17:17:52 +0100
Subject: [PATCH 1/2] Add tests.

---
 llvm/test/CodeGen/AArch64/sve-cmp-folds.ll | 48 ++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/llvm/test/CodeGen/AArch64/sve-cmp-folds.ll b/llvm/test/CodeGen/AArch64/sve-cmp-folds.ll
index 103e31baa6d41..0e4011acc1314 100644
--- a/llvm/test/CodeGen/AArch64/sve-cmp-folds.ll
+++ b/llvm/test/CodeGen/AArch64/sve-cmp-folds.ll
@@ -89,6 +89,54 @@ define <vscale x 2 x i64> @icmp_cnot_nxv2i64(<vscale x 2 x i64> %a) {
   ret <vscale x 2 x i64> %zext
 }
 
+define <vscale x 16 x i8> @icmp_clamp_i1_nxv16i8(<vscale x 16 x i8> %a) {
+; CHECK-LABEL: icmp_clamp_i1_nxv16i8:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ptrue p0.b
+; CHECK-NEXT:    cmpne p1.b, p0/z, z0.b, #0
+; CHECK-NEXT:    mov z0.b, p1/z, #1 // =0x1
+; CHECK-NEXT:    ret
+  %mask = icmp ne <vscale x 16 x i8> %a, zeroinitializer
+  %zext = zext <vscale x 16 x i1> %mask to <vscale x 16 x i8>
+  ret <vscale x 16 x i8> %zext
+}
+
+define <vscale x 8 x i16> @icmp_clamp_i1_nxv8i16(<vscale x 8 x i16> %a) {
+; CHECK-LABEL: icmp_clamp_i1_nxv8i16:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ptrue p0.h
+; CHECK-NEXT:    cmpne p1.h, p0/z, z0.h, #0
+; CHECK-NEXT:    mov z0.h, p1/z, #1 // =0x1
+; CHECK-NEXT:    ret
+  %mask = icmp ne <vscale x 8 x i16> %a, zeroinitializer
+  %zext = zext <vscale x 8 x i1> %mask to <vscale x 8 x i16>
+  ret <vscale x 8 x i16> %zext
+}
+
+define <vscale x 4 x i32> @icmp_clamp_i1_nxv4i32(<vscale x 4 x i32> %a) {
+; CHECK-LABEL: icmp_clamp_i1_nxv4i32:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ptrue p0.s
+; CHECK-NEXT:    cmpne p1.s, p0/z, z0.s, #0
+; CHECK-NEXT:    mov z0.s, p1/z, #1 // =0x1
+; CHECK-NEXT:    ret
+  %mask = icmp ne <vscale x 4 x i32> %a, zeroinitializer
+  %zext = zext <vscale x 4 x i1> %mask to <vscale x 4 x i32>
+  ret <vscale x 4 x i32> %zext
+}
+
+define <vscale x 2 x i64> @icmp_clamp_i1_nxv2i64(<vscale x 2 x i64> %a) {
+; CHECK-LABEL: icmp_clamp_i1_nxv2i64:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ptrue p0.d
+; CHECK-NEXT:    cmpne p1.d, p0/z, z0.d, #0
+; CHECK-NEXT:    mov z0.d, p1/z, #1 // =0x1
+; CHECK-NEXT:    ret
+  %mask = icmp ne <vscale x 2 x i64> %a, zeroinitializer
+  %zext = zext <vscale x 2 x i1> %mask to <vscale x 2 x i64>
+  ret <vscale x 2 x i64> %zext
+}
+
 define i1 @foo_first(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
 ; CHECK-LABEL: foo_first:
 ; CHECK:       // %bb.0:

>From 2ad94c23054af4e9ee23c10c5f04d2991d6b508f Mon Sep 17 00:00:00 2001
From: Paul Walker <paul.walker at arm.com>
Date: Fri, 10 Jul 2026 17:32:37 +0100
Subject: [PATCH 2/2] [LLVM][CodeGen][SVE] Add isel for zext(setcc(x,0,ne)) ->
 umin(x,1).

---
 llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td | 10 ++++++++++
 llvm/test/CodeGen/AArch64/sve-cmp-folds.ll     | 16 ++++------------
 2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index 26b0a38f6bae0..9b5c6f9cef125 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -789,6 +789,16 @@ let Predicates = [HasSVE_or_SME] in {
   defm UMAX_ZI   : sve_int_arith_imm1_unsigned<0b01, "umax", AArch64umax_p>;
   defm UMIN_ZI   : sve_int_arith_imm1_unsigned<0b11, "umin", AArch64umin_p>;
 
+  // zext(cmpne(x, splat(0))) -> umin(x, 1)
+  def : Pat<(nxv16i8 (zext (AArch64setcc_z (SVEAllActive), nxv16i8:$LHS, (SVEDup0), SETNE))),
+            (UMIN_ZI_B $LHS, 1)>;
+  def : Pat<(nxv8i16 (zext (AArch64setcc_z (SVEAllActive), nxv8i16:$LHS, (SVEDup0), SETNE))),
+            (UMIN_ZI_H $LHS, 1)>;
+  def : Pat<(nxv4i32 (zext (AArch64setcc_z (SVEAllActive), nxv4i32:$LHS, (SVEDup0), SETNE))),
+            (UMIN_ZI_S $LHS, 1)>;
+  def : Pat<(nxv2i64 (zext (AArch64setcc_z (SVEAllActive), nxv2i64:$LHS, (SVEDup0), SETNE))),
+            (UMIN_ZI_D $LHS, 1)>;
+
   defm MUL_ZI     : sve_int_arith_imm2<"mul", AArch64mul_p>;
   defm MUL_ZPmZ   : sve_int_bin_pred_arit_2<0b000, "mul",   "MUL_ZPZZ",   AArch64mul_m1,         DestructiveBinaryComm>;
   defm SMULH_ZPmZ : sve_int_bin_pred_arit_2<0b010, "smulh", "SMULH_ZPZZ", int_aarch64_sve_smulh, DestructiveBinaryComm>;
diff --git a/llvm/test/CodeGen/AArch64/sve-cmp-folds.ll b/llvm/test/CodeGen/AArch64/sve-cmp-folds.ll
index 0e4011acc1314..88b3b3ad2102b 100644
--- a/llvm/test/CodeGen/AArch64/sve-cmp-folds.ll
+++ b/llvm/test/CodeGen/AArch64/sve-cmp-folds.ll
@@ -92,9 +92,7 @@ define <vscale x 2 x i64> @icmp_cnot_nxv2i64(<vscale x 2 x i64> %a) {
 define <vscale x 16 x i8> @icmp_clamp_i1_nxv16i8(<vscale x 16 x i8> %a) {
 ; CHECK-LABEL: icmp_clamp_i1_nxv16i8:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    ptrue p0.b
-; CHECK-NEXT:    cmpne p1.b, p0/z, z0.b, #0
-; CHECK-NEXT:    mov z0.b, p1/z, #1 // =0x1
+; CHECK-NEXT:    umin z0.b, z0.b, #1
 ; CHECK-NEXT:    ret
   %mask = icmp ne <vscale x 16 x i8> %a, zeroinitializer
   %zext = zext <vscale x 16 x i1> %mask to <vscale x 16 x i8>
@@ -104,9 +102,7 @@ define <vscale x 16 x i8> @icmp_clamp_i1_nxv16i8(<vscale x 16 x i8> %a) {
 define <vscale x 8 x i16> @icmp_clamp_i1_nxv8i16(<vscale x 8 x i16> %a) {
 ; CHECK-LABEL: icmp_clamp_i1_nxv8i16:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    ptrue p0.h
-; CHECK-NEXT:    cmpne p1.h, p0/z, z0.h, #0
-; CHECK-NEXT:    mov z0.h, p1/z, #1 // =0x1
+; CHECK-NEXT:    umin z0.h, z0.h, #1
 ; CHECK-NEXT:    ret
   %mask = icmp ne <vscale x 8 x i16> %a, zeroinitializer
   %zext = zext <vscale x 8 x i1> %mask to <vscale x 8 x i16>
@@ -116,9 +112,7 @@ define <vscale x 8 x i16> @icmp_clamp_i1_nxv8i16(<vscale x 8 x i16> %a) {
 define <vscale x 4 x i32> @icmp_clamp_i1_nxv4i32(<vscale x 4 x i32> %a) {
 ; CHECK-LABEL: icmp_clamp_i1_nxv4i32:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    ptrue p0.s
-; CHECK-NEXT:    cmpne p1.s, p0/z, z0.s, #0
-; CHECK-NEXT:    mov z0.s, p1/z, #1 // =0x1
+; CHECK-NEXT:    umin z0.s, z0.s, #1
 ; CHECK-NEXT:    ret
   %mask = icmp ne <vscale x 4 x i32> %a, zeroinitializer
   %zext = zext <vscale x 4 x i1> %mask to <vscale x 4 x i32>
@@ -128,9 +122,7 @@ define <vscale x 4 x i32> @icmp_clamp_i1_nxv4i32(<vscale x 4 x i32> %a) {
 define <vscale x 2 x i64> @icmp_clamp_i1_nxv2i64(<vscale x 2 x i64> %a) {
 ; CHECK-LABEL: icmp_clamp_i1_nxv2i64:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    ptrue p0.d
-; CHECK-NEXT:    cmpne p1.d, p0/z, z0.d, #0
-; CHECK-NEXT:    mov z0.d, p1/z, #1 // =0x1
+; CHECK-NEXT:    umin z0.d, z0.d, #1
 ; CHECK-NEXT:    ret
   %mask = icmp ne <vscale x 2 x i64> %a, zeroinitializer
   %zext = zext <vscale x 2 x i1> %mask to <vscale x 2 x i64>



More information about the llvm-commits mailing list