[AArch64][InstCombine] Fold zext cmpne umin boolean trees#209234
Open
MDevereau wants to merge 1 commit into
Open
[AArch64][InstCombine] Fold zext cmpne umin boolean trees#209234MDevereau wants to merge 1 commit into
MDevereau wants to merge 1 commit into
Conversation
Fold an all-active umin tree of zext(cmpne(0, umin)) nodes:
zext(cmpne(0, umin(zext(cmpne(0, umin(%a, %b)))
zext(cmpne(0, umin(%c, %d))))))
->
zext(cmpne(0, umin(umin(%a, %b),
umin(%c, %d))))
|
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-backend-aarch64 Author: Matthew Devereau (MDevereau) ChangesFold an all-active umin tree of zext(cmpne(0, umin)) nodes: Patch is 21.09 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/209234.diff 2 Files Affected:
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index 9e1a0960617a5..024f9efaf18f2 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -2205,6 +2205,69 @@ static std::optional<Instruction *> instCombineZExtSVECmpNE(InstCombiner &IC,
return std::nullopt;
}
+static std::optional<Instruction *> isZextedCmpneUMin(Value *V) {
+ Instruction *CmpNE;
+ if (!match(V, m_ZExt(m_Instruction(CmpNE))))
+ return std::nullopt;
+
+ Value *Pg;
+ Instruction *UMin;
+ if (!match(CmpNE, m_Intrinsic<Intrinsic::aarch64_sve_cmpne>(
+ m_Value(Pg), m_Zero(), m_Instruction(UMin))) ||
+ !isAllActivePredicate(Pg) || V->getType() != UMin->getType())
+ return std::nullopt;
+
+ Value *UMinPg;
+ if (!match(UMin, m_Intrinsic<Intrinsic::aarch64_sve_umin_u>(
+ m_Value(UMinPg), m_Value(), m_Value())) ||
+ !isAllActivePredicate(UMinPg))
+ return std::nullopt;
+
+ return UMin;
+}
+
+// InstCombine:
+// zext(cmpne(0, umin(zext(cmpne(0, umin(%a, %b)))
+// zext(cmpne(0, umin(%c, %d))))))
+// ->
+// zext(cmpne(0, umin(umin(%a, %b),
+// umin(%c, %d))))
+//
+// To remove redundant ZExt and CmpNE intrinsics.
+static std::optional<Instruction *>
+instCombineZExtCmpNEUMinTree(InstCombiner &IC, IntrinsicInst &II) {
+ Value *Pg = II.getOperand(0);
+ if (!isAllActivePredicate(Pg) || !II.hasOneUse())
+ return std::nullopt;
+
+ auto ZExt = cast<Instruction>(*II.user_begin());
+ auto _UMin = isZextedCmpneUMin(ZExt);
+ if (!_UMin)
+ return std::nullopt;
+ Instruction *UMin = *_UMin;
+ // Check for outer UMin single use to avoid generating an extra UMin
+ if (!UMin->hasOneUse())
+ return std::nullopt;
+
+ auto LhsUMin = isZextedCmpneUMin(UMin->getOperand(1));
+ auto RhsUMin = isZextedCmpneUMin(UMin->getOperand(2));
+ if (!LhsUMin || !RhsUMin)
+ return std::nullopt;
+
+ IC.Builder.SetInsertPoint(ZExt);
+ Type *Ty = UMin->getType();
+ Value *NewUMin = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_umin_u, Ty,
+ {Pg, *LhsUMin, *RhsUMin});
+ Value *NewCmpne =
+ IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_cmpne, Ty,
+ {Pg, ConstantInt::getNullValue(Ty), NewUMin});
+ Value *NewZext = IC.Builder.CreateZExt(NewCmpne, Ty);
+
+ IC.replaceInstUsesWith(*ZExt, NewZext);
+ IC.eraseInstFromFunction(*ZExt);
+ return &II;
+}
+
static std::optional<Instruction *> instCombineSVECmpNE(InstCombiner &IC,
IntrinsicInst &II) {
LLVMContext &Ctx = II.getContext();
@@ -2215,6 +2278,9 @@ static std::optional<Instruction *> instCombineSVECmpNE(InstCombiner &IC,
if (auto Res = instCombineZExtSVECmpNE(IC, II))
return Res;
+ if (auto Res = instCombineZExtCmpNEUMinTree(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 11e6e0089293a..a434ad086d891 100644
--- a/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-cmpne.ll
+++ b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-cmpne.ll
@@ -573,6 +573,160 @@ define <vscale x 16 x i1> @dupq_b_idx(i64 %idx) #0 {
ret <vscale x 16 x i1> %5
}
+define <vscale x 16 x i8> @logical_bool_tree_i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b, <vscale x 16 x i8> %c, <vscale x 16 x i8> %d) #0 {
+; CHECK-LABEL: define <vscale x 16 x i8> @logical_bool_tree_i8(
+; CHECK-SAME: <vscale x 16 x i8> [[A:%.*]], <vscale x 16 x i8> [[B:%.*]], <vscale x 16 x i8> [[C:%.*]], <vscale x 16 x i8> [[D:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[AB:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[A]], <vscale x 16 x i8> [[B]])
+; CHECK-NEXT: [[CD:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[C]], <vscale x 16 x i8> [[D]])
+; CHECK-NEXT: [[ABCD:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[AB]], <vscale x 16 x i8> [[CD]])
+; CHECK-NEXT: [[ABCD_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> zeroinitializer, <vscale x 16 x i8> [[ABCD]])
+; CHECK-NEXT: [[ABCD_BOOL:%.*]] = zext <vscale x 16 x i1> [[ABCD_CMP]] to <vscale x 16 x i8>
+; CHECK-NEXT: ret <vscale x 16 x i8> [[ABCD_BOOL]]
+;
+ %ab = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
+ %ab.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> zeroinitializer, <vscale x 16 x i8> %ab)
+ %ab.bool = zext <vscale x 16 x i1> %ab.cmp to <vscale x 16 x i8>
+ %cd = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %c, <vscale x 16 x i8> %d)
+ %cd.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> zeroinitializer, <vscale x 16 x i8> %cd)
+ %cd.bool = zext <vscale x 16 x i1> %cd.cmp to <vscale x 16 x i8>
+ %abcd = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %ab.bool, <vscale x 16 x i8> %cd.bool)
+ %abcd.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> zeroinitializer, <vscale x 16 x i8> %abcd)
+ %abcd.bool = zext <vscale x 16 x i1> %abcd.cmp to <vscale x 16 x i8>
+ ret <vscale x 16 x i8> %abcd.bool
+}
+
+define <vscale x 16 x i8> @logical_bool_tree_outer_umin_extra_use_i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b, <vscale x 16 x i8> %c, <vscale x 16 x i8> %d) #0 {
+; CHECK-LABEL: define <vscale x 16 x i8> @logical_bool_tree_outer_umin_extra_use_i8(
+; CHECK-SAME: <vscale x 16 x i8> [[A:%.*]], <vscale x 16 x i8> [[B:%.*]], <vscale x 16 x i8> [[C:%.*]], <vscale x 16 x i8> [[D:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[AB:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[A]], <vscale x 16 x i8> [[B]])
+; CHECK-NEXT: [[AB_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> zeroinitializer, <vscale x 16 x i8> [[AB]])
+; CHECK-NEXT: [[AB_BOOL:%.*]] = zext <vscale x 16 x i1> [[AB_CMP]] to <vscale x 16 x i8>
+; CHECK-NEXT: [[CD:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[C]], <vscale x 16 x i8> [[D]])
+; CHECK-NEXT: [[CD_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> zeroinitializer, <vscale x 16 x i8> [[CD]])
+; CHECK-NEXT: [[CD_BOOL:%.*]] = zext <vscale x 16 x i1> [[CD_CMP]] to <vscale x 16 x i8>
+; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[AB_BOOL]], <vscale x 16 x i8> [[CD_BOOL]])
+; CHECK-NEXT: [[ABCD_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> zeroinitializer, <vscale x 16 x i8> [[TMP1]])
+; CHECK-NEXT: [[ABCD_BOOL:%.*]] = zext <vscale x 16 x i1> [[ABCD_CMP]] to <vscale x 16 x i8>
+; CHECK-NEXT: call void (...) @llvm.fake.use(<vscale x 16 x i8> [[TMP1]])
+; CHECK-NEXT: ret <vscale x 16 x i8> [[ABCD_BOOL]]
+;
+ %ab = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
+ %ab.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> zeroinitializer, <vscale x 16 x i8> %ab)
+ %ab.bool = zext <vscale x 16 x i1> %ab.cmp to <vscale x 16 x i8>
+ %cd = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %c, <vscale x 16 x i8> %d)
+ %cd.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> zeroinitializer, <vscale x 16 x i8> %cd)
+ %cd.bool = zext <vscale x 16 x i1> %cd.cmp to <vscale x 16 x i8>
+ %abcd = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %ab.bool, <vscale x 16 x i8> %cd.bool)
+ %abcd.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> zeroinitializer, <vscale x 16 x i8> %abcd)
+ %abcd.bool = zext <vscale x 16 x i1> %abcd.cmp to <vscale x 16 x i8>
+ call void (...) @llvm.fake.use(<vscale x 16 x i8> %abcd)
+ ret <vscale x 16 x i8> %abcd.bool
+}
+
+define <vscale x 16 x i8> @logical_bool_tree_nonzero_outer_cmp_i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b, <vscale x 16 x i8> %c, <vscale x 16 x i8> %d, <vscale x 16 x i8> %mask) #0 {
+; CHECK-LABEL: define <vscale x 16 x i8> @logical_bool_tree_nonzero_outer_cmp_i8(
+; CHECK-SAME: <vscale x 16 x i8> [[A:%.*]], <vscale x 16 x i8> [[B:%.*]], <vscale x 16 x i8> [[C:%.*]], <vscale x 16 x i8> [[D:%.*]], <vscale x 16 x i8> [[MASK:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[AB:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[A]], <vscale x 16 x i8> [[B]])
+; CHECK-NEXT: [[AB_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> zeroinitializer, <vscale x 16 x i8> [[AB]])
+; CHECK-NEXT: [[AB_BOOL:%.*]] = zext <vscale x 16 x i1> [[AB_CMP]] to <vscale x 16 x i8>
+; CHECK-NEXT: [[CD:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[C]], <vscale x 16 x i8> [[D]])
+; CHECK-NEXT: [[CD_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> zeroinitializer, <vscale x 16 x i8> [[CD]])
+; CHECK-NEXT: [[CD_BOOL:%.*]] = zext <vscale x 16 x i1> [[CD_CMP]] to <vscale x 16 x i8>
+; CHECK-NEXT: [[ABCD:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[AB_BOOL]], <vscale x 16 x i8> [[CD_BOOL]])
+; CHECK-NEXT: [[ABCD_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> [[MASK]], <vscale x 16 x i8> [[ABCD]])
+; CHECK-NEXT: [[ABCD_BOOL:%.*]] = zext <vscale x 16 x i1> [[ABCD_CMP]] to <vscale x 16 x i8>
+; CHECK-NEXT: ret <vscale x 16 x i8> [[ABCD_BOOL]]
+;
+ %ab = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
+ %ab.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> zeroinitializer, <vscale x 16 x i8> %ab)
+ %ab.bool = zext <vscale x 16 x i1> %ab.cmp to <vscale x 16 x i8>
+ %cd = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %c, <vscale x 16 x i8> %d)
+ %cd.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> zeroinitializer, <vscale x 16 x i8> %cd)
+ %cd.bool = zext <vscale x 16 x i1> %cd.cmp to <vscale x 16 x i8>
+ %abcd = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %ab.bool, <vscale x 16 x i8> %cd.bool)
+ %abcd.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> %mask, <vscale x 16 x i8> %abcd)
+ %abcd.bool = zext <vscale x 16 x i1> %abcd.cmp to <vscale x 16 x i8>
+ ret <vscale x 16 x i8> %abcd.bool
+}
+
+define <vscale x 16 x i8> @logical_bool_tree_inactive_predicate_i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %a, <vscale x 16 x i8> %b, <vscale x 16 x i8> %c, <vscale x 16 x i8> %d) #0 {
+; CHECK-LABEL: define <vscale x 16 x i8> @logical_bool_tree_inactive_predicate_i8(
+; CHECK-SAME: <vscale x 16 x i1> [[PG:%.*]], <vscale x 16 x i8> [[A:%.*]], <vscale x 16 x i8> [[B:%.*]], <vscale x 16 x i8> [[C:%.*]], <vscale x 16 x i8> [[D:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[AB:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[A]], <vscale x 16 x i8> [[B]])
+; CHECK-NEXT: [[AB_CMP:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> zeroinitializer, <vscale x 16 x i8> [[AB]])
+; CHECK-NEXT: [[AB_BOOL:%.*]] = zext <vscale x 16 x i1> [[AB_CMP]] to <vscale x 16 x i8>
+; CHECK-NEXT: [[CD:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[C]], <vscale x 16 x i8> [[D]])
+; CHECK-NEXT: [[CD_CMP:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> zeroinitializer, <vscale x 16 x i8> [[CD]])
+; CHECK-NEXT: [[CD_BOOL:%.*]] = zext <vscale x 16 x i1> [[CD_CMP]] to <vscale x 16 x i8>
+; CHECK-NEXT: [[ABCD:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[AB_BOOL]], <vscale x 16 x i8> [[CD_BOOL]])
+; CHECK-NEXT: [[ABCD_CMP:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> zeroinitializer, <vscale x 16 x i8> [[ABCD]])
+; CHECK-NEXT: [[ABCD_BOOL:%.*]] = zext <vscale x 16 x i1> [[ABCD_CMP]] to <vscale x 16 x i8>
+; CHECK-NEXT: ret <vscale x 16 x i8> [[ABCD_BOOL]]
+;
+ %ab = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
+ %ab.cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> zeroinitializer, <vscale x 16 x i8> %ab)
+ %ab.bool = zext <vscale x 16 x i1> %ab.cmp to <vscale x 16 x i8>
+ %cd = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %c, <vscale x 16 x i8> %d)
+ %cd.cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> zeroinitializer, <vscale x 16 x i8> %cd)
+ %cd.bool = zext <vscale x 16 x i1> %cd.cmp to <vscale x 16 x i8>
+ %abcd = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %ab.bool, <vscale x 16 x i8> %cd.bool)
+ %abcd.cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> zeroinitializer, <vscale x 16 x i8> %abcd)
+ %abcd.bool = zext <vscale x 16 x i1> %abcd.cmp to <vscale x 16 x i8>
+ ret <vscale x 16 x i8> %abcd.bool
+}
+
+define <vscale x 16 x i16> @logical_bool_tree_wide_final_zext_i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b, <vscale x 16 x i8> %c, <vscale x 16 x i8> %d) #0 {
+; CHECK-LABEL: define <vscale x 16 x i16> @logical_bool_tree_wide_final_zext_i8(
+; CHECK-SAME: <vscale x 16 x i8> [[A:%.*]], <vscale x 16 x i8> [[B:%.*]], <vscale x 16 x i8> [[C:%.*]], <vscale x 16 x i8> [[D:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[AB:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[A]], <vscale x 16 x i8> [[B]])
+; CHECK-NEXT: [[AB_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> zeroinitializer, <vscale x 16 x i8> [[AB]])
+; CHECK-NEXT: [[AB_BOOL:%.*]] = zext <vscale x 16 x i1> [[AB_CMP]] to <vscale x 16 x i8>
+; CHECK-NEXT: [[CD:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[C]], <vscale x 16 x i8> [[D]])
+; CHECK-NEXT: [[CD_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> zeroinitializer, <vscale x 16 x i8> [[CD]])
+; CHECK-NEXT: [[CD_BOOL:%.*]] = zext <vscale x 16 x i1> [[CD_CMP]] to <vscale x 16 x i8>
+; CHECK-NEXT: [[ABCD:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[AB_BOOL]], <vscale x 16 x i8> [[CD_BOOL]])
+; CHECK-NEXT: [[ABCD_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> zeroinitializer, <vscale x 16 x i8> [[ABCD]])
+; CHECK-NEXT: [[ABCD_BOOL:%.*]] = zext <vscale x 16 x i1> [[ABCD_CMP]] to <vscale x 16 x i16>
+; CHECK-NEXT: ret <vscale x 16 x i16> [[ABCD_BOOL]]
+;
+ %ab = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
+ %ab.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> zeroinitializer, <vscale x 16 x i8> %ab)
+ %ab.bool = zext <vscale x 16 x i1> %ab.cmp to <vscale x 16 x i8>
+ %cd = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %c, <vscale x 16 x i8> %d)
+ %cd.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> zeroinitializer, <vscale x 16 x i8> %cd)
+ %cd.bool = zext <vscale x 16 x i1> %cd.cmp to <vscale x 16 x i8>
+ %abcd = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %ab.bool, <vscale x 16 x i8> %cd.bool)
+ %abcd.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> zeroinitializer, <vscale x 16 x i8> %abcd)
+ %abcd.bool = zext <vscale x 16 x i1> %abcd.cmp to <vscale x 16 x i16>
+ ret <vscale x 16 x i16> %abcd.bool
+}
+
+define <vscale x 16 x i16> @logical_bool_tree_wide_inner_zext_i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b, <vscale x 16 x i8> %c, <vscale x 16 x i8> %d) #0 {
+; CHECK-LABEL: define <vscale x 16 x i16> @logical_bool_tree_wide_inner_zext_i8(
+; CHECK-SAME: <vscale x 16 x i8> [[A:%.*]], <vscale x 16 x i8> [[B:%.*]], <vscale x 16 x i8> [[C:%.*]], <vscale x 16 x i8> [[D:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[AB:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[A]], <vscale x 16 x i8> [[B]])
+; CHECK-NEXT: [[AB_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> zeroinitializer, <vscale x 16 x i8> [[AB]])
+; CHECK-NEXT: [[AB_BOOL:%.*]] = zext <vscale x 16 x i1> [[AB_CMP]] to <vscale x 16 x i16>
+; CHECK-NEXT: [[CD:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> [[C]], <vscale x 16 x i8> [[D]])
+; CHECK-NEXT: [[CD_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> zeroinitializer, <vscale x 16 x i8> [[CD]])
+; CHECK-NEXT: [[CD_BOOL:%.*]] = zext <vscale x 16 x i1> [[CD_CMP]] to <vscale x 16 x i16>
+; CHECK-NEXT: [[ABCD:%.*]] = call <vscale x 16 x i16> @llvm.aarch64.sve.umin.u.nxv16i16(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i16> [[AB_BOOL]], <vscale x 16 x i16> [[CD_BOOL]])
+; CHECK-NEXT: [[ABCD_CMP:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i16(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i16> zeroinitializer, <vscale x 16 x i16> [[ABCD]])
+; CHECK-NEXT: [[ABCD_BOOL:%.*]] = zext <vscale x 16 x i1> [[ABCD_CMP]] to <vscale x 16 x i16>
+; CHECK-NEXT: ret <vscale x 16 x i16> [[ABCD_BOOL]]
+;
+ %ab = call <vscale x 16 x i8> @llvm.aarch64.sve.umin.u.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
+ %ab.cmp = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpne.nxv16i8(<vscale x 16 x i1> splat (i1 true), <vscale x...
[truncated]
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fold an all-active umin tree of zext(cmpne(0, umin)) nodes: