[llvm] [AArch64][InstCombine] xor(cmpne) -> cmpeq (PR #207007)
Matthew Devereau via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 3 01:28:48 PDT 2026
https://github.com/MDevereau updated https://github.com/llvm/llvm-project/pull/207007
>From d43de29e3cd4abdf9cd94c6fb8d026d5bb64bdd0 Mon Sep 17 00:00:00 2001
From: Matt Devereau <matthew.devereau at arm.com>
Date: Wed, 1 Jul 2026 14:13:50 +0000
Subject: [PATCH 1/3] [AArch64][InstCombine] Fold xor(cmpne(pg, v, 0), pg) into
cmpeq(pv, v, 0)
Created after initially trying as a DAGCombine in #206931.
---
.../AArch64/AArch64TargetTransformInfo.cpp | 35 ++++++++
.../AArch64/sve-intrinsic-opts-cmpne.ll | 84 +++++++++++++++++++
2 files changed, 119 insertions(+)
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index ee06217fc5d87..4ec910a4d409f 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -2142,10 +2142,45 @@ static std::optional<Instruction *> instCombineSVEDupX(InstCombiner &IC,
return IC.replaceInstUsesWith(II, Splat);
}
+static std::optional<Instruction *> instCombineXorSVECmpNE(InstCombiner &IC,
+ IntrinsicInst &II) {
+ if (!match(II.getOperand(2), m_Zero()) || !II.hasOneUse())
+ return std::nullopt;
+
+ auto *User = dyn_cast<Instruction>(*II.user_begin());
+ if (!User ||
+ (!match(User, m_Xor(m_Specific(&II), m_Specific(II.getOperand(0)))) &&
+ !match(User, m_Xor(m_Specific(II.getOperand(0)), m_Specific(&II)))))
+ return std::nullopt;
+
+ IC.Builder.SetInsertPoint(User);
+ Intrinsic::ID IID;
+ switch ((II.getIntrinsicID())) {
+ case Intrinsic::aarch64_sve_cmpne:
+ IID = Intrinsic::aarch64_sve_cmpeq;
+ break;
+ case Intrinsic::aarch64_sve_cmpne_wide:
+ IID = Intrinsic::aarch64_sve_cmpeq_wide;
+ break;
+ default:
+ return std::nullopt;
+ }
+
+ Value *CMPEQ = IC.Builder.CreateIntrinsic(
+ IID, II.getOperand(1)->getType(),
+ {II.getOperand(0), II.getOperand(1), II.getOperand(2)});
+ CMPEQ->takeName(User);
+ IC.replaceInstUsesWith(*User, CMPEQ);
+ return IC.eraseInstFromFunction(*User);
+}
+
static std::optional<Instruction *> instCombineSVECmpNE(InstCombiner &IC,
IntrinsicInst &II) {
LLVMContext &Ctx = II.getContext();
+ if (auto Res = instCombineXorSVECmpNE(IC, II))
+ return *Res;
+
if (!isAllActivePredicate(II.getArgOperand(0)))
return std::nullopt;
diff --git a/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-cmpne.ll b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-cmpne.ll
index bb3b3d069c7d1..dd6a11b07b7a1 100644
--- a/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-cmpne.ll
+++ b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-cmpne.ll
@@ -202,6 +202,88 @@ define <vscale x 2 x i1> @dupq_d_d() #0 {
ret <vscale x 2 x i1> %5
}
+define <vscale x 16 x i1> @not_cmpne(<vscale x 16 x i8> %vec, <vscale x 16 x i1> %pg) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne(
+; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[NOT:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpeq.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC]], <vscale x 16 x i8> zeroinitializer)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
+;
+ %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec, <vscale x 16 x i8> zeroinitializer)
+ %not = xor <vscale x 16 x i1> %cmp, %pg
+ ret <vscale x 16 x i1> %not
+}
+
+define <vscale x 16 x i1> @not_cmpne_true(<vscale x 16 x i8> %vec) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne_true(
+; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[NOT:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpeq.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[VEC]], <vscale x 16 x i8> zeroinitializer)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
+;
+ %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %vec, <vscale x 16 x i8> zeroinitializer)
+ %not = xor <vscale x 16 x i1> %cmp, splat (i1 true)
+ ret <vscale x 16 x i1> %not
+}
+
+define <vscale x 16 x i1> @not_cmpne_swapped_xor(<vscale x 16 x i8> %vec, <vscale x 16 x i1> %pg) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne_swapped_xor(
+; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[NOT:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpeq.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC]], <vscale x 16 x i8> zeroinitializer)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
+;
+ %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec, <vscale x 16 x i8> zeroinitializer)
+ %not = xor <vscale x 16 x i1> %pg, %cmp
+ ret <vscale x 16 x i1> %not
+}
+
+define <vscale x 16 x i1> @not_cmpne_wide(<vscale x 16 x i8> %vec, <vscale x 16 x i1> %pg) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne_wide(
+; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[NOT:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpeq.wide.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC]], <vscale x 2 x i64> zeroinitializer)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
+;
+ %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.wide.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec, <vscale x 2 x i64> zeroinitializer)
+ %not = xor <vscale x 16 x i1> %cmp, %pg
+ ret <vscale x 16 x i1> %not
+}
+
+define <vscale x 16 x i1> @not_cmpne_nonzero_rhs(<vscale x 16 x i8> %vec, <vscale x 16 x i1> %pg) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne_nonzero_rhs(
+; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CMP:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC]], <vscale x 16 x i8> splat (i8 1))
+; CHECK-NEXT: [[NOT:%.*]] = xor <vscale x 16 x i1> [[CMP]], [[PG]]
+; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
+;
+ %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec, <vscale x 16 x i8> splat (i8 1))
+ %not = xor <vscale x 16 x i1> %cmp, %pg
+ ret <vscale x 16 x i1> %not
+}
+
+define <vscale x 16 x i1> @not_cmpne_multiple_uses(<vscale x 16 x i8> %vec, <vscale x 16 x i1> %pg) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne_multiple_uses(
+; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CMP:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC]], <vscale x 16 x i8> zeroinitializer)
+; CHECK-NEXT: call void @use_nxv16i1(<vscale x 16 x i1> [[CMP]])
+; CHECK-NEXT: [[NOT:%.*]] = xor <vscale x 16 x i1> [[CMP]], [[PG]]
+; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
+;
+ %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec, <vscale x 16 x i8> zeroinitializer)
+ call void @use_nxv16i1(<vscale x 16 x i1> %cmp)
+ %not = xor <vscale x 16 x i1> %cmp, %pg
+ ret <vscale x 16 x i1> %not
+}
+
+define <vscale x 16 x i1> @not_cmpne_wrong_xor_operand(<vscale x 16 x i8> %vec, <vscale x 16 x i1> %pg) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne_wrong_xor_operand(
+; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CMP:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC]], <vscale x 16 x i8> zeroinitializer)
+; CHECK-NEXT: [[NOT:%.*]] = xor <vscale x 16 x i1> [[CMP]], splat (i1 true)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
+;
+ %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec, <vscale x 16 x i8> zeroinitializer)
+ %not = xor <vscale x 16 x i1> %cmp, splat (i1 true)
+ ret <vscale x 16 x i1> %not
+}
+
; Cases that cannot be converted
define <vscale x 2 x i1> @dupq_neg1() #0 {
@@ -451,4 +533,6 @@ declare <vscale x 2 x i1> @llvm.aarch64.sve.cmpne.nxv2i64(<vscale x 2 x i1>, <vs
declare <vscale x 2 x i64> @llvm.aarch64.sve.dup.x.nxv2i64(i64)
+declare void @use_nxv16i1(<vscale x 16 x i1>)
+
attributes #0 = { "target-features"="+sve" }
>From 413ab68c641be70932b8ed1604dac4cfa8026442 Mon Sep 17 00:00:00 2001
From: Matt Devereau <matthew.devereau at arm.com>
Date: Thu, 2 Jul 2026 11:09:08 +0000
Subject: [PATCH 2/3] address review comments
---
.../Target/AArch64/AArch64TargetTransformInfo.cpp | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index 4ec910a4d409f..2afa280848ec0 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -2147,13 +2147,10 @@ static std::optional<Instruction *> instCombineXorSVECmpNE(InstCombiner &IC,
if (!match(II.getOperand(2), m_Zero()) || !II.hasOneUse())
return std::nullopt;
- auto *User = dyn_cast<Instruction>(*II.user_begin());
- if (!User ||
- (!match(User, m_Xor(m_Specific(&II), m_Specific(II.getOperand(0)))) &&
- !match(User, m_Xor(m_Specific(II.getOperand(0)), m_Specific(&II)))))
+ auto *User = cast<Instruction>(*II.user_begin());
+ if (!match(User, m_c_Xor(m_Specific(&II), m_Specific(II.getOperand(0)))))
return std::nullopt;
- IC.Builder.SetInsertPoint(User);
Intrinsic::ID IID;
switch ((II.getIntrinsicID())) {
case Intrinsic::aarch64_sve_cmpne:
@@ -2166,12 +2163,13 @@ static std::optional<Instruction *> instCombineXorSVECmpNE(InstCombiner &IC,
return std::nullopt;
}
+ IC.Builder.SetInsertPoint(User);
Value *CMPEQ = IC.Builder.CreateIntrinsic(
IID, II.getOperand(1)->getType(),
{II.getOperand(0), II.getOperand(1), II.getOperand(2)});
- CMPEQ->takeName(User);
IC.replaceInstUsesWith(*User, CMPEQ);
- return IC.eraseInstFromFunction(*User);
+ IC.eraseInstFromFunction(*User);
+ return &II;
}
static std::optional<Instruction *> instCombineSVECmpNE(InstCombiner &IC,
>From c2b607417bbea7f05c982d8abd25926f97c9fa6f Mon Sep 17 00:00:00 2001
From: Matt Devereau <matthew.devereau at arm.com>
Date: Fri, 3 Jul 2026 08:07:16 +0000
Subject: [PATCH 3/3] remove zero constraint
---
.../AArch64/AArch64TargetTransformInfo.cpp | 7 +-
.../AArch64/sve-intrinsic-opts-cmpne.ll | 69 ++++++-------------
2 files changed, 26 insertions(+), 50 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index 2afa280848ec0..f5d4f906be09f 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -2142,17 +2142,18 @@ static std::optional<Instruction *> instCombineSVEDupX(InstCombiner &IC,
return IC.replaceInstUsesWith(II, Splat);
}
+// xor(cmpne(%pg, %lhs, %rhs), %pg)
+// -> cmpeq(%pg, %lhs, %rhs)
static std::optional<Instruction *> instCombineXorSVECmpNE(InstCombiner &IC,
IntrinsicInst &II) {
- if (!match(II.getOperand(2), m_Zero()) || !II.hasOneUse())
+ if (!II.hasOneUse())
return std::nullopt;
-
auto *User = cast<Instruction>(*II.user_begin());
if (!match(User, m_c_Xor(m_Specific(&II), m_Specific(II.getOperand(0)))))
return std::nullopt;
Intrinsic::ID IID;
- switch ((II.getIntrinsicID())) {
+ switch (II.getIntrinsicID()) {
case Intrinsic::aarch64_sve_cmpne:
IID = Intrinsic::aarch64_sve_cmpeq;
break;
diff --git a/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-cmpne.ll b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-cmpne.ll
index dd6a11b07b7a1..e803572a06523 100644
--- a/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-cmpne.ll
+++ b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-cmpne.ll
@@ -202,84 +202,61 @@ define <vscale x 2 x i1> @dupq_d_d() #0 {
ret <vscale x 2 x i1> %5
}
-define <vscale x 16 x i1> @not_cmpne(<vscale x 16 x i8> %vec, <vscale x 16 x i1> %pg) #0 {
+define <vscale x 16 x i1> @not_cmpne(<vscale x 16 x i8> %vec_a, <vscale x 16 x i8> %vec_b, <vscale x 16 x i1> %pg) #0 {
; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne(
-; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[NOT:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpeq.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC]], <vscale x 16 x i8> zeroinitializer)
+; CHECK-SAME: <vscale x 16 x i8> [[VEC_A:%.*]], <vscale x 16 x i8> [[VEC_B:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[NOT:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpeq.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC_A]], <vscale x 16 x i8> [[VEC_B]])
; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
;
- %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec, <vscale x 16 x i8> zeroinitializer)
+ %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec_a, <vscale x 16 x i8> %vec_b)
%not = xor <vscale x 16 x i1> %cmp, %pg
ret <vscale x 16 x i1> %not
}
-define <vscale x 16 x i1> @not_cmpne_true(<vscale x 16 x i8> %vec) #0 {
-; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne_true(
-; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[NOT:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpeq.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[VEC]], <vscale x 16 x i8> zeroinitializer)
-; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
-;
- %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %vec, <vscale x 16 x i8> zeroinitializer)
- %not = xor <vscale x 16 x i1> %cmp, splat (i1 true)
- ret <vscale x 16 x i1> %not
-}
-
-define <vscale x 16 x i1> @not_cmpne_swapped_xor(<vscale x 16 x i8> %vec, <vscale x 16 x i1> %pg) #0 {
+define <vscale x 16 x i1> @not_cmpne_swapped_xor(<vscale x 16 x i8> %vec_a, <vscale x 16 x i8> %vec_b, <vscale x 16 x i1> %pg) #0 {
; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne_swapped_xor(
-; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[NOT:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpeq.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC]], <vscale x 16 x i8> zeroinitializer)
+; CHECK-SAME: <vscale x 16 x i8> [[VEC_A:%.*]], <vscale x 16 x i8> [[VEC_B:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[NOT:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpeq.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC_A]], <vscale x 16 x i8> [[VEC_B]])
; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
;
- %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec, <vscale x 16 x i8> zeroinitializer)
+ %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec_a, <vscale x 16 x i8> %vec_b)
%not = xor <vscale x 16 x i1> %pg, %cmp
ret <vscale x 16 x i1> %not
}
-define <vscale x 16 x i1> @not_cmpne_wide(<vscale x 16 x i8> %vec, <vscale x 16 x i1> %pg) #0 {
+define <vscale x 16 x i1> @not_cmpne_wide(<vscale x 16 x i8> %vec_a, <vscale x 2 x i64> %vec_b, <vscale x 16 x i1> %pg) #0 {
; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne_wide(
-; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[NOT:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpeq.wide.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC]], <vscale x 2 x i64> zeroinitializer)
-; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
-;
- %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.wide.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec, <vscale x 2 x i64> zeroinitializer)
- %not = xor <vscale x 16 x i1> %cmp, %pg
- ret <vscale x 16 x i1> %not
-}
-
-define <vscale x 16 x i1> @not_cmpne_nonzero_rhs(<vscale x 16 x i8> %vec, <vscale x 16 x i1> %pg) #0 {
-; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne_nonzero_rhs(
-; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[CMP:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC]], <vscale x 16 x i8> splat (i8 1))
-; CHECK-NEXT: [[NOT:%.*]] = xor <vscale x 16 x i1> [[CMP]], [[PG]]
+; CHECK-SAME: <vscale x 16 x i8> [[VEC_A:%.*]], <vscale x 2 x i64> [[VEC_B:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[NOT:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpeq.wide.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC_A]], <vscale x 2 x i64> [[VEC_B]])
; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
;
- %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec, <vscale x 16 x i8> splat (i8 1))
+ %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.wide.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec_a, <vscale x 2 x i64> %vec_b)
%not = xor <vscale x 16 x i1> %cmp, %pg
ret <vscale x 16 x i1> %not
}
-define <vscale x 16 x i1> @not_cmpne_multiple_uses(<vscale x 16 x i8> %vec, <vscale x 16 x i1> %pg) #0 {
+define <vscale x 16 x i1> @not_cmpne_multiple_uses(<vscale x 16 x i8> %vec_a, <vscale x 16 x i8> %vec_b, <vscale x 16 x i1> %pg) #0 {
; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne_multiple_uses(
-; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[CMP:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC]], <vscale x 16 x i8> zeroinitializer)
-; CHECK-NEXT: call void @use_nxv16i1(<vscale x 16 x i1> [[CMP]])
+; CHECK-SAME: <vscale x 16 x i8> [[VEC_A:%.*]], <vscale x 16 x i8> [[VEC_B:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CMP:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC_A]], <vscale x 16 x i8> [[VEC_B]])
+; CHECK-NEXT: call void (...) @llvm.fake.use(<vscale x 16 x i1> [[CMP]])
; CHECK-NEXT: [[NOT:%.*]] = xor <vscale x 16 x i1> [[CMP]], [[PG]]
; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
;
- %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec, <vscale x 16 x i8> zeroinitializer)
- call void @use_nxv16i1(<vscale x 16 x i1> %cmp)
+ %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec_a, <vscale x 16 x i8> %vec_b)
+ call void (...) @llvm.fake.use(<vscale x 16 x i1> %cmp)
%not = xor <vscale x 16 x i1> %cmp, %pg
ret <vscale x 16 x i1> %not
}
-define <vscale x 16 x i1> @not_cmpne_wrong_xor_operand(<vscale x 16 x i8> %vec, <vscale x 16 x i1> %pg) #0 {
+define <vscale x 16 x i1> @not_cmpne_wrong_xor_operand(<vscale x 16 x i8> %vec_a, <vscale x 16 x i8> %vec_b, <vscale x 16 x i1> %pg) #0 {
; CHECK-LABEL: define <vscale x 16 x i1> @not_cmpne_wrong_xor_operand(
-; CHECK-SAME: <vscale x 16 x i8> [[VEC:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[CMP:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC]], <vscale x 16 x i8> zeroinitializer)
+; CHECK-SAME: <vscale x 16 x i8> [[VEC_A:%.*]], <vscale x 16 x i8> [[VEC_B:%.*]], <vscale x 16 x i1> [[PG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CMP:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[VEC_A]], <vscale x 16 x i8> [[VEC_B]])
; CHECK-NEXT: [[NOT:%.*]] = xor <vscale x 16 x i1> [[CMP]], splat (i1 true)
; CHECK-NEXT: ret <vscale x 16 x i1> [[NOT]]
;
- %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec, <vscale x 16 x i8> zeroinitializer)
+ %cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %vec_a, <vscale x 16 x i8> %vec_b)
%not = xor <vscale x 16 x i1> %cmp, splat (i1 true)
ret <vscale x 16 x i1> %not
}
@@ -533,6 +510,4 @@ declare <vscale x 2 x i1> @llvm.aarch64.sve.cmpne.nxv2i64(<vscale x 2 x i1>, <vs
declare <vscale x 2 x i64> @llvm.aarch64.sve.dup.x.nxv2i64(i64)
-declare void @use_nxv16i1(<vscale x 16 x i1>)
-
attributes #0 = { "target-features"="+sve" }
More information about the llvm-commits
mailing list