[llvm] [AArch64] Combine (and/or X, (dup (not Y))) -> (bic/orn X, (dup Y)) (PR #175739)
Piotr Fusik via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 2 00:06:42 PST 2026
https://github.com/pfusik updated https://github.com/llvm/llvm-project/pull/175739
>From 2f57e93961e21a4e2ee1ab3aa22c499e6c9c8b95 Mon Sep 17 00:00:00 2001
From: Piotr Fusik <p.fusik at samsung.com>
Date: Tue, 13 Jan 2026 11:39:21 +0100
Subject: [PATCH 1/4] [AArch64][test] Combine (and/or X, (dup (not Y))) ->
(bic/orn X, (dup Y))
---
.../AArch64/neon-bitwise-instructions.ll | 364 ++++++++++++++++++
1 file changed, 364 insertions(+)
diff --git a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
index 2026959a51a8e..3165ee4b6193b 100644
--- a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
+++ b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
@@ -2872,3 +2872,367 @@ entry:
%vqaddq_v2.i26515 = tail call <8 x i16> @llvm.aarch64.neon.sqadd.v8i16(<8 x i16> < i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1 >, <8 x i16> %vbsl5.i)
ret <8 x i16> %vqaddq_v2.i26515
}
+
+define <8 x i8> @and_dup_not_v8i8(<8 x i8> %a, i8 %m) {
+; CHECK-LABEL: and_dup_not_v8i8:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.8b, w8
+; CHECK-NEXT: and v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: ret
+ %not = xor i8 %m, -1
+ %insert = insertelement <8 x i8> poison, i8 %not, i64 0
+ %shuffle = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer
+ %and = and <8 x i8> %a, %shuffle
+ ret <8 x i8> %and
+}
+
+define <8 x i8> @and_dup_not_v8i8_swapped(<8 x i8> %a, i8 %m) {
+; CHECK-LABEL: and_dup_not_v8i8_swapped:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.8b, w8
+; CHECK-NEXT: and v0.8b, v1.8b, v0.8b
+; CHECK-NEXT: ret
+ %not = xor i8 %m, -1
+ %insert = insertelement <8 x i8> poison, i8 %not, i64 0
+ %shuffle = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer
+ %and = and <8 x i8> %shuffle, %a
+ ret <8 x i8> %and
+}
+
+define <16 x i8> @and_dup_not_v16i8(<16 x i8> %a, i8 %m) {
+; CHECK-LABEL: and_dup_not_v16i8:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.16b, w8
+; CHECK-NEXT: and v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: ret
+ %not = xor i8 %m, -1
+ %insert = insertelement <16 x i8> poison, i8 %not, i64 0
+ %shuffle = shufflevector <16 x i8> %insert, <16 x i8> poison, <16 x i32> zeroinitializer
+ %and = and <16 x i8> %a, %shuffle
+ ret <16 x i8> %and
+}
+
+define <16 x i8> @and_dup_not_v16i8_swapped(<16 x i8> %a, i8 %m) {
+; CHECK-LABEL: and_dup_not_v16i8_swapped:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.16b, w8
+; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-NEXT: ret
+ %not = xor i8 %m, -1
+ %insert = insertelement <16 x i8> poison, i8 %not, i64 0
+ %shuffle = shufflevector <16 x i8> %insert, <16 x i8> poison, <16 x i32> zeroinitializer
+ %and = and <16 x i8> %shuffle, %a
+ ret <16 x i8> %and
+}
+
+define <4 x i16> @and_dup_not_v4i16(<4 x i16> %a, i16 %m) {
+; CHECK-LABEL: and_dup_not_v4i16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.4h, w8
+; CHECK-NEXT: and v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: ret
+ %not = xor i16 %m, -1
+ %insert = insertelement <4 x i16> poison, i16 %not, i64 0
+ %shuffle = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer
+ %and = and <4 x i16> %a, %shuffle
+ ret <4 x i16> %and
+}
+
+define <4 x i16> @and_dup_not_v4i16_swapped(<4 x i16> %a, i16 %m) {
+; CHECK-LABEL: and_dup_not_v4i16_swapped:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.4h, w8
+; CHECK-NEXT: and v0.8b, v1.8b, v0.8b
+; CHECK-NEXT: ret
+ %not = xor i16 %m, -1
+ %insert = insertelement <4 x i16> poison, i16 %not, i64 0
+ %shuffle = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer
+ %and = and <4 x i16> %shuffle, %a
+ ret <4 x i16> %and
+}
+
+define <8 x i16> @and_dup_not_v8i16(<8 x i16> %a, i16 %m) {
+; CHECK-LABEL: and_dup_not_v8i16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.8h, w8
+; CHECK-NEXT: and v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: ret
+ %not = xor i16 %m, -1
+ %insert = insertelement <8 x i16> poison, i16 %not, i64 0
+ %shuffle = shufflevector <8 x i16> %insert, <8 x i16> poison, <8 x i32> zeroinitializer
+ %and = and <8 x i16> %a, %shuffle
+ ret <8 x i16> %and
+}
+
+define <8 x i16> @and_dup_not_v8i16_swapped(<8 x i16> %a, i16 %m) {
+; CHECK-LABEL: and_dup_not_v8i16_swapped:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.8h, w8
+; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-NEXT: ret
+ %not = xor i16 %m, -1
+ %insert = insertelement <8 x i16> poison, i16 %not, i64 0
+ %shuffle = shufflevector <8 x i16> %insert, <8 x i16> poison, <8 x i32> zeroinitializer
+ %and = and <8 x i16> %shuffle, %a
+ ret <8 x i16> %and
+}
+
+define <2 x i32> @and_dup_not_v2i32(<2 x i32> %a, i32 %m) {
+; CHECK-LABEL: and_dup_not_v2i32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.2s, w8
+; CHECK-NEXT: and v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: ret
+ %not = xor i32 %m, -1
+ %insert = insertelement <2 x i32> poison, i32 %not, i64 0
+ %shuffle = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer
+ %and = and <2 x i32> %a, %shuffle
+ ret <2 x i32> %and
+}
+
+define <2 x i32> @and_dup_not_v2i32_swapped(<2 x i32> %a, i32 %m) {
+; CHECK-LABEL: and_dup_not_v2i32_swapped:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.2s, w8
+; CHECK-NEXT: and v0.8b, v1.8b, v0.8b
+; CHECK-NEXT: ret
+ %not = xor i32 %m, -1
+ %insert = insertelement <2 x i32> poison, i32 %not, i64 0
+ %shuffle = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer
+ %and = and <2 x i32> %shuffle, %a
+ ret <2 x i32> %and
+}
+
+define <4 x i32> @and_dup_not_v4i32(<4 x i32> %a, i32 %m) {
+; CHECK-LABEL: and_dup_not_v4i32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.4s, w8
+; CHECK-NEXT: and v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: ret
+ %not = xor i32 %m, -1
+ %insert = insertelement <4 x i32> poison, i32 %not, i64 0
+ %shuffle = shufflevector <4 x i32> %insert, <4 x i32> poison, <4 x i32> zeroinitializer
+ %and = and <4 x i32> %a, %shuffle
+ ret <4 x i32> %and
+}
+
+define <4 x i32> @and_dup_not_v4i32_swapped(<4 x i32> %a, i32 %m) {
+; CHECK-LABEL: and_dup_not_v4i32_swapped:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.4s, w8
+; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-NEXT: ret
+ %not = xor i32 %m, -1
+ %insert = insertelement <4 x i32> poison, i32 %not, i64 0
+ %shuffle = shufflevector <4 x i32> %insert, <4 x i32> poison, <4 x i32> zeroinitializer
+ %and = and <4 x i32> %shuffle, %a
+ ret <4 x i32> %and
+}
+
+define <2 x i64> @and_dup_not_v2i64(<2 x i64> %a, i64 %m) {
+; CHECK-LABEL: and_dup_not_v2i64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn x8, x0
+; CHECK-NEXT: dup v1.2d, x8
+; CHECK-NEXT: and v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: ret
+ %not = xor i64 %m, -1
+ %insert = insertelement <2 x i64> poison, i64 %not, i64 0
+ %shuffle = shufflevector <2 x i64> %insert, <2 x i64> poison, <2 x i32> zeroinitializer
+ %and = and <2 x i64> %a, %shuffle
+ ret <2 x i64> %and
+}
+
+define <8 x i8> @or_dup_not_v8i8(<8 x i8> %a, i8 %m) {
+; CHECK-LABEL: or_dup_not_v8i8:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.8b, w8
+; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: ret
+ %not = xor i8 %m, -1
+ %insert = insertelement <8 x i8> poison, i8 %not, i64 0
+ %shuffle = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer
+ %or = or <8 x i8> %a, %shuffle
+ ret <8 x i8> %or
+}
+
+define <8 x i8> @or_dup_not_v8i8_swapped(<8 x i8> %a, i8 %m) {
+; CHECK-LABEL: or_dup_not_v8i8_swapped:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.8b, w8
+; CHECK-NEXT: orr v0.8b, v1.8b, v0.8b
+; CHECK-NEXT: ret
+ %not = xor i8 %m, -1
+ %insert = insertelement <8 x i8> poison, i8 %not, i64 0
+ %shuffle = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer
+ %or = or <8 x i8> %shuffle, %a
+ ret <8 x i8> %or
+}
+
+define <16 x i8> @or_dup_not_v16i8(<16 x i8> %a, i8 %m) {
+; CHECK-LABEL: or_dup_not_v16i8:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.16b, w8
+; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: ret
+ %not = xor i8 %m, -1
+ %insert = insertelement <16 x i8> poison, i8 %not, i64 0
+ %shuffle = shufflevector <16 x i8> %insert, <16 x i8> poison, <16 x i32> zeroinitializer
+ %or = or <16 x i8> %a, %shuffle
+ ret <16 x i8> %or
+}
+
+define <16 x i8> @or_dup_not_v16i8_swapped(<16 x i8> %a, i8 %m) {
+; CHECK-LABEL: or_dup_not_v16i8_swapped:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.16b, w8
+; CHECK-NEXT: orr v0.16b, v1.16b, v0.16b
+; CHECK-NEXT: ret
+ %not = xor i8 %m, -1
+ %insert = insertelement <16 x i8> poison, i8 %not, i64 0
+ %shuffle = shufflevector <16 x i8> %insert, <16 x i8> poison, <16 x i32> zeroinitializer
+ %or = or <16 x i8> %shuffle, %a
+ ret <16 x i8> %or
+}
+
+define <4 x i16> @or_dup_not_v4i16(<4 x i16> %a, i16 %m) {
+; CHECK-LABEL: or_dup_not_v4i16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.4h, w8
+; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: ret
+ %not = xor i16 %m, -1
+ %insert = insertelement <4 x i16> poison, i16 %not, i64 0
+ %shuffle = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer
+ %or = or <4 x i16> %a, %shuffle
+ ret <4 x i16> %or
+}
+
+define <4 x i16> @or_dup_not_v4i16_swapped(<4 x i16> %a, i16 %m) {
+; CHECK-LABEL: or_dup_not_v4i16_swapped:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.4h, w8
+; CHECK-NEXT: orr v0.8b, v1.8b, v0.8b
+; CHECK-NEXT: ret
+ %not = xor i16 %m, -1
+ %insert = insertelement <4 x i16> poison, i16 %not, i64 0
+ %shuffle = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer
+ %or = or <4 x i16> %shuffle, %a
+ ret <4 x i16> %or
+}
+
+define <8 x i16> @or_dup_not_v8i16(<8 x i16> %a, i16 %m) {
+; CHECK-LABEL: or_dup_not_v8i16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.8h, w8
+; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: ret
+ %not = xor i16 %m, -1
+ %insert = insertelement <8 x i16> poison, i16 %not, i64 0
+ %shuffle = shufflevector <8 x i16> %insert, <8 x i16> poison, <8 x i32> zeroinitializer
+ %or = or <8 x i16> %a, %shuffle
+ ret <8 x i16> %or
+}
+
+define <8 x i16> @or_dup_not_v8i16_swapped(<8 x i16> %a, i16 %m) {
+; CHECK-LABEL: or_dup_not_v8i16_swapped:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.8h, w8
+; CHECK-NEXT: orr v0.16b, v1.16b, v0.16b
+; CHECK-NEXT: ret
+ %not = xor i16 %m, -1
+ %insert = insertelement <8 x i16> poison, i16 %not, i64 0
+ %shuffle = shufflevector <8 x i16> %insert, <8 x i16> poison, <8 x i32> zeroinitializer
+ %or = or <8 x i16> %shuffle, %a
+ ret <8 x i16> %or
+}
+
+define <2 x i32> @or_dup_not_v2i32(<2 x i32> %a, i32 %m) {
+; CHECK-LABEL: or_dup_not_v2i32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.2s, w8
+; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: ret
+ %not = xor i32 %m, -1
+ %insert = insertelement <2 x i32> poison, i32 %not, i64 0
+ %shuffle = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer
+ %or = or <2 x i32> %a, %shuffle
+ ret <2 x i32> %or
+}
+
+define <2 x i32> @or_dup_not_v2i32_swapped(<2 x i32> %a, i32 %m) {
+; CHECK-LABEL: or_dup_not_v2i32_swapped:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.2s, w8
+; CHECK-NEXT: orr v0.8b, v1.8b, v0.8b
+; CHECK-NEXT: ret
+ %not = xor i32 %m, -1
+ %insert = insertelement <2 x i32> poison, i32 %not, i64 0
+ %shuffle = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer
+ %or = or <2 x i32> %shuffle, %a
+ ret <2 x i32> %or
+}
+
+define <4 x i32> @or_dup_not_v4i32(<4 x i32> %a, i32 %m) {
+; CHECK-LABEL: or_dup_not_v4i32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.4s, w8
+; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: ret
+ %not = xor i32 %m, -1
+ %insert = insertelement <4 x i32> poison, i32 %not, i64 0
+ %shuffle = shufflevector <4 x i32> %insert, <4 x i32> poison, <4 x i32> zeroinitializer
+ %or = or <4 x i32> %a, %shuffle
+ ret <4 x i32> %or
+}
+
+define <4 x i32> @or_dup_not_v4i32_swapped(<4 x i32> %a, i32 %m) {
+; CHECK-LABEL: or_dup_not_v4i32_swapped:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn w8, w0
+; CHECK-NEXT: dup v1.4s, w8
+; CHECK-NEXT: orr v0.16b, v1.16b, v0.16b
+; CHECK-NEXT: ret
+ %not = xor i32 %m, -1
+ %insert = insertelement <4 x i32> poison, i32 %not, i64 0
+ %shuffle = shufflevector <4 x i32> %insert, <4 x i32> poison, <4 x i32> zeroinitializer
+ %or = or <4 x i32> %shuffle, %a
+ ret <4 x i32> %or
+}
+
+define <2 x i64> @or_dup_not_v2i64(<2 x i64> %a, i64 %m) {
+; CHECK-LABEL: or_dup_not_v2i64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mvn x8, x0
+; CHECK-NEXT: dup v1.2d, x8
+; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: ret
+ %not = xor i64 %m, -1
+ %insert = insertelement <2 x i64> poison, i64 %not, i64 0
+ %shuffle = shufflevector <2 x i64> %insert, <2 x i64> poison, <2 x i32> zeroinitializer
+ %or = or <2 x i64> %a, %shuffle
+ ret <2 x i64> %or
+}
>From 11185acf3d63d4a463083ddd64d20af1d153e78f Mon Sep 17 00:00:00 2001
From: Piotr Fusik <p.fusik at samsung.com>
Date: Tue, 13 Jan 2026 11:39:40 +0100
Subject: [PATCH 2/4] [AArch64] Combine (and/or X, (dup (not Y))) -> (bic/orn
X, (dup Y))
---
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 17 +
.../AArch64/neon-bitwise-instructions.ll | 338 +++++++++++-------
2 files changed, 229 insertions(+), 126 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 5a471824ef513..2bdfc9de88719 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -7748,6 +7748,23 @@ def : DUPWithTruncPat<v16i8, v4i32, i32, DUPv16i8lane, VecIndex_x4>;
def : DUPWithTruncPat<v4i16, v4i32, i32, DUPv4i16lane, VecIndex_x2>;
def : DUPWithTruncPat<v8i16, v4i32, i32, DUPv8i16lane, VecIndex_x2>;
+multiclass BicOrnDupGpr<ValueType vectype, RegisterClass regtype> {
+ defvar vecreg = !cast<RegisterOperand>("V" # vectype.Size);
+ defvar bvectype = "v" # !srl(vectype.Size, 3) # "i8";
+ def : Pat<(vectype (and vecreg:$Rn, (AArch64dup (not regtype:$Rm)))),
+ (!cast<Instruction>("BIC" # bvectype) vectype:$Rn, (!cast<Instruction>("DUP" # vectype # "gpr") regtype:$Rm))>;
+ def : Pat<(vectype (or vecreg:$Rn, (AArch64dup (not regtype:$Rm)))),
+ (!cast<Instruction>("ORN" # bvectype) vectype:$Rn, (!cast<Instruction>("DUP" # vectype # "gpr") regtype:$Rm))>;
+}
+
+defm : BicOrnDupGpr<v8i8, GPR32>;
+defm : BicOrnDupGpr<v16i8, GPR32>;
+defm : BicOrnDupGpr<v4i16, GPR32>;
+defm : BicOrnDupGpr<v8i16, GPR32>;
+defm : BicOrnDupGpr<v2i32, GPR32>;
+defm : BicOrnDupGpr<v4i32, GPR32>;
+defm : BicOrnDupGpr<v2i64, GPR64>;
+
// SMOV and UMOV definitions, with some extra patterns for convenience
defm SMOV : SMov;
defm UMOV : UMov;
diff --git a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
index 3165ee4b6193b..2d6d0ca124a58 100644
--- a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
+++ b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
@@ -2874,12 +2874,18 @@ entry:
}
define <8 x i8> @and_dup_not_v8i8(<8 x i8> %a, i8 %m) {
-; CHECK-LABEL: and_dup_not_v8i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.8b, w8
-; CHECK-NEXT: and v0.8b, v0.8b, v1.8b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: and_dup_not_v8i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.8b, w0
+; CHECK-SD-NEXT: bic v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: and_dup_not_v8i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.8b, w8
+; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT: ret
%not = xor i8 %m, -1
%insert = insertelement <8 x i8> poison, i8 %not, i64 0
%shuffle = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer
@@ -2888,12 +2894,18 @@ define <8 x i8> @and_dup_not_v8i8(<8 x i8> %a, i8 %m) {
}
define <8 x i8> @and_dup_not_v8i8_swapped(<8 x i8> %a, i8 %m) {
-; CHECK-LABEL: and_dup_not_v8i8_swapped:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.8b, w8
-; CHECK-NEXT: and v0.8b, v1.8b, v0.8b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: and_dup_not_v8i8_swapped:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.8b, w0
+; CHECK-SD-NEXT: bic v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: and_dup_not_v8i8_swapped:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.8b, w8
+; CHECK-GI-NEXT: and v0.8b, v1.8b, v0.8b
+; CHECK-GI-NEXT: ret
%not = xor i8 %m, -1
%insert = insertelement <8 x i8> poison, i8 %not, i64 0
%shuffle = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer
@@ -2902,12 +2914,18 @@ define <8 x i8> @and_dup_not_v8i8_swapped(<8 x i8> %a, i8 %m) {
}
define <16 x i8> @and_dup_not_v16i8(<16 x i8> %a, i8 %m) {
-; CHECK-LABEL: and_dup_not_v16i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.16b, w8
-; CHECK-NEXT: and v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: and_dup_not_v16i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.16b, w0
+; CHECK-SD-NEXT: bic v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: and_dup_not_v16i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.16b, w8
+; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT: ret
%not = xor i8 %m, -1
%insert = insertelement <16 x i8> poison, i8 %not, i64 0
%shuffle = shufflevector <16 x i8> %insert, <16 x i8> poison, <16 x i32> zeroinitializer
@@ -2916,12 +2934,18 @@ define <16 x i8> @and_dup_not_v16i8(<16 x i8> %a, i8 %m) {
}
define <16 x i8> @and_dup_not_v16i8_swapped(<16 x i8> %a, i8 %m) {
-; CHECK-LABEL: and_dup_not_v16i8_swapped:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.16b, w8
-; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: and_dup_not_v16i8_swapped:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.16b, w0
+; CHECK-SD-NEXT: bic v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: and_dup_not_v16i8_swapped:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.16b, w8
+; CHECK-GI-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-GI-NEXT: ret
%not = xor i8 %m, -1
%insert = insertelement <16 x i8> poison, i8 %not, i64 0
%shuffle = shufflevector <16 x i8> %insert, <16 x i8> poison, <16 x i32> zeroinitializer
@@ -2930,12 +2954,18 @@ define <16 x i8> @and_dup_not_v16i8_swapped(<16 x i8> %a, i8 %m) {
}
define <4 x i16> @and_dup_not_v4i16(<4 x i16> %a, i16 %m) {
-; CHECK-LABEL: and_dup_not_v4i16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.4h, w8
-; CHECK-NEXT: and v0.8b, v0.8b, v1.8b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: and_dup_not_v4i16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.4h, w0
+; CHECK-SD-NEXT: bic v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: and_dup_not_v4i16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.4h, w8
+; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT: ret
%not = xor i16 %m, -1
%insert = insertelement <4 x i16> poison, i16 %not, i64 0
%shuffle = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer
@@ -2944,12 +2974,18 @@ define <4 x i16> @and_dup_not_v4i16(<4 x i16> %a, i16 %m) {
}
define <4 x i16> @and_dup_not_v4i16_swapped(<4 x i16> %a, i16 %m) {
-; CHECK-LABEL: and_dup_not_v4i16_swapped:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.4h, w8
-; CHECK-NEXT: and v0.8b, v1.8b, v0.8b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: and_dup_not_v4i16_swapped:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.4h, w0
+; CHECK-SD-NEXT: bic v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: and_dup_not_v4i16_swapped:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.4h, w8
+; CHECK-GI-NEXT: and v0.8b, v1.8b, v0.8b
+; CHECK-GI-NEXT: ret
%not = xor i16 %m, -1
%insert = insertelement <4 x i16> poison, i16 %not, i64 0
%shuffle = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer
@@ -2958,12 +2994,18 @@ define <4 x i16> @and_dup_not_v4i16_swapped(<4 x i16> %a, i16 %m) {
}
define <8 x i16> @and_dup_not_v8i16(<8 x i16> %a, i16 %m) {
-; CHECK-LABEL: and_dup_not_v8i16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.8h, w8
-; CHECK-NEXT: and v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: and_dup_not_v8i16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.8h, w0
+; CHECK-SD-NEXT: bic v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: and_dup_not_v8i16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.8h, w8
+; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT: ret
%not = xor i16 %m, -1
%insert = insertelement <8 x i16> poison, i16 %not, i64 0
%shuffle = shufflevector <8 x i16> %insert, <8 x i16> poison, <8 x i32> zeroinitializer
@@ -2972,12 +3014,18 @@ define <8 x i16> @and_dup_not_v8i16(<8 x i16> %a, i16 %m) {
}
define <8 x i16> @and_dup_not_v8i16_swapped(<8 x i16> %a, i16 %m) {
-; CHECK-LABEL: and_dup_not_v8i16_swapped:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.8h, w8
-; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: and_dup_not_v8i16_swapped:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.8h, w0
+; CHECK-SD-NEXT: bic v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: and_dup_not_v8i16_swapped:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.8h, w8
+; CHECK-GI-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-GI-NEXT: ret
%not = xor i16 %m, -1
%insert = insertelement <8 x i16> poison, i16 %not, i64 0
%shuffle = shufflevector <8 x i16> %insert, <8 x i16> poison, <8 x i32> zeroinitializer
@@ -2988,9 +3036,8 @@ define <8 x i16> @and_dup_not_v8i16_swapped(<8 x i16> %a, i16 %m) {
define <2 x i32> @and_dup_not_v2i32(<2 x i32> %a, i32 %m) {
; CHECK-LABEL: and_dup_not_v2i32:
; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.2s, w8
-; CHECK-NEXT: and v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: dup v1.2s, w0
+; CHECK-NEXT: bic v0.8b, v0.8b, v1.8b
; CHECK-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <2 x i32> poison, i32 %not, i64 0
@@ -3002,9 +3049,8 @@ define <2 x i32> @and_dup_not_v2i32(<2 x i32> %a, i32 %m) {
define <2 x i32> @and_dup_not_v2i32_swapped(<2 x i32> %a, i32 %m) {
; CHECK-LABEL: and_dup_not_v2i32_swapped:
; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.2s, w8
-; CHECK-NEXT: and v0.8b, v1.8b, v0.8b
+; CHECK-NEXT: dup v1.2s, w0
+; CHECK-NEXT: bic v0.8b, v0.8b, v1.8b
; CHECK-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <2 x i32> poison, i32 %not, i64 0
@@ -3016,9 +3062,8 @@ define <2 x i32> @and_dup_not_v2i32_swapped(<2 x i32> %a, i32 %m) {
define <4 x i32> @and_dup_not_v4i32(<4 x i32> %a, i32 %m) {
; CHECK-LABEL: and_dup_not_v4i32:
; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.4s, w8
-; CHECK-NEXT: and v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: dup v1.4s, w0
+; CHECK-NEXT: bic v0.16b, v0.16b, v1.16b
; CHECK-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <4 x i32> poison, i32 %not, i64 0
@@ -3030,9 +3075,8 @@ define <4 x i32> @and_dup_not_v4i32(<4 x i32> %a, i32 %m) {
define <4 x i32> @and_dup_not_v4i32_swapped(<4 x i32> %a, i32 %m) {
; CHECK-LABEL: and_dup_not_v4i32_swapped:
; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.4s, w8
-; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-NEXT: dup v1.4s, w0
+; CHECK-NEXT: bic v0.16b, v0.16b, v1.16b
; CHECK-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <4 x i32> poison, i32 %not, i64 0
@@ -3044,9 +3088,8 @@ define <4 x i32> @and_dup_not_v4i32_swapped(<4 x i32> %a, i32 %m) {
define <2 x i64> @and_dup_not_v2i64(<2 x i64> %a, i64 %m) {
; CHECK-LABEL: and_dup_not_v2i64:
; CHECK: // %bb.0:
-; CHECK-NEXT: mvn x8, x0
-; CHECK-NEXT: dup v1.2d, x8
-; CHECK-NEXT: and v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: dup v1.2d, x0
+; CHECK-NEXT: bic v0.16b, v0.16b, v1.16b
; CHECK-NEXT: ret
%not = xor i64 %m, -1
%insert = insertelement <2 x i64> poison, i64 %not, i64 0
@@ -3056,12 +3099,18 @@ define <2 x i64> @and_dup_not_v2i64(<2 x i64> %a, i64 %m) {
}
define <8 x i8> @or_dup_not_v8i8(<8 x i8> %a, i8 %m) {
-; CHECK-LABEL: or_dup_not_v8i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.8b, w8
-; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: or_dup_not_v8i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.8b, w0
+; CHECK-SD-NEXT: orn v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: or_dup_not_v8i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.8b, w8
+; CHECK-GI-NEXT: orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT: ret
%not = xor i8 %m, -1
%insert = insertelement <8 x i8> poison, i8 %not, i64 0
%shuffle = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer
@@ -3070,12 +3119,18 @@ define <8 x i8> @or_dup_not_v8i8(<8 x i8> %a, i8 %m) {
}
define <8 x i8> @or_dup_not_v8i8_swapped(<8 x i8> %a, i8 %m) {
-; CHECK-LABEL: or_dup_not_v8i8_swapped:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.8b, w8
-; CHECK-NEXT: orr v0.8b, v1.8b, v0.8b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: or_dup_not_v8i8_swapped:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.8b, w0
+; CHECK-SD-NEXT: orn v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: or_dup_not_v8i8_swapped:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.8b, w8
+; CHECK-GI-NEXT: orr v0.8b, v1.8b, v0.8b
+; CHECK-GI-NEXT: ret
%not = xor i8 %m, -1
%insert = insertelement <8 x i8> poison, i8 %not, i64 0
%shuffle = shufflevector <8 x i8> %insert, <8 x i8> poison, <8 x i32> zeroinitializer
@@ -3084,12 +3139,18 @@ define <8 x i8> @or_dup_not_v8i8_swapped(<8 x i8> %a, i8 %m) {
}
define <16 x i8> @or_dup_not_v16i8(<16 x i8> %a, i8 %m) {
-; CHECK-LABEL: or_dup_not_v16i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.16b, w8
-; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: or_dup_not_v16i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.16b, w0
+; CHECK-SD-NEXT: orn v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: or_dup_not_v16i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.16b, w8
+; CHECK-GI-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT: ret
%not = xor i8 %m, -1
%insert = insertelement <16 x i8> poison, i8 %not, i64 0
%shuffle = shufflevector <16 x i8> %insert, <16 x i8> poison, <16 x i32> zeroinitializer
@@ -3098,12 +3159,18 @@ define <16 x i8> @or_dup_not_v16i8(<16 x i8> %a, i8 %m) {
}
define <16 x i8> @or_dup_not_v16i8_swapped(<16 x i8> %a, i8 %m) {
-; CHECK-LABEL: or_dup_not_v16i8_swapped:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.16b, w8
-; CHECK-NEXT: orr v0.16b, v1.16b, v0.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: or_dup_not_v16i8_swapped:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.16b, w0
+; CHECK-SD-NEXT: orn v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: or_dup_not_v16i8_swapped:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.16b, w8
+; CHECK-GI-NEXT: orr v0.16b, v1.16b, v0.16b
+; CHECK-GI-NEXT: ret
%not = xor i8 %m, -1
%insert = insertelement <16 x i8> poison, i8 %not, i64 0
%shuffle = shufflevector <16 x i8> %insert, <16 x i8> poison, <16 x i32> zeroinitializer
@@ -3112,12 +3179,18 @@ define <16 x i8> @or_dup_not_v16i8_swapped(<16 x i8> %a, i8 %m) {
}
define <4 x i16> @or_dup_not_v4i16(<4 x i16> %a, i16 %m) {
-; CHECK-LABEL: or_dup_not_v4i16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.4h, w8
-; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: or_dup_not_v4i16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.4h, w0
+; CHECK-SD-NEXT: orn v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: or_dup_not_v4i16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.4h, w8
+; CHECK-GI-NEXT: orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT: ret
%not = xor i16 %m, -1
%insert = insertelement <4 x i16> poison, i16 %not, i64 0
%shuffle = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer
@@ -3126,12 +3199,18 @@ define <4 x i16> @or_dup_not_v4i16(<4 x i16> %a, i16 %m) {
}
define <4 x i16> @or_dup_not_v4i16_swapped(<4 x i16> %a, i16 %m) {
-; CHECK-LABEL: or_dup_not_v4i16_swapped:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.4h, w8
-; CHECK-NEXT: orr v0.8b, v1.8b, v0.8b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: or_dup_not_v4i16_swapped:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.4h, w0
+; CHECK-SD-NEXT: orn v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: or_dup_not_v4i16_swapped:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.4h, w8
+; CHECK-GI-NEXT: orr v0.8b, v1.8b, v0.8b
+; CHECK-GI-NEXT: ret
%not = xor i16 %m, -1
%insert = insertelement <4 x i16> poison, i16 %not, i64 0
%shuffle = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer
@@ -3140,12 +3219,18 @@ define <4 x i16> @or_dup_not_v4i16_swapped(<4 x i16> %a, i16 %m) {
}
define <8 x i16> @or_dup_not_v8i16(<8 x i16> %a, i16 %m) {
-; CHECK-LABEL: or_dup_not_v8i16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.8h, w8
-; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: or_dup_not_v8i16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.8h, w0
+; CHECK-SD-NEXT: orn v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: or_dup_not_v8i16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.8h, w8
+; CHECK-GI-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT: ret
%not = xor i16 %m, -1
%insert = insertelement <8 x i16> poison, i16 %not, i64 0
%shuffle = shufflevector <8 x i16> %insert, <8 x i16> poison, <8 x i32> zeroinitializer
@@ -3154,12 +3239,18 @@ define <8 x i16> @or_dup_not_v8i16(<8 x i16> %a, i16 %m) {
}
define <8 x i16> @or_dup_not_v8i16_swapped(<8 x i16> %a, i16 %m) {
-; CHECK-LABEL: or_dup_not_v8i16_swapped:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.8h, w8
-; CHECK-NEXT: orr v0.16b, v1.16b, v0.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: or_dup_not_v8i16_swapped:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.8h, w0
+; CHECK-SD-NEXT: orn v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: or_dup_not_v8i16_swapped:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.8h, w8
+; CHECK-GI-NEXT: orr v0.16b, v1.16b, v0.16b
+; CHECK-GI-NEXT: ret
%not = xor i16 %m, -1
%insert = insertelement <8 x i16> poison, i16 %not, i64 0
%shuffle = shufflevector <8 x i16> %insert, <8 x i16> poison, <8 x i32> zeroinitializer
@@ -3170,9 +3261,8 @@ define <8 x i16> @or_dup_not_v8i16_swapped(<8 x i16> %a, i16 %m) {
define <2 x i32> @or_dup_not_v2i32(<2 x i32> %a, i32 %m) {
; CHECK-LABEL: or_dup_not_v2i32:
; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.2s, w8
-; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: dup v1.2s, w0
+; CHECK-NEXT: orn v0.8b, v0.8b, v1.8b
; CHECK-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <2 x i32> poison, i32 %not, i64 0
@@ -3184,9 +3274,8 @@ define <2 x i32> @or_dup_not_v2i32(<2 x i32> %a, i32 %m) {
define <2 x i32> @or_dup_not_v2i32_swapped(<2 x i32> %a, i32 %m) {
; CHECK-LABEL: or_dup_not_v2i32_swapped:
; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.2s, w8
-; CHECK-NEXT: orr v0.8b, v1.8b, v0.8b
+; CHECK-NEXT: dup v1.2s, w0
+; CHECK-NEXT: orn v0.8b, v0.8b, v1.8b
; CHECK-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <2 x i32> poison, i32 %not, i64 0
@@ -3198,9 +3287,8 @@ define <2 x i32> @or_dup_not_v2i32_swapped(<2 x i32> %a, i32 %m) {
define <4 x i32> @or_dup_not_v4i32(<4 x i32> %a, i32 %m) {
; CHECK-LABEL: or_dup_not_v4i32:
; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.4s, w8
-; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: dup v1.4s, w0
+; CHECK-NEXT: orn v0.16b, v0.16b, v1.16b
; CHECK-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <4 x i32> poison, i32 %not, i64 0
@@ -3212,9 +3300,8 @@ define <4 x i32> @or_dup_not_v4i32(<4 x i32> %a, i32 %m) {
define <4 x i32> @or_dup_not_v4i32_swapped(<4 x i32> %a, i32 %m) {
; CHECK-LABEL: or_dup_not_v4i32_swapped:
; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w0
-; CHECK-NEXT: dup v1.4s, w8
-; CHECK-NEXT: orr v0.16b, v1.16b, v0.16b
+; CHECK-NEXT: dup v1.4s, w0
+; CHECK-NEXT: orn v0.16b, v0.16b, v1.16b
; CHECK-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <4 x i32> poison, i32 %not, i64 0
@@ -3226,9 +3313,8 @@ define <4 x i32> @or_dup_not_v4i32_swapped(<4 x i32> %a, i32 %m) {
define <2 x i64> @or_dup_not_v2i64(<2 x i64> %a, i64 %m) {
; CHECK-LABEL: or_dup_not_v2i64:
; CHECK: // %bb.0:
-; CHECK-NEXT: mvn x8, x0
-; CHECK-NEXT: dup v1.2d, x8
-; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: dup v1.2d, x0
+; CHECK-NEXT: orn v0.16b, v0.16b, v1.16b
; CHECK-NEXT: ret
%not = xor i64 %m, -1
%insert = insertelement <2 x i64> poison, i64 %not, i64 0
>From 052b79113d8a593f73ac02cb8fdcebfeb3455fe9 Mon Sep 17 00:00:00 2001
From: Piotr Fusik <p.fusik at samsung.com>
Date: Fri, 27 Feb 2026 14:45:45 +0100
Subject: [PATCH 3/4] [AArch64] Move the transform to AArch64DAGToDAGISel
---
.../Target/AArch64/AArch64ISelDAGToDAG.cpp | 26 ++++++++++++++++++-
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 17 ------------
2 files changed, 25 insertions(+), 18 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 7b566e432b6bc..ee8998ea361af 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -15,6 +15,7 @@
#include "MCTargetDesc/AArch64AddressingModes.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/CodeGen/ISDOpcodes.h"
+#include "llvm/CodeGen/SDPatternMatch.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/IR/Function.h" // To access function attributes.
#include "llvm/IR/GlobalValue.h"
@@ -432,6 +433,7 @@ class AArch64DAGToDAGISel : public SelectionDAGISel {
const SDValue &OldBase, const SDValue &OldOffset,
unsigned Scale);
+ bool tryBicOrnDup(SDNode *N);
bool tryBitfieldExtractOp(SDNode *N);
bool tryBitfieldExtractOpFromSExt(SDNode *N);
bool tryBitfieldInsertOp(SDNode *N);
@@ -2798,6 +2800,23 @@ static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0,
return true;
}
+bool AArch64DAGToDAGISel::tryBicOrnDup(SDNode *N) {
+ unsigned Opc = N->getOpcode();
+ assert(Opc == ISD::AND || Opc == ISD::OR);
+ using namespace SDPatternMatch;
+ SDValue X, Y;
+ if (!sd_match(N, m_c_BinOp(Opc, m_Node(AArch64ISD::DUP, m_Not(m_Value(X))),
+ m_Value(Y))))
+ return false;
+
+ EVT VT = N->getValueType(0);
+ SDLoc DL(N);
+ SDValue Dup = CurDAG->getNode(AArch64ISD::DUP, DL, VT, X);
+ SDValue Ops[] = {CurDAG->getNOT(DL, Dup, VT), Y};
+ CurDAG->SelectNodeTo(N, Opc, VT, Ops);
+ return true;
+}
+
bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *N) {
assert(N->getOpcode() == ISD::SIGN_EXTEND);
@@ -4821,8 +4840,11 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) {
break;
}
- case ISD::SRL:
case ISD::AND:
+ if (tryBicOrnDup(Node))
+ return;
+ [[fallthrough]];
+ case ISD::SRL:
case ISD::SRA:
case ISD::SIGN_EXTEND_INREG:
if (tryBitfieldExtractOp(Node))
@@ -4842,6 +4864,8 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) {
break;
case ISD::OR:
+ if (tryBicOrnDup(Node))
+ return;
if (tryBitfieldInsertOp(Node))
return;
if (trySelectXAR(Node))
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 2bdfc9de88719..5a471824ef513 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -7748,23 +7748,6 @@ def : DUPWithTruncPat<v16i8, v4i32, i32, DUPv16i8lane, VecIndex_x4>;
def : DUPWithTruncPat<v4i16, v4i32, i32, DUPv4i16lane, VecIndex_x2>;
def : DUPWithTruncPat<v8i16, v4i32, i32, DUPv8i16lane, VecIndex_x2>;
-multiclass BicOrnDupGpr<ValueType vectype, RegisterClass regtype> {
- defvar vecreg = !cast<RegisterOperand>("V" # vectype.Size);
- defvar bvectype = "v" # !srl(vectype.Size, 3) # "i8";
- def : Pat<(vectype (and vecreg:$Rn, (AArch64dup (not regtype:$Rm)))),
- (!cast<Instruction>("BIC" # bvectype) vectype:$Rn, (!cast<Instruction>("DUP" # vectype # "gpr") regtype:$Rm))>;
- def : Pat<(vectype (or vecreg:$Rn, (AArch64dup (not regtype:$Rm)))),
- (!cast<Instruction>("ORN" # bvectype) vectype:$Rn, (!cast<Instruction>("DUP" # vectype # "gpr") regtype:$Rm))>;
-}
-
-defm : BicOrnDupGpr<v8i8, GPR32>;
-defm : BicOrnDupGpr<v16i8, GPR32>;
-defm : BicOrnDupGpr<v4i16, GPR32>;
-defm : BicOrnDupGpr<v8i16, GPR32>;
-defm : BicOrnDupGpr<v2i32, GPR32>;
-defm : BicOrnDupGpr<v4i32, GPR32>;
-defm : BicOrnDupGpr<v2i64, GPR64>;
-
// SMOV and UMOV definitions, with some extra patterns for convenience
defm SMOV : SMov;
defm UMOV : UMov;
>From 9e78b097e8a38ebffff44578e685c318a4291215 Mon Sep 17 00:00:00 2001
From: Piotr Fusik <p.fusik at samsung.com>
Date: Mon, 2 Mar 2026 09:05:26 +0100
Subject: [PATCH 4/4] [AArch64] Move the transform to AArch64ISelLowering
---
.../Target/AArch64/AArch64ISelDAGToDAG.cpp | 26 +--
.../Target/AArch64/AArch64ISelLowering.cpp | 25 +++
.../AArch64/neon-bitwise-instructions.ll | 170 ++++++++++++------
3 files changed, 146 insertions(+), 75 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index ee8998ea361af..7b566e432b6bc 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -15,7 +15,6 @@
#include "MCTargetDesc/AArch64AddressingModes.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/CodeGen/ISDOpcodes.h"
-#include "llvm/CodeGen/SDPatternMatch.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/IR/Function.h" // To access function attributes.
#include "llvm/IR/GlobalValue.h"
@@ -433,7 +432,6 @@ class AArch64DAGToDAGISel : public SelectionDAGISel {
const SDValue &OldBase, const SDValue &OldOffset,
unsigned Scale);
- bool tryBicOrnDup(SDNode *N);
bool tryBitfieldExtractOp(SDNode *N);
bool tryBitfieldExtractOpFromSExt(SDNode *N);
bool tryBitfieldInsertOp(SDNode *N);
@@ -2800,23 +2798,6 @@ static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0,
return true;
}
-bool AArch64DAGToDAGISel::tryBicOrnDup(SDNode *N) {
- unsigned Opc = N->getOpcode();
- assert(Opc == ISD::AND || Opc == ISD::OR);
- using namespace SDPatternMatch;
- SDValue X, Y;
- if (!sd_match(N, m_c_BinOp(Opc, m_Node(AArch64ISD::DUP, m_Not(m_Value(X))),
- m_Value(Y))))
- return false;
-
- EVT VT = N->getValueType(0);
- SDLoc DL(N);
- SDValue Dup = CurDAG->getNode(AArch64ISD::DUP, DL, VT, X);
- SDValue Ops[] = {CurDAG->getNOT(DL, Dup, VT), Y};
- CurDAG->SelectNodeTo(N, Opc, VT, Ops);
- return true;
-}
-
bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *N) {
assert(N->getOpcode() == ISD::SIGN_EXTEND);
@@ -4840,11 +4821,8 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) {
break;
}
- case ISD::AND:
- if (tryBicOrnDup(Node))
- return;
- [[fallthrough]];
case ISD::SRL:
+ case ISD::AND:
case ISD::SRA:
case ISD::SIGN_EXTEND_INREG:
if (tryBitfieldExtractOp(Node))
@@ -4864,8 +4842,6 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) {
break;
case ISD::OR:
- if (tryBicOrnDup(Node))
- return;
if (tryBitfieldInsertOp(Node))
return;
if (trySelectXAR(Node))
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index ffd9641e9f9df..2ba1e7b35aa6d 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -20561,6 +20561,25 @@ static SDValue performANDORCSELCombine(SDNode *N, SelectionDAG &DAG) {
CSel0.getOperand(1), getCondCode(DAG, CC1), CCmp);
}
+// (and/or X, (splat (not Y))) -> (and/or X, (not (splat Y)))
+// so that it gets selected as (bic/orn X, (dup Y))
+static SDValue performANDORDUPNOTCombine(SDNode *N, SelectionDAG &DAG) {
+ unsigned Opc = N->getOpcode();
+ assert(Opc == ISD::AND || Opc == ISD::OR);
+ using namespace llvm::SDPatternMatch;
+ SDValue X, Y;
+ if (!sd_match(N, m_c_BinOp(Opc, m_Value(X),
+ m_Shuffle(m_InsertElt(m_Poison(),
+ m_Not(m_Value(Y)), m_Zero()),
+ m_Poison()))))
+ return SDValue();
+
+ EVT VT = N->getValueType(0);
+ SDLoc DL(N);
+ SDValue Not = DAG.getNOT(DL, DAG.getSplat(VT, DL, Y), VT);
+ return DAG.getNode(Opc, DL, VT, X, Not);
+}
+
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
const AArch64Subtarget *Subtarget,
const AArch64TargetLowering &TLI) {
@@ -20569,6 +20588,9 @@ static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
if (SDValue R = performANDORCSELCombine(N, DAG))
return R;
+ if (SDValue R = performANDORDUPNOTCombine(N, DAG))
+ return R;
+
return SDValue();
}
@@ -20775,6 +20797,9 @@ static SDValue performANDCombine(SDNode *N,
if (SDValue R = performANDSETCCCombine(N,DCI))
return R;
+ if (SDValue R = performANDORDUPNOTCombine(N, DAG))
+ return R;
+
if (!DAG.getTargetLoweringInfo().isTypeLegal(VT))
return SDValue();
diff --git a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
index 2d6d0ca124a58..e920539e0df40 100644
--- a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
+++ b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
@@ -3034,11 +3034,18 @@ define <8 x i16> @and_dup_not_v8i16_swapped(<8 x i16> %a, i16 %m) {
}
define <2 x i32> @and_dup_not_v2i32(<2 x i32> %a, i32 %m) {
-; CHECK-LABEL: and_dup_not_v2i32:
-; CHECK: // %bb.0:
-; CHECK-NEXT: dup v1.2s, w0
-; CHECK-NEXT: bic v0.8b, v0.8b, v1.8b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: and_dup_not_v2i32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.2s, w0
+; CHECK-SD-NEXT: bic v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: and_dup_not_v2i32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.2s, w8
+; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <2 x i32> poison, i32 %not, i64 0
%shuffle = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer
@@ -3047,11 +3054,18 @@ define <2 x i32> @and_dup_not_v2i32(<2 x i32> %a, i32 %m) {
}
define <2 x i32> @and_dup_not_v2i32_swapped(<2 x i32> %a, i32 %m) {
-; CHECK-LABEL: and_dup_not_v2i32_swapped:
-; CHECK: // %bb.0:
-; CHECK-NEXT: dup v1.2s, w0
-; CHECK-NEXT: bic v0.8b, v0.8b, v1.8b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: and_dup_not_v2i32_swapped:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.2s, w0
+; CHECK-SD-NEXT: bic v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: and_dup_not_v2i32_swapped:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.2s, w8
+; CHECK-GI-NEXT: and v0.8b, v1.8b, v0.8b
+; CHECK-GI-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <2 x i32> poison, i32 %not, i64 0
%shuffle = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer
@@ -3060,11 +3074,18 @@ define <2 x i32> @and_dup_not_v2i32_swapped(<2 x i32> %a, i32 %m) {
}
define <4 x i32> @and_dup_not_v4i32(<4 x i32> %a, i32 %m) {
-; CHECK-LABEL: and_dup_not_v4i32:
-; CHECK: // %bb.0:
-; CHECK-NEXT: dup v1.4s, w0
-; CHECK-NEXT: bic v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: and_dup_not_v4i32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.4s, w0
+; CHECK-SD-NEXT: bic v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: and_dup_not_v4i32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.4s, w8
+; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <4 x i32> poison, i32 %not, i64 0
%shuffle = shufflevector <4 x i32> %insert, <4 x i32> poison, <4 x i32> zeroinitializer
@@ -3073,11 +3094,18 @@ define <4 x i32> @and_dup_not_v4i32(<4 x i32> %a, i32 %m) {
}
define <4 x i32> @and_dup_not_v4i32_swapped(<4 x i32> %a, i32 %m) {
-; CHECK-LABEL: and_dup_not_v4i32_swapped:
-; CHECK: // %bb.0:
-; CHECK-NEXT: dup v1.4s, w0
-; CHECK-NEXT: bic v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: and_dup_not_v4i32_swapped:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.4s, w0
+; CHECK-SD-NEXT: bic v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: and_dup_not_v4i32_swapped:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.4s, w8
+; CHECK-GI-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-GI-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <4 x i32> poison, i32 %not, i64 0
%shuffle = shufflevector <4 x i32> %insert, <4 x i32> poison, <4 x i32> zeroinitializer
@@ -3086,11 +3114,18 @@ define <4 x i32> @and_dup_not_v4i32_swapped(<4 x i32> %a, i32 %m) {
}
define <2 x i64> @and_dup_not_v2i64(<2 x i64> %a, i64 %m) {
-; CHECK-LABEL: and_dup_not_v2i64:
-; CHECK: // %bb.0:
-; CHECK-NEXT: dup v1.2d, x0
-; CHECK-NEXT: bic v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: and_dup_not_v2i64:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.2d, x0
+; CHECK-SD-NEXT: bic v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: and_dup_not_v2i64:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn x8, x0
+; CHECK-GI-NEXT: dup v1.2d, x8
+; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT: ret
%not = xor i64 %m, -1
%insert = insertelement <2 x i64> poison, i64 %not, i64 0
%shuffle = shufflevector <2 x i64> %insert, <2 x i64> poison, <2 x i32> zeroinitializer
@@ -3259,11 +3294,18 @@ define <8 x i16> @or_dup_not_v8i16_swapped(<8 x i16> %a, i16 %m) {
}
define <2 x i32> @or_dup_not_v2i32(<2 x i32> %a, i32 %m) {
-; CHECK-LABEL: or_dup_not_v2i32:
-; CHECK: // %bb.0:
-; CHECK-NEXT: dup v1.2s, w0
-; CHECK-NEXT: orn v0.8b, v0.8b, v1.8b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: or_dup_not_v2i32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.2s, w0
+; CHECK-SD-NEXT: orn v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: or_dup_not_v2i32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.2s, w8
+; CHECK-GI-NEXT: orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <2 x i32> poison, i32 %not, i64 0
%shuffle = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer
@@ -3272,11 +3314,18 @@ define <2 x i32> @or_dup_not_v2i32(<2 x i32> %a, i32 %m) {
}
define <2 x i32> @or_dup_not_v2i32_swapped(<2 x i32> %a, i32 %m) {
-; CHECK-LABEL: or_dup_not_v2i32_swapped:
-; CHECK: // %bb.0:
-; CHECK-NEXT: dup v1.2s, w0
-; CHECK-NEXT: orn v0.8b, v0.8b, v1.8b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: or_dup_not_v2i32_swapped:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.2s, w0
+; CHECK-SD-NEXT: orn v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: or_dup_not_v2i32_swapped:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.2s, w8
+; CHECK-GI-NEXT: orr v0.8b, v1.8b, v0.8b
+; CHECK-GI-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <2 x i32> poison, i32 %not, i64 0
%shuffle = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer
@@ -3285,11 +3334,18 @@ define <2 x i32> @or_dup_not_v2i32_swapped(<2 x i32> %a, i32 %m) {
}
define <4 x i32> @or_dup_not_v4i32(<4 x i32> %a, i32 %m) {
-; CHECK-LABEL: or_dup_not_v4i32:
-; CHECK: // %bb.0:
-; CHECK-NEXT: dup v1.4s, w0
-; CHECK-NEXT: orn v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: or_dup_not_v4i32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.4s, w0
+; CHECK-SD-NEXT: orn v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: or_dup_not_v4i32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.4s, w8
+; CHECK-GI-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <4 x i32> poison, i32 %not, i64 0
%shuffle = shufflevector <4 x i32> %insert, <4 x i32> poison, <4 x i32> zeroinitializer
@@ -3298,11 +3354,18 @@ define <4 x i32> @or_dup_not_v4i32(<4 x i32> %a, i32 %m) {
}
define <4 x i32> @or_dup_not_v4i32_swapped(<4 x i32> %a, i32 %m) {
-; CHECK-LABEL: or_dup_not_v4i32_swapped:
-; CHECK: // %bb.0:
-; CHECK-NEXT: dup v1.4s, w0
-; CHECK-NEXT: orn v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: or_dup_not_v4i32_swapped:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.4s, w0
+; CHECK-SD-NEXT: orn v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: or_dup_not_v4i32_swapped:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn w8, w0
+; CHECK-GI-NEXT: dup v1.4s, w8
+; CHECK-GI-NEXT: orr v0.16b, v1.16b, v0.16b
+; CHECK-GI-NEXT: ret
%not = xor i32 %m, -1
%insert = insertelement <4 x i32> poison, i32 %not, i64 0
%shuffle = shufflevector <4 x i32> %insert, <4 x i32> poison, <4 x i32> zeroinitializer
@@ -3311,11 +3374,18 @@ define <4 x i32> @or_dup_not_v4i32_swapped(<4 x i32> %a, i32 %m) {
}
define <2 x i64> @or_dup_not_v2i64(<2 x i64> %a, i64 %m) {
-; CHECK-LABEL: or_dup_not_v2i64:
-; CHECK: // %bb.0:
-; CHECK-NEXT: dup v1.2d, x0
-; CHECK-NEXT: orn v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: or_dup_not_v2i64:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: dup v1.2d, x0
+; CHECK-SD-NEXT: orn v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: or_dup_not_v2i64:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mvn x8, x0
+; CHECK-GI-NEXT: dup v1.2d, x8
+; CHECK-GI-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT: ret
%not = xor i64 %m, -1
%insert = insertelement <2 x i64> poison, i64 %not, i64 0
%shuffle = shufflevector <2 x i64> %insert, <2 x i64> poison, <2 x i32> zeroinitializer
More information about the llvm-commits
mailing list