[llvm] [AArch64] Use SVE2 bit-sel instructions for some binary patterns. (PR #147544)
Ricardo Jesus via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 8 08:12:35 PDT 2025
https://github.com/rj-jesus created https://github.com/llvm/llvm-project/pull/147544
We can use NBSL/BSL2N to implement the following operations via the
corresponding identities:
* EON(a, b) = BSL2N(a, a, b) = BSL2N (b, b, a)
* NAND(a, b) = NBSL(a, b, b) = NBSL(b, a, a)
* NOR(a, b) = NBSL(a, b, a) = NBSL(b, a, b)
* ORN(a, b) = BSL2N(a, b, a)
Most of these operations are currently lowered into at least two instructions
because we don't have dedicated Neon/SVE instructions for them. With the
appropriate pattern of NBSL/BSL2N we can lower them in a single
instruction.
P.S. We can also use NBSL to implement an unpredicated NOT(a) =
NBSL(a, a, a). However, because of the tied register constraint, this
may not always be profitable.
>From 46785cbdf84d42328ec56ed88c170ca8cc546f2f Mon Sep 17 00:00:00 2001
From: Ricardo Jesus <rjj at nvidia.com>
Date: Tue, 8 Jul 2025 04:19:01 -0700
Subject: [PATCH 1/2] Add tests.
---
llvm/test/CodeGen/AArch64/bsl.ll | 85 +++++++++++++++++++++++++++
llvm/test/CodeGen/AArch64/eor3.ll | 48 ++++++++++++++-
llvm/test/CodeGen/AArch64/sve2-bsl.ll | 64 ++++++++++++++++++++
3 files changed, 196 insertions(+), 1 deletion(-)
diff --git a/llvm/test/CodeGen/AArch64/bsl.ll b/llvm/test/CodeGen/AArch64/bsl.ll
index 5a270bc71cfc1..8e402ed23d085 100644
--- a/llvm/test/CodeGen/AArch64/bsl.ll
+++ b/llvm/test/CodeGen/AArch64/bsl.ll
@@ -431,3 +431,88 @@ define <4 x i8> @bsl2n_v4i8(<4 x i8> %0, <4 x i8> %1, <4 x i8> %2) {
%7 = or <4 x i8> %4, %6
ret <4 x i8> %7
}
+
+; NOT (a) has a dedicated instruction (MVN).
+define <2 x i64> @not_q(<2 x i64> %0) #0 {
+; NEON-LABEL: not_q:
+; NEON: // %bb.0:
+; NEON-NEXT: mvn v0.16b, v0.16b
+; NEON-NEXT: ret
+;
+; SVE2-LABEL: not_q:
+; SVE2: // %bb.0:
+; SVE2-NEXT: mvn v0.16b, v0.16b
+; SVE2-NEXT: ret
+ %2 = xor <2 x i64> %0, splat (i64 -1)
+ ret <2 x i64> %2
+}
+
+; NAND (a, b) = NBSL (a, b, b) = NBSL (b, a, a).
+define <2 x i64> @nand_q(<2 x i64> %0, <2 x i64> %1) #0 {
+; NEON-LABEL: nand_q:
+; NEON: // %bb.0:
+; NEON-NEXT: and v0.16b, v1.16b, v0.16b
+; NEON-NEXT: mvn v0.16b, v0.16b
+; NEON-NEXT: ret
+;
+; SVE2-LABEL: nand_q:
+; SVE2: // %bb.0:
+; SVE2-NEXT: and v0.16b, v1.16b, v0.16b
+; SVE2-NEXT: mvn v0.16b, v0.16b
+; SVE2-NEXT: ret
+ %3 = and <2 x i64> %1, %0
+ %4 = xor <2 x i64> %3, splat (i64 -1)
+ ret <2 x i64> %4
+}
+
+; NOR (a, b) = NBSL (a, b, a) = NBSL (b, a, b).
+define <2 x i64> @nor_q(<2 x i64> %0, <2 x i64> %1) #0 {
+; NEON-LABEL: nor_q:
+; NEON: // %bb.0:
+; NEON-NEXT: orr v0.16b, v1.16b, v0.16b
+; NEON-NEXT: mvn v0.16b, v0.16b
+; NEON-NEXT: ret
+;
+; SVE2-LABEL: nor_q:
+; SVE2: // %bb.0:
+; SVE2-NEXT: orr v0.16b, v1.16b, v0.16b
+; SVE2-NEXT: mvn v0.16b, v0.16b
+; SVE2-NEXT: ret
+ %3 = or <2 x i64> %1, %0
+ %4 = xor <2 x i64> %3, splat (i64 -1)
+ ret <2 x i64> %4
+}
+
+; EON (a, b) = BSL2N (a, a, b) = BSL2N (b, b, a).
+define <2 x i64> @eon_q(<2 x i64> %0, <2 x i64> %1) #0 {
+; NEON-LABEL: eon_q:
+; NEON: // %bb.0:
+; NEON-NEXT: eor v0.16b, v0.16b, v1.16b
+; NEON-NEXT: mvn v0.16b, v0.16b
+; NEON-NEXT: ret
+;
+; SVE2-LABEL: eon_q:
+; SVE2: // %bb.0:
+; SVE2-NEXT: eor v0.16b, v0.16b, v1.16b
+; SVE2-NEXT: mvn v0.16b, v0.16b
+; SVE2-NEXT: ret
+ %3 = xor <2 x i64> %0, %1
+ %4 = xor <2 x i64> %3, splat (i64 -1)
+ ret <2 x i64> %4
+}
+
+; ORN (a, b) has a dedicated instruction (ORN).
+define <2 x i64> @orn_q(<2 x i64> %0, <2 x i64> %1) #0 {
+; NEON-LABEL: orn_q:
+; NEON: // %bb.0:
+; NEON-NEXT: orn v0.16b, v0.16b, v1.16b
+; NEON-NEXT: ret
+;
+; SVE2-LABEL: orn_q:
+; SVE2: // %bb.0:
+; SVE2-NEXT: orn v0.16b, v0.16b, v1.16b
+; SVE2-NEXT: ret
+ %3 = xor <2 x i64> %1, splat (i64 -1)
+ %4 = or <2 x i64> %0, %3
+ ret <2 x i64> %4
+}
diff --git a/llvm/test/CodeGen/AArch64/eor3.ll b/llvm/test/CodeGen/AArch64/eor3.ll
index b89d9d608575c..a2631681847dc 100644
--- a/llvm/test/CodeGen/AArch64/eor3.ll
+++ b/llvm/test/CodeGen/AArch64/eor3.ll
@@ -2,7 +2,7 @@
; RUN: llc -mtriple=aarch64 -mattr=+sha3 < %s | FileCheck --check-prefix=SHA3 %s
; RUN: llc -mtriple=aarch64 -mattr=-sha3 < %s | FileCheck --check-prefix=NOSHA3 %s
; RUN: llc -mtriple=aarch64 -mattr=+sve2 < %s | FileCheck --check-prefix=SVE2 %s
-; RUN: llc -mtriple=aarch64 -mattr=+sha3,+sve2 < %s | FileCheck --check-prefix=SHA3 %s
+; RUN: llc -mtriple=aarch64 -mattr=+sha3,+sve2 < %s | FileCheck --check-prefix=SHA3-SVE2 %s
define <16 x i8> @eor3_16x8_left(<16 x i8> %0, <16 x i8> %1, <16 x i8> %2) {
; SHA3-LABEL: eor3_16x8_left:
@@ -24,6 +24,11 @@ define <16 x i8> @eor3_16x8_left(<16 x i8> %0, <16 x i8> %1, <16 x i8> %2) {
; SVE2-NEXT: eor3 z2.d, z2.d, z0.d, z1.d
; SVE2-NEXT: mov v0.16b, v2.16b
; SVE2-NEXT: ret
+;
+; SHA3-SVE2-LABEL: eor3_16x8_left:
+; SHA3-SVE2: // %bb.0:
+; SHA3-SVE2-NEXT: eor3 v0.16b, v0.16b, v1.16b, v2.16b
+; SHA3-SVE2-NEXT: ret
%4 = xor <16 x i8> %0, %1
%5 = xor <16 x i8> %2, %4
ret <16 x i8> %5
@@ -49,6 +54,11 @@ define <16 x i8> @eor3_16x8_right(<16 x i8> %0, <16 x i8> %1, <16 x i8> %2) {
; SVE2-NEXT: eor3 z1.d, z1.d, z2.d, z0.d
; SVE2-NEXT: mov v0.16b, v1.16b
; SVE2-NEXT: ret
+;
+; SHA3-SVE2-LABEL: eor3_16x8_right:
+; SHA3-SVE2: // %bb.0:
+; SHA3-SVE2-NEXT: eor3 v0.16b, v1.16b, v2.16b, v0.16b
+; SHA3-SVE2-NEXT: ret
%4 = xor <16 x i8> %1, %2
%5 = xor <16 x i8> %4, %0
ret <16 x i8> %5
@@ -74,6 +84,11 @@ define <8 x i16> @eor3_8x16_left(<8 x i16> %0, <8 x i16> %1, <8 x i16> %2) {
; SVE2-NEXT: eor3 z2.d, z2.d, z0.d, z1.d
; SVE2-NEXT: mov v0.16b, v2.16b
; SVE2-NEXT: ret
+;
+; SHA3-SVE2-LABEL: eor3_8x16_left:
+; SHA3-SVE2: // %bb.0:
+; SHA3-SVE2-NEXT: eor3 v0.16b, v0.16b, v1.16b, v2.16b
+; SHA3-SVE2-NEXT: ret
%4 = xor <8 x i16> %0, %1
%5 = xor <8 x i16> %2, %4
ret <8 x i16> %5
@@ -99,6 +114,11 @@ define <8 x i16> @eor3_8x16_right(<8 x i16> %0, <8 x i16> %1, <8 x i16> %2) {
; SVE2-NEXT: eor3 z1.d, z1.d, z2.d, z0.d
; SVE2-NEXT: mov v0.16b, v1.16b
; SVE2-NEXT: ret
+;
+; SHA3-SVE2-LABEL: eor3_8x16_right:
+; SHA3-SVE2: // %bb.0:
+; SHA3-SVE2-NEXT: eor3 v0.16b, v1.16b, v2.16b, v0.16b
+; SHA3-SVE2-NEXT: ret
%4 = xor <8 x i16> %1, %2
%5 = xor <8 x i16> %4, %0
ret <8 x i16> %5
@@ -124,6 +144,11 @@ define <4 x i32> @eor3_4x32_left(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2) {
; SVE2-NEXT: eor3 z2.d, z2.d, z0.d, z1.d
; SVE2-NEXT: mov v0.16b, v2.16b
; SVE2-NEXT: ret
+;
+; SHA3-SVE2-LABEL: eor3_4x32_left:
+; SHA3-SVE2: // %bb.0:
+; SHA3-SVE2-NEXT: eor3 v0.16b, v0.16b, v1.16b, v2.16b
+; SHA3-SVE2-NEXT: ret
%4 = xor <4 x i32> %0, %1
%5 = xor <4 x i32> %2, %4
ret <4 x i32> %5
@@ -149,6 +174,11 @@ define <4 x i32> @eor3_4x32_right(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2) {
; SVE2-NEXT: eor3 z1.d, z1.d, z2.d, z0.d
; SVE2-NEXT: mov v0.16b, v1.16b
; SVE2-NEXT: ret
+;
+; SHA3-SVE2-LABEL: eor3_4x32_right:
+; SHA3-SVE2: // %bb.0:
+; SHA3-SVE2-NEXT: eor3 v0.16b, v1.16b, v2.16b, v0.16b
+; SHA3-SVE2-NEXT: ret
%4 = xor <4 x i32> %1, %2
%5 = xor <4 x i32> %4, %0
ret <4 x i32> %5
@@ -174,6 +204,11 @@ define <2 x i64> @eor3_2x64_left(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2) {
; SVE2-NEXT: eor3 z2.d, z2.d, z0.d, z1.d
; SVE2-NEXT: mov v0.16b, v2.16b
; SVE2-NEXT: ret
+;
+; SHA3-SVE2-LABEL: eor3_2x64_left:
+; SHA3-SVE2: // %bb.0:
+; SHA3-SVE2-NEXT: eor3 v0.16b, v0.16b, v1.16b, v2.16b
+; SHA3-SVE2-NEXT: ret
%4 = xor <2 x i64> %0, %1
%5 = xor <2 x i64> %2, %4
ret <2 x i64> %5
@@ -199,6 +234,11 @@ define <2 x i64> @eor3_2x64_right(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2) {
; SVE2-NEXT: eor3 z1.d, z1.d, z2.d, z0.d
; SVE2-NEXT: mov v0.16b, v1.16b
; SVE2-NEXT: ret
+;
+; SHA3-SVE2-LABEL: eor3_2x64_right:
+; SHA3-SVE2: // %bb.0:
+; SHA3-SVE2-NEXT: eor3 v0.16b, v1.16b, v2.16b, v0.16b
+; SHA3-SVE2-NEXT: ret
%4 = xor <2 x i64> %1, %2
%5 = xor <2 x i64> %4, %0
ret <2 x i64> %5
@@ -222,6 +262,12 @@ define <2 x i64> @eor3_vnot(<2 x i64> %0, <2 x i64> %1) {
; SVE2-NEXT: eor v0.16b, v0.16b, v1.16b
; SVE2-NEXT: mvn v0.16b, v0.16b
; SVE2-NEXT: ret
+;
+; SHA3-SVE2-LABEL: eor3_vnot:
+; SHA3-SVE2: // %bb.0:
+; SHA3-SVE2-NEXT: eor v0.16b, v0.16b, v1.16b
+; SHA3-SVE2-NEXT: mvn v0.16b, v0.16b
+; SHA3-SVE2-NEXT: ret
%3 = xor <2 x i64> %0, <i64 -1, i64 -1>
%4 = xor <2 x i64> %3, %1
ret <2 x i64> %4
diff --git a/llvm/test/CodeGen/AArch64/sve2-bsl.ll b/llvm/test/CodeGen/AArch64/sve2-bsl.ll
index 8aedeac18f64a..660d0c85a4b7c 100644
--- a/llvm/test/CodeGen/AArch64/sve2-bsl.ll
+++ b/llvm/test/CodeGen/AArch64/sve2-bsl.ll
@@ -312,3 +312,67 @@ entry:
%t3 = xor <vscale x 4 x i32> %t2, %b
ret <vscale x 4 x i32> %t3
}
+
+; NOT (a) = NBSL (a, a, a).
+; We don't have a pattern for this right now because the tied register
+; constraint can lead to worse code gen.
+define <vscale x 2 x i64> @not(<vscale x 2 x i64> %0) #0 {
+; CHECK-LABEL: not:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z1.d, #-1 // =0xffffffffffffffff
+; CHECK-NEXT: eor z0.d, z0.d, z1.d
+; CHECK-NEXT: ret
+ %2 = xor <vscale x 2 x i64> %0, splat (i64 -1)
+ ret <vscale x 2 x i64> %2
+}
+
+; NAND (a, b) = NBSL (a, b, b) = NBSL (b, a, a).
+define <vscale x 2 x i64> @nand(<vscale x 2 x i64> %0, <vscale x 2 x i64> %1) #0 {
+; CHECK-LABEL: nand:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z2.d, #-1 // =0xffffffffffffffff
+; CHECK-NEXT: and z0.d, z1.d, z0.d
+; CHECK-NEXT: eor z0.d, z0.d, z2.d
+; CHECK-NEXT: ret
+ %3 = and <vscale x 2 x i64> %1, %0
+ %4 = xor <vscale x 2 x i64> %3, splat (i64 -1)
+ ret <vscale x 2 x i64> %4
+}
+
+; NOR (a, b) = NBSL (a, b, a) = NBSL (b, a, b).
+define <vscale x 2 x i64> @nor(<vscale x 2 x i64> %0, <vscale x 2 x i64> %1) #0 {
+; CHECK-LABEL: nor:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z2.d, #-1 // =0xffffffffffffffff
+; CHECK-NEXT: orr z0.d, z1.d, z0.d
+; CHECK-NEXT: eor z0.d, z0.d, z2.d
+; CHECK-NEXT: ret
+ %3 = or <vscale x 2 x i64> %1, %0
+ %4 = xor <vscale x 2 x i64> %3, splat (i64 -1)
+ ret <vscale x 2 x i64> %4
+}
+
+; EON (a, b) = BSL2N (a, a, b) = BSL2N (b, b, a).
+define <vscale x 2 x i64> @eon(<vscale x 2 x i64> %0, <vscale x 2 x i64> %1) #0 {
+; CHECK-LABEL: eon:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z2.d, #-1 // =0xffffffffffffffff
+; CHECK-NEXT: eor3 z0.d, z0.d, z1.d, z2.d
+; CHECK-NEXT: ret
+ %3 = xor <vscale x 2 x i64> %0, %1
+ %4 = xor <vscale x 2 x i64> %3, splat (i64 -1)
+ ret <vscale x 2 x i64> %4
+}
+
+; ORN (a, b) = BSL2N (a, b, a).
+define <vscale x 2 x i64> @orn(<vscale x 2 x i64> %0, <vscale x 2 x i64> %1) #0 {
+; CHECK-LABEL: orn:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z2.d, #-1 // =0xffffffffffffffff
+; CHECK-NEXT: eor z1.d, z1.d, z2.d
+; CHECK-NEXT: orr z0.d, z0.d, z1.d
+; CHECK-NEXT: ret
+ %3 = xor <vscale x 2 x i64> %1, splat (i64 -1)
+ %4 = or <vscale x 2 x i64> %0, %3
+ ret <vscale x 2 x i64> %4
+}
>From 7f5c069de223eedf28f2f9efa603287194bc27b4 Mon Sep 17 00:00:00 2001
From: Ricardo Jesus <rjj at nvidia.com>
Date: Tue, 8 Jul 2025 04:19:17 -0700
Subject: [PATCH 2/2] [AArch64] Use SVE2 bit-sel instructions for some binary
patterns.
We can use NBSL/BSL2N to implement the following operations via the
corresponding identities:
* EON(a, b) = BSL2N(a, a, b)
* NAND(a, b) = NBSL(a, b, b) = NBSL(b, a, a)
* NOR(a, b) = NBSL(a, b, a) = NBSL(b, a, b)
* ORN(a, b) = BSL2N(a, b, a)
These operations are currently lowered into at least two instructions
because we don't have dedicated Neon/SVE instructions for them. With the
appropriate pattern of NBSL/BSL2N we can lower them in a single
instruction.
P.S. We can also use NBSL to implement an unpredicated NOT(a) =
NBSL(a, a, a). However, because of the tied register constraint, this
may not be always profitable.
---
.../lib/Target/AArch64/AArch64SVEInstrInfo.td | 30 +++++++++++++++++++
llvm/test/CodeGen/AArch64/bsl.ll | 18 +++++++----
llvm/test/CodeGen/AArch64/eor3.ll | 12 +++++---
.../test/CodeGen/AArch64/sve-pred-selectop.ll | 12 ++------
llvm/test/CodeGen/AArch64/sve2-bsl.ll | 15 +++-------
5 files changed, 57 insertions(+), 30 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index 261df563bb2a9..8f02fc0b647ac 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -4034,6 +4034,36 @@ let Predicates = [HasSVE2_or_SME] in {
defm BSL2N_ZZZZ : sve2_int_bitwise_ternary_op<0b101, "bsl2n", AArch64bsl2n>;
defm NBSL_ZZZZ : sve2_int_bitwise_ternary_op<0b111, "nbsl", AArch64nbsl>;
+ multiclass binary_bitwise<ValueType VT, SDPatternOperator InOp, SDPatternOperator OutOp> {
+ def : Pat<(InOp VT:$op1, VT:$op2), (OutOp $op1, $op2)>;
+
+ def : Pat<(SVEType<VT>.DSub (InOp V64:$op1, V64:$op2)),
+ (EXTRACT_SUBREG (OutOp (INSERT_SUBREG (IMPLICIT_DEF), (SVEType<VT>.DSub $op1), dsub),
+ (INSERT_SUBREG (IMPLICIT_DEF), (SVEType<VT>.DSub $op2), dsub)), dsub)>;
+
+ def : Pat<(SVEType<VT>.ZSub (InOp V128:$op1, V128:$op2)),
+ (EXTRACT_SUBREG (OutOp (INSERT_SUBREG (IMPLICIT_DEF), (SVEType<VT>.ZSub $op1), zsub),
+ (INSERT_SUBREG (IMPLICIT_DEF), (SVEType<VT>.ZSub $op2), zsub)), zsub)>;
+ }
+
+ foreach VT = [nxv16i8, nxv8i16, nxv4i32, nxv2i64] in {
+ // EON (a, b) = BSL2N (a, a, b) = BSL2N (b, b, a)
+ defm : binary_bitwise<VT, PatFrag<(ops node:$op1, node:$op2), (vnot (xor node:$op1, node:$op2))>,
+ OutPatFrag<(ops node:$op1, node:$op2), (BSL2N_ZZZZ $op1, $op1, $op2)>>;
+
+ // NAND (a, b) = NBSL (a, b, b) = NBSL (b, a, a)
+ defm : binary_bitwise<VT, PatFrag<(ops node:$op1, node:$op2), (vnot (and node:$op1, node:$op2))>,
+ OutPatFrag<(ops node:$op1, node:$op2), (NBSL_ZZZZ $op2, $op1, $op1)>>;
+
+ // NOR (a, b) = NBSL (a, b, a) = NBSL (b, a, b)
+ defm : binary_bitwise<VT, PatFrag<(ops node:$op1, node:$op2), (vnot (or node:$op1, node:$op2))>,
+ OutPatFrag<(ops node:$op1, node:$op2), (NBSL_ZZZZ $op2, $op1, $op2)>>;
+
+ // ORN (a, b) = BSL2N (a, b, a)
+ defm : binary_bitwise<VT, PatFrag<(ops node:$op1, node:$op2), (or node:$op1, (vnot node:$op2))>,
+ OutPatFrag<(ops node:$op1, node:$op2), (BSL2N_ZZZZ $op1, $op2, $op1)>>;
+ }
+
// SVE2 bitwise xor and rotate right by immediate
defm XAR_ZZZI : sve2_int_rotate_right_imm<"xar", int_aarch64_sve_xar>;
diff --git a/llvm/test/CodeGen/AArch64/bsl.ll b/llvm/test/CodeGen/AArch64/bsl.ll
index 8e402ed23d085..df6b6f75b8935 100644
--- a/llvm/test/CodeGen/AArch64/bsl.ll
+++ b/llvm/test/CodeGen/AArch64/bsl.ll
@@ -457,8 +457,10 @@ define <2 x i64> @nand_q(<2 x i64> %0, <2 x i64> %1) #0 {
;
; SVE2-LABEL: nand_q:
; SVE2: // %bb.0:
-; SVE2-NEXT: and v0.16b, v1.16b, v0.16b
-; SVE2-NEXT: mvn v0.16b, v0.16b
+; SVE2-NEXT: // kill: def $q0 killed $q0 def $z0
+; SVE2-NEXT: // kill: def $q1 killed $q1 def $z1
+; SVE2-NEXT: nbsl z0.d, z0.d, z1.d, z1.d
+; SVE2-NEXT: // kill: def $q0 killed $q0 killed $z0
; SVE2-NEXT: ret
%3 = and <2 x i64> %1, %0
%4 = xor <2 x i64> %3, splat (i64 -1)
@@ -475,8 +477,10 @@ define <2 x i64> @nor_q(<2 x i64> %0, <2 x i64> %1) #0 {
;
; SVE2-LABEL: nor_q:
; SVE2: // %bb.0:
-; SVE2-NEXT: orr v0.16b, v1.16b, v0.16b
-; SVE2-NEXT: mvn v0.16b, v0.16b
+; SVE2-NEXT: // kill: def $q0 killed $q0 def $z0
+; SVE2-NEXT: // kill: def $q1 killed $q1 def $z1
+; SVE2-NEXT: nbsl z0.d, z0.d, z1.d, z0.d
+; SVE2-NEXT: // kill: def $q0 killed $q0 killed $z0
; SVE2-NEXT: ret
%3 = or <2 x i64> %1, %0
%4 = xor <2 x i64> %3, splat (i64 -1)
@@ -493,8 +497,10 @@ define <2 x i64> @eon_q(<2 x i64> %0, <2 x i64> %1) #0 {
;
; SVE2-LABEL: eon_q:
; SVE2: // %bb.0:
-; SVE2-NEXT: eor v0.16b, v0.16b, v1.16b
-; SVE2-NEXT: mvn v0.16b, v0.16b
+; SVE2-NEXT: // kill: def $q0 killed $q0 def $z0
+; SVE2-NEXT: // kill: def $q1 killed $q1 def $z1
+; SVE2-NEXT: bsl2n z0.d, z0.d, z0.d, z1.d
+; SVE2-NEXT: // kill: def $q0 killed $q0 killed $z0
; SVE2-NEXT: ret
%3 = xor <2 x i64> %0, %1
%4 = xor <2 x i64> %3, splat (i64 -1)
diff --git a/llvm/test/CodeGen/AArch64/eor3.ll b/llvm/test/CodeGen/AArch64/eor3.ll
index a2631681847dc..eccd09131b525 100644
--- a/llvm/test/CodeGen/AArch64/eor3.ll
+++ b/llvm/test/CodeGen/AArch64/eor3.ll
@@ -259,14 +259,18 @@ define <2 x i64> @eor3_vnot(<2 x i64> %0, <2 x i64> %1) {
;
; SVE2-LABEL: eor3_vnot:
; SVE2: // %bb.0:
-; SVE2-NEXT: eor v0.16b, v0.16b, v1.16b
-; SVE2-NEXT: mvn v0.16b, v0.16b
+; SVE2-NEXT: // kill: def $q0 killed $q0 def $z0
+; SVE2-NEXT: // kill: def $q1 killed $q1 def $z1
+; SVE2-NEXT: bsl2n z0.d, z0.d, z0.d, z1.d
+; SVE2-NEXT: // kill: def $q0 killed $q0 killed $z0
; SVE2-NEXT: ret
;
; SHA3-SVE2-LABEL: eor3_vnot:
; SHA3-SVE2: // %bb.0:
-; SHA3-SVE2-NEXT: eor v0.16b, v0.16b, v1.16b
-; SHA3-SVE2-NEXT: mvn v0.16b, v0.16b
+; SHA3-SVE2-NEXT: // kill: def $q0 killed $q0 def $z0
+; SHA3-SVE2-NEXT: // kill: def $q1 killed $q1 def $z1
+; SHA3-SVE2-NEXT: bsl2n z0.d, z0.d, z0.d, z1.d
+; SHA3-SVE2-NEXT: // kill: def $q0 killed $q0 killed $z0
; SHA3-SVE2-NEXT: ret
%3 = xor <2 x i64> %0, <i64 -1, i64 -1>
%4 = xor <2 x i64> %3, %1
diff --git a/llvm/test/CodeGen/AArch64/sve-pred-selectop.ll b/llvm/test/CodeGen/AArch64/sve-pred-selectop.ll
index 30ec2de2bd9cc..9a78726c450d1 100644
--- a/llvm/test/CodeGen/AArch64/sve-pred-selectop.ll
+++ b/llvm/test/CodeGen/AArch64/sve-pred-selectop.ll
@@ -322,11 +322,9 @@ entry:
define <vscale x 4 x i32> @ornot_v4i32(<vscale x 4 x i32> %z, <vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {
; CHECK-LABEL: ornot_v4i32:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: mov z3.s, #-1 // =0xffffffffffffffff
; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: bsl2n z1.d, z1.d, z2.d, z1.d
; CHECK-NEXT: cmpeq p0.s, p0/z, z0.s, #0
-; CHECK-NEXT: eor z2.d, z2.d, z3.d
-; CHECK-NEXT: orr z1.d, z1.d, z2.d
; CHECK-NEXT: mov z0.s, p0/m, z1.s
; CHECK-NEXT: ret
entry:
@@ -340,11 +338,9 @@ entry:
define <vscale x 8 x i16> @ornot_v8i16(<vscale x 8 x i16> %z, <vscale x 8 x i16> %x, <vscale x 8 x i16> %y) {
; CHECK-LABEL: ornot_v8i16:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: mov z3.h, #-1 // =0xffffffffffffffff
; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: bsl2n z1.d, z1.d, z2.d, z1.d
; CHECK-NEXT: cmpeq p0.h, p0/z, z0.h, #0
-; CHECK-NEXT: eor z2.d, z2.d, z3.d
-; CHECK-NEXT: orr z1.d, z1.d, z2.d
; CHECK-NEXT: mov z0.h, p0/m, z1.h
; CHECK-NEXT: ret
entry:
@@ -358,11 +354,9 @@ entry:
define <vscale x 16 x i8> @ornot_v16i8(<vscale x 16 x i8> %z, <vscale x 16 x i8> %x, <vscale x 16 x i8> %y) {
; CHECK-LABEL: ornot_v16i8:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: mov z3.b, #-1 // =0xffffffffffffffff
; CHECK-NEXT: ptrue p0.b
+; CHECK-NEXT: bsl2n z1.d, z1.d, z2.d, z1.d
; CHECK-NEXT: cmpeq p0.b, p0/z, z0.b, #0
-; CHECK-NEXT: eor z2.d, z2.d, z3.d
-; CHECK-NEXT: orr z1.d, z1.d, z2.d
; CHECK-NEXT: mov z0.b, p0/m, z1.b
; CHECK-NEXT: ret
entry:
diff --git a/llvm/test/CodeGen/AArch64/sve2-bsl.ll b/llvm/test/CodeGen/AArch64/sve2-bsl.ll
index 660d0c85a4b7c..6cfe66eb8e633 100644
--- a/llvm/test/CodeGen/AArch64/sve2-bsl.ll
+++ b/llvm/test/CodeGen/AArch64/sve2-bsl.ll
@@ -330,9 +330,7 @@ define <vscale x 2 x i64> @not(<vscale x 2 x i64> %0) #0 {
define <vscale x 2 x i64> @nand(<vscale x 2 x i64> %0, <vscale x 2 x i64> %1) #0 {
; CHECK-LABEL: nand:
; CHECK: // %bb.0:
-; CHECK-NEXT: mov z2.d, #-1 // =0xffffffffffffffff
-; CHECK-NEXT: and z0.d, z1.d, z0.d
-; CHECK-NEXT: eor z0.d, z0.d, z2.d
+; CHECK-NEXT: nbsl z0.d, z0.d, z1.d, z1.d
; CHECK-NEXT: ret
%3 = and <vscale x 2 x i64> %1, %0
%4 = xor <vscale x 2 x i64> %3, splat (i64 -1)
@@ -343,9 +341,7 @@ define <vscale x 2 x i64> @nand(<vscale x 2 x i64> %0, <vscale x 2 x i64> %1) #0
define <vscale x 2 x i64> @nor(<vscale x 2 x i64> %0, <vscale x 2 x i64> %1) #0 {
; CHECK-LABEL: nor:
; CHECK: // %bb.0:
-; CHECK-NEXT: mov z2.d, #-1 // =0xffffffffffffffff
-; CHECK-NEXT: orr z0.d, z1.d, z0.d
-; CHECK-NEXT: eor z0.d, z0.d, z2.d
+; CHECK-NEXT: nbsl z0.d, z0.d, z1.d, z0.d
; CHECK-NEXT: ret
%3 = or <vscale x 2 x i64> %1, %0
%4 = xor <vscale x 2 x i64> %3, splat (i64 -1)
@@ -356,8 +352,7 @@ define <vscale x 2 x i64> @nor(<vscale x 2 x i64> %0, <vscale x 2 x i64> %1) #0
define <vscale x 2 x i64> @eon(<vscale x 2 x i64> %0, <vscale x 2 x i64> %1) #0 {
; CHECK-LABEL: eon:
; CHECK: // %bb.0:
-; CHECK-NEXT: mov z2.d, #-1 // =0xffffffffffffffff
-; CHECK-NEXT: eor3 z0.d, z0.d, z1.d, z2.d
+; CHECK-NEXT: bsl2n z0.d, z0.d, z0.d, z1.d
; CHECK-NEXT: ret
%3 = xor <vscale x 2 x i64> %0, %1
%4 = xor <vscale x 2 x i64> %3, splat (i64 -1)
@@ -368,9 +363,7 @@ define <vscale x 2 x i64> @eon(<vscale x 2 x i64> %0, <vscale x 2 x i64> %1) #0
define <vscale x 2 x i64> @orn(<vscale x 2 x i64> %0, <vscale x 2 x i64> %1) #0 {
; CHECK-LABEL: orn:
; CHECK: // %bb.0:
-; CHECK-NEXT: mov z2.d, #-1 // =0xffffffffffffffff
-; CHECK-NEXT: eor z1.d, z1.d, z2.d
-; CHECK-NEXT: orr z0.d, z0.d, z1.d
+; CHECK-NEXT: bsl2n z0.d, z0.d, z1.d, z0.d
; CHECK-NEXT: ret
%3 = xor <vscale x 2 x i64> %1, splat (i64 -1)
%4 = or <vscale x 2 x i64> %0, %3
More information about the llvm-commits
mailing list