[llvm] [AArch64] Optimize lowering of i1 vector reduction (PR #187912)
Cheng Lingfei via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 19 02:10:02 PDT 2026
https://github.com/clingfei updated https://github.com/llvm/llvm-project/pull/187912
>From 83c7bbb461f78a25ba62c13341c74b2300746819 Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Sun, 22 Mar 2026 14:12:21 +0800
Subject: [PATCH 1/6] [AArch64] Optimize lowering of i1 vector reduction
---
.../Target/AArch64/AArch64ISelLowering.cpp | 95 ++++++++++++++++++-
.../AArch64/bool-vector-bitcast-compare.ll | 84 ++++++++++++++++
.../test/CodeGen/AArch64/dag-combine-setcc.ll | 60 ++++++------
.../illegal-floating-point-vector-compares.ll | 24 ++---
llvm/test/CodeGen/AArch64/neon-anyof-splat.ll | 24 ++---
5 files changed, 230 insertions(+), 57 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/bool-vector-bitcast-compare.ll
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 66c22db0491d1..8535937402bd5 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -1151,8 +1151,9 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
setTargetDAGCombine({ISD::FP_TO_SINT, ISD::FP_TO_UINT, ISD::FP_TO_SINT_SAT,
ISD::FP_TO_UINT_SAT, ISD::FADD});
- // Try and combine setcc with csel
+ // Try and combine setcc/select_cc with csel and bool-vector bitcasts.
setTargetDAGCombine(ISD::SETCC);
+ setTargetDAGCombine(ISD::SELECT_CC);
setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN);
@@ -25505,6 +25506,47 @@ static EVT tryGetOriginalBoolVectorType(SDValue Op, int Depth = 0) {
return BaseVT;
}
+static bool getBoolVectorBitcastCompare(SDValue Vec, SDValue RHS,
+ const SDLoc &DL, SelectionDAG &DAG,
+ SDValue &CompareLHS,
+ SDValue &CompareRHS) {
+ EVT VecVT = Vec.getValueType();
+ assert(VecVT.isFixedLengthVector() && VecVT.getVectorElementType() == MVT::i1 &&
+ "Expected a fixed-length bool vector");
+
+ unsigned NumElts = VecVT.getVectorNumElements();
+ if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16)
+ return false;
+
+ EVT CompareVecVT = tryGetOriginalBoolVectorType(Vec);
+ if (!CompareVecVT.isSimple() || CompareVecVT.getSizeInBits() > 128) {
+ unsigned BitsPerElement = std::max(64 / NumElts, 8u);
+ CompareVecVT = MVT::getVectorVT(MVT::getIntegerVT(BitsPerElement), NumElts);
+ }
+ CompareVecVT = CompareVecVT.changeVectorElementTypeToInteger();
+
+ if (CompareVecVT.getSizeInBits() > 128)
+ return false;
+
+ SDValue CompareBits = DAG.getSExtOrTrunc(Vec, DL, CompareVecVT);
+
+ if (CompareVecVT.getSizeInBits() == 64) {
+ CompareLHS = DAG.getBitcast(MVT::i64, CompareBits);
+ } else {
+ SDValue Lo, Hi;
+ std::tie(Lo, Hi) = DAG.SplitVector(CompareBits, DL);
+
+ unsigned CombineOpc = isNullConstant(RHS) ? ISD::OR : ISD::AND;
+ CompareLHS =
+ DAG.getNode(CombineOpc, DL, MVT::i64, DAG.getBitcast(MVT::i64, Lo),
+ DAG.getBitcast(MVT::i64, Hi));
+ }
+
+ CompareRHS = isNullConstant(RHS) ? DAG.getConstant(0, DL, MVT::i64)
+ : DAG.getAllOnesConstant(DL, MVT::i64);
+ return true;
+}
+
// When converting a <N x iX> vector to <N x i1> to store or use as a scalar
// iN, we can use a trick that extracts the i^th bit from the i^th element and
// then performs a vector add to get a scalar bitmask. This requires that each
@@ -27190,10 +27232,9 @@ static SDValue performSETCCCombine(SDNode *N,
}
}
- // setcc (iN (bitcast (vNi1 X))), 0, (eq|ne)
- // ==> setcc (iN (zext (i1 (vecreduce_or (vNi1 X))))), 0, (eq|ne)
- // setcc (iN (bitcast (vNi1 X))), -1, (eq|ne)
- // ==> setcc (iN (sext (i1 (vecreduce_and (vNi1 X))))), -1, (eq|ne)
+ // When a bool vector bitcast is only compared against zero or all ones, it
+ // is enough to test a widened scalar view of the comparison bits. This
+ // avoids materializing the packed bitmask via vectorToScalarBitmask().
if (DCI.isBeforeLegalize() && VT.isScalarInteger() &&
(Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
(isNullConstant(RHS) || isAllOnesConstant(RHS)) &&
@@ -27202,6 +27243,11 @@ static SDValue performSETCCCombine(SDNode *N,
EVT FromVT = LHS->getOperand(0).getValueType();
if (FromVT.isFixedLengthVector() &&
FromVT.getVectorElementType() == MVT::i1) {
+ SDValue CompareLHS, CompareRHS;
+ if (getBoolVectorBitcastCompare(LHS.getOperand(0), RHS, DL, DAG,
+ CompareLHS, CompareRHS))
+ return DAG.getSetCC(DL, VT, CompareLHS, CompareRHS, Cond);
+
bool IsNull = isNullConstant(RHS);
LHS = DAG.getNode(IsNull ? ISD::VECREDUCE_OR : ISD::VECREDUCE_AND,
DL, MVT::i1, LHS->getOperand(0));
@@ -27228,6 +27274,43 @@ static SDValue performSETCCCombine(SDNode *N,
return SDValue();
}
+static SDValue performSELECT_CCCombine(SDNode *N,
+ TargetLowering::DAGCombinerInfo &DCI,
+ SelectionDAG &DAG) {
+ assert(N->getOpcode() == ISD::SELECT_CC && "Unexpected opcode!");
+
+ if (!DCI.isBeforeLegalize())
+ return SDValue();
+
+ SDValue LHS = N->getOperand(0);
+ SDValue RHS = N->getOperand(1);
+ ISD::CondCode Cond = cast<CondCodeSDNode>(N->getOperand(4))->get();
+ if (Cond != ISD::SETEQ && Cond != ISD::SETNE)
+ return SDValue();
+
+ if ((isNullConstant(LHS) || isAllOnesConstant(LHS)) &&
+ RHS.getOpcode() == ISD::BITCAST)
+ std::swap(LHS, RHS);
+
+ if (!(isNullConstant(RHS) || isAllOnesConstant(RHS)) ||
+ LHS.getOpcode() != ISD::BITCAST)
+ return SDValue();
+
+ EVT FromVT = LHS.getOperand(0).getValueType();
+ if (!FromVT.isFixedLengthVector() || FromVT.getVectorElementType() != MVT::i1)
+ return SDValue();
+
+ SDLoc DL(N);
+ SDValue CompareLHS, CompareRHS;
+ if (!getBoolVectorBitcastCompare(LHS.getOperand(0), RHS, DL, DAG, CompareLHS,
+ CompareRHS))
+ return SDValue();
+
+ return DAG.getNode(ISD::SELECT_CC, DL, N->getValueType(0), CompareLHS,
+ CompareRHS, N->getOperand(2), N->getOperand(3),
+ N->getOperand(4));
+}
+
// Replace a flag-setting operator (eg ANDS) with the generic version
// (eg AND) if the flag is unused.
static SDValue performFlagSettingCombine(SDNode *N,
@@ -28979,6 +29062,8 @@ SDValue AArch64TargetLowering::PerformDAGCombine(SDNode *N,
return performInsertSubvectorCombine(N, DCI, DAG);
case ISD::SELECT:
return performSelectCombine(N, DCI);
+ case ISD::SELECT_CC:
+ return performSELECT_CCCombine(N, DCI, DAG);
case ISD::VSELECT:
return performVSelectCombine(N, DCI.DAG);
case ISD::SETCC:
diff --git a/llvm/test/CodeGen/AArch64/bool-vector-bitcast-compare.ll b/llvm/test/CodeGen/AArch64/bool-vector-bitcast-compare.ll
new file mode 100644
index 0000000000000..67616b3501af8
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/bool-vector-bitcast-compare.ll
@@ -0,0 +1,84 @@
+; RUN: llc -global-isel=false -mtriple=aarch64-linux-gnu -o - %s | FileCheck %s
+
+define i64 @match_any_byte(<8 x i8> %haystack, i8 %needle) {
+; CHECK-LABEL: match_any_byte:
+; CHECK: // %bb.0: // %bb1
+; CHECK-NEXT: dup v1.8b, w0
+; CHECK-NEXT: mov w8, #999 // =0x3e7
+; CHECK-NEXT: cmeq v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: fmov x9, d0
+; CHECK-NEXT: cmp x9, #0
+; CHECK-NEXT: mov w9, #777 // =0x309
+; CHECK-NEXT: csel x0, x9, x8, ne
+; CHECK-NEXT: ret
+bb1:
+ %0 = insertelement <8 x i8> poison, i8 %needle, i64 0
+ %1 = shufflevector <8 x i8> %0, <8 x i8> poison, <8 x i32> zeroinitializer
+ %2 = icmp eq <8 x i8> %haystack, %1
+ %3 = bitcast <8 x i1> %2 to i8
+ %4 = icmp ne i8 %3, 0
+ %5 = select i1 %4, i64 777, i64 999
+ ret i64 %5
+}
+
+define i64 @match_all_byte(<8 x i8> %haystack, i8 %needle) {
+; CHECK-LABEL: match_all_byte:
+; CHECK: // %bb.0
+; CHECK-NEXT: dup v1.8b, w0
+; CHECK-NEXT: mov w8, #999 // =0x3e7
+; CHECK-NEXT: cmeq v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: fmov x9, d0
+; CHECK-NEXT: cmn x9, #1
+; CHECK-NEXT: mov w9, #777 // =0x309
+; CHECK-NEXT: csel x0, x9, x8, eq
+; CHECK-NEXT: ret
+bb1:
+ %0 = insertelement <8 x i8> poison, i8 %needle, i64 0
+ %1 = shufflevector <8 x i8> %0, <8 x i8> poison, <8 x i32> zeroinitializer
+ %2 = icmp eq <8 x i8> %haystack, %1
+ %3 = bitcast <8 x i1> %2 to i8
+ %4 = icmp eq i8 %3, -1
+ %5 = select i1 %4, i64 777, i64 999
+ ret i64 %5
+}
+
+define i1 @match_any_bool(<8 x i8> %haystack, i8 %needle) {
+; CHECK-LABEL: match_any_bool:
+; CHECK: // %bb.0
+; CHECK-NEXT: dup v1.8b, w0
+; CHECK-NEXT: cmeq v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: fmov x8, d0
+; CHECK-NEXT: cmp x8, #0
+; CHECK-NEXT: cset w0, ne
+; CHECK-NEXT: ret
+bb1:
+ %0 = insertelement <8 x i8> poison, i8 %needle, i64 0
+ %1 = shufflevector <8 x i8> %0, <8 x i8> poison, <8 x i32> zeroinitializer
+ %2 = icmp eq <8 x i8> %haystack, %1
+ %3 = bitcast <8 x i1> %2 to i8
+ %4 = icmp ne i8 %3, 0
+ ret i1 %4
+}
+
+define i64 @match_any_byte_16(<16 x i8> %haystack, i8 %needle) {
+; CHECK-LABEL: match_any_byte_16:
+; CHECK: // %bb.0
+; CHECK-NEXT: dup v1.16b, w0
+; CHECK-NEXT: mov w8, #999 // =0x3e7
+; CHECK-NEXT: cmeq v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: fmov x9, d0
+; CHECK-NEXT: cmp x9, #0
+; CHECK-NEXT: mov w9, #777 // =0x309
+; CHECK-NEXT: csel x0, x9, x8, ne
+; CHECK-NEXT: ret
+bb1:
+ %0 = insertelement <16 x i8> poison, i8 %needle, i64 0
+ %1 = shufflevector <16 x i8> %0, <16 x i8> poison, <16 x i32> zeroinitializer
+ %2 = icmp eq <16 x i8> %haystack, %1
+ %3 = bitcast <16 x i1> %2 to i16
+ %4 = icmp ne i16 %3, 0
+ %5 = select i1 %4, i64 777, i64 999
+ ret i64 %5
+}
diff --git a/llvm/test/CodeGen/AArch64/dag-combine-setcc.ll b/llvm/test/CodeGen/AArch64/dag-combine-setcc.ll
index 16ccd61f925e3..7255212f14623 100644
--- a/llvm/test/CodeGen/AArch64/dag-combine-setcc.ll
+++ b/llvm/test/CodeGen/AArch64/dag-combine-setcc.ll
@@ -5,10 +5,9 @@ define i1 @combine_setcc_eq_vecreduce_or_v8i1(<8 x i8> %a) {
; CHECK-LABEL: combine_setcc_eq_vecreduce_or_v8i1:
; CHECK: // %bb.0:
; CHECK-NEXT: cmeq v0.8b, v0.8b, #0
-; CHECK-NEXT: mov w8, #1 // =0x1
-; CHECK-NEXT: umaxv b0, v0.8b
-; CHECK-NEXT: fmov w9, s0
-; CHECK-NEXT: bic w0, w8, w9
+; CHECK-NEXT: fmov x8, d0
+; CHECK-NEXT: cmp x8, #0
+; CHECK-NEXT: cset w0, eq
; CHECK-NEXT: ret
%cmp1 = icmp eq <8 x i8> %a, zeroinitializer
%cast = bitcast <8 x i1> %cmp1 to i8
@@ -20,10 +19,11 @@ define i1 @combine_setcc_eq_vecreduce_or_v16i1(<16 x i8> %a) {
; CHECK-LABEL: combine_setcc_eq_vecreduce_or_v16i1:
; CHECK: // %bb.0:
; CHECK-NEXT: cmeq v0.16b, v0.16b, #0
-; CHECK-NEXT: mov w8, #1 // =0x1
-; CHECK-NEXT: umaxv b0, v0.16b
-; CHECK-NEXT: fmov w9, s0
-; CHECK-NEXT: bic w0, w8, w9
+; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: fmov x8, d0
+; CHECK-NEXT: cmp x8, #0
+; CHECK-NEXT: cset w0, eq
; CHECK-NEXT: ret
%cmp1 = icmp eq <16 x i8> %a, zeroinitializer
%cast = bitcast <16 x i1> %cmp1 to i16
@@ -73,9 +73,9 @@ define i1 @combine_setcc_ne_vecreduce_or_v8i1(<8 x i8> %a) {
; CHECK-LABEL: combine_setcc_ne_vecreduce_or_v8i1:
; CHECK: // %bb.0:
; CHECK-NEXT: cmtst v0.8b, v0.8b, v0.8b
-; CHECK-NEXT: umaxv b0, v0.8b
-; CHECK-NEXT: fmov w8, s0
-; CHECK-NEXT: and w0, w8, #0x1
+; CHECK-NEXT: fmov x8, d0
+; CHECK-NEXT: cmp x8, #0
+; CHECK-NEXT: cset w0, ne
; CHECK-NEXT: ret
%cmp1 = icmp ne <8 x i8> %a, zeroinitializer
%cast = bitcast <8 x i1> %cmp1 to i8
@@ -87,9 +87,11 @@ define i1 @combine_setcc_ne_vecreduce_or_v16i1(<16 x i8> %a) {
; CHECK-LABEL: combine_setcc_ne_vecreduce_or_v16i1:
; CHECK: // %bb.0:
; CHECK-NEXT: cmtst v0.16b, v0.16b, v0.16b
-; CHECK-NEXT: umaxv b0, v0.16b
-; CHECK-NEXT: fmov w8, s0
-; CHECK-NEXT: and w0, w8, #0x1
+; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: fmov x8, d0
+; CHECK-NEXT: cmp x8, #0
+; CHECK-NEXT: cset w0, ne
; CHECK-NEXT: ret
%cmp1 = icmp ne <16 x i8> %a, zeroinitializer
%cast = bitcast <16 x i1> %cmp1 to i16
@@ -133,9 +135,9 @@ define i1 @combine_setcc_eq_vecreduce_and_v8i1(<8 x i8> %a) {
; CHECK-LABEL: combine_setcc_eq_vecreduce_and_v8i1:
; CHECK: // %bb.0:
; CHECK-NEXT: cmeq v0.8b, v0.8b, #0
-; CHECK-NEXT: uminv b0, v0.8b
-; CHECK-NEXT: fmov w8, s0
-; CHECK-NEXT: and w0, w8, #0x1
+; CHECK-NEXT: fmov x8, d0
+; CHECK-NEXT: cmn x8, #1
+; CHECK-NEXT: cset w0, eq
; CHECK-NEXT: ret
%cmp1 = icmp eq <8 x i8> %a, zeroinitializer
%cast = bitcast <8 x i1> %cmp1 to i8
@@ -147,9 +149,11 @@ define i1 @combine_setcc_eq_vecreduce_and_v16i1(<16 x i8> %a) {
; CHECK-LABEL: combine_setcc_eq_vecreduce_and_v16i1:
; CHECK: // %bb.0:
; CHECK-NEXT: cmeq v0.16b, v0.16b, #0
-; CHECK-NEXT: uminv b0, v0.16b
-; CHECK-NEXT: fmov w8, s0
-; CHECK-NEXT: and w0, w8, #0x1
+; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT: and v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: fmov x8, d0
+; CHECK-NEXT: cmn x8, #1
+; CHECK-NEXT: cset w0, eq
; CHECK-NEXT: ret
%cmp1 = icmp eq <16 x i8> %a, zeroinitializer
%cast = bitcast <16 x i1> %cmp1 to i16
@@ -193,10 +197,9 @@ define i1 @combine_setcc_ne_vecreduce_and_v8i1(<8 x i8> %a) {
; CHECK-LABEL: combine_setcc_ne_vecreduce_and_v8i1:
; CHECK: // %bb.0:
; CHECK-NEXT: cmtst v0.8b, v0.8b, v0.8b
-; CHECK-NEXT: mov w8, #1 // =0x1
-; CHECK-NEXT: uminv b0, v0.8b
-; CHECK-NEXT: fmov w9, s0
-; CHECK-NEXT: bic w0, w8, w9
+; CHECK-NEXT: fmov x8, d0
+; CHECK-NEXT: cmn x8, #1
+; CHECK-NEXT: cset w0, ne
; CHECK-NEXT: ret
%cmp1 = icmp ne <8 x i8> %a, zeroinitializer
%cast = bitcast <8 x i1> %cmp1 to i8
@@ -208,10 +211,11 @@ define i1 @combine_setcc_ne_vecreduce_and_v16i1(<16 x i8> %a) {
; CHECK-LABEL: combine_setcc_ne_vecreduce_and_v16i1:
; CHECK: // %bb.0:
; CHECK-NEXT: cmtst v0.16b, v0.16b, v0.16b
-; CHECK-NEXT: mov w8, #1 // =0x1
-; CHECK-NEXT: uminv b0, v0.16b
-; CHECK-NEXT: fmov w9, s0
-; CHECK-NEXT: bic w0, w8, w9
+; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT: and v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: fmov x8, d0
+; CHECK-NEXT: cmn x8, #1
+; CHECK-NEXT: cset w0, ne
; CHECK-NEXT: ret
%cmp1 = icmp ne <16 x i8> %a, zeroinitializer
%cast = bitcast <16 x i1> %cmp1 to i16
diff --git a/llvm/test/CodeGen/AArch64/illegal-floating-point-vector-compares.ll b/llvm/test/CodeGen/AArch64/illegal-floating-point-vector-compares.ll
index f317a7b808342..676888a3d97f1 100644
--- a/llvm/test/CodeGen/AArch64/illegal-floating-point-vector-compares.ll
+++ b/llvm/test/CodeGen/AArch64/illegal-floating-point-vector-compares.ll
@@ -9,12 +9,12 @@ define i1 @unordered_floating_point_compare_on_v8f32(<8 x float> %a_vec) {
; CHECK: // %bb.0:
; CHECK-NEXT: fcmgt v1.4s, v1.4s, #0.0
; CHECK-NEXT: fcmgt v0.4s, v0.4s, #0.0
-; CHECK-NEXT: mov w8, #1 // =0x1
; CHECK-NEXT: uzp1 v0.8h, v0.8h, v1.8h
; CHECK-NEXT: mvn v0.16b, v0.16b
-; CHECK-NEXT: umaxv h0, v0.8h
-; CHECK-NEXT: fmov w9, s0
-; CHECK-NEXT: bic w0, w8, w9
+; CHECK-NEXT: xtn v0.8b, v0.8h
+; CHECK-NEXT: fmov x8, d0
+; CHECK-NEXT: cmp x8, #0
+; CHECK-NEXT: cset w0, eq
; CHECK-NEXT: ret
%a_cmp = fcmp ule <8 x float> %a_vec, zeroinitializer
%cmp_result = bitcast <8 x i1> %a_cmp to i8
@@ -25,18 +25,18 @@ define i1 @unordered_floating_point_compare_on_v8f32(<8 x float> %a_vec) {
define i1 @unordered_floating_point_compare_on_v16f32(<16 x float> %a_vec) {
; CHECK-LABEL: unordered_floating_point_compare_on_v16f32:
; CHECK: // %bb.0:
-; CHECK-NEXT: fcmgt v3.4s, v3.4s, #0.0
-; CHECK-NEXT: fcmgt v2.4s, v2.4s, #0.0
-; CHECK-NEXT: mov w9, #1 // =0x1
; CHECK-NEXT: fcmgt v1.4s, v1.4s, #0.0
; CHECK-NEXT: fcmgt v0.4s, v0.4s, #0.0
-; CHECK-NEXT: uzp1 v2.8h, v2.8h, v3.8h
+; CHECK-NEXT: fcmgt v3.4s, v3.4s, #0.0
+; CHECK-NEXT: fcmgt v2.4s, v2.4s, #0.0
; CHECK-NEXT: uzp1 v0.8h, v0.8h, v1.8h
-; CHECK-NEXT: uzp1 v0.16b, v0.16b, v2.16b
+; CHECK-NEXT: uzp1 v1.8h, v2.8h, v3.8h
; CHECK-NEXT: mvn v0.16b, v0.16b
-; CHECK-NEXT: umaxv b0, v0.16b
-; CHECK-NEXT: fmov w8, s0
-; CHECK-NEXT: bic w0, w9, w8
+; CHECK-NEXT: orn v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: xtn v0.8b, v0.8h
+; CHECK-NEXT: fmov x8, d0
+; CHECK-NEXT: cmp x8, #0
+; CHECK-NEXT: cset w0, eq
; CHECK-NEXT: ret
%a_cmp = fcmp ule <16 x float> %a_vec, zeroinitializer
%cmp_result = bitcast <16 x i1> %a_cmp to i16
diff --git a/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll b/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll
index dedd4323f1519..cd414120e2939 100644
--- a/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll
+++ b/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll
@@ -13,12 +13,12 @@ define <4 x i32> @any_of_select_vf4(<4 x i32> %mask, <4 x i32> %a, <4 x i32> %b)
; CHECK-LABEL: any_of_select_vf4:
; CHECK: // %bb.0:
; CHECK-NEXT: cmlt v0.4s, v0.4s, #0
-; CHECK-NEXT: umaxv s0, v0.4s
-; CHECK-NEXT: fmov w8, s0
-; CHECK-NEXT: tst w8, #0x1
-; CHECK-NEXT: csetm w8, ne
-; CHECK-NEXT: dup v0.4s, w8
-; CHECK-NEXT: bsl v0.16b, v2.16b, v1.16b
+; CHECK-NEXT: ext v3.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT: orr v0.8b, v0.8b, v3.8b
+; CHECK-NEXT: movi d3, #0000000000000000
+; CHECK-NEXT: cmeq v0.2d, v0.2d, v3.2d
+; CHECK-NEXT: dup v0.2d, v0.d[0]
+; CHECK-NEXT: bsl v0.16b, v1.16b, v2.16b
; CHECK-NEXT: ret
%cmp = icmp slt <4 x i32> %mask, zeroinitializer
%cmp.bc = bitcast <4 x i1> %cmp to i4
@@ -31,12 +31,12 @@ define <2 x i64> @any_of_select_vf2(<2 x i64> %mask, <2 x i64> %a, <2 x i64> %b)
; CHECK-LABEL: any_of_select_vf2:
; CHECK: // %bb.0:
; CHECK-NEXT: cmlt v0.2d, v0.2d, #0
-; CHECK-NEXT: umaxv s0, v0.4s
-; CHECK-NEXT: fmov w8, s0
-; CHECK-NEXT: tst w8, #0x1
-; CHECK-NEXT: csetm x8, ne
-; CHECK-NEXT: dup v0.2d, x8
-; CHECK-NEXT: bsl v0.16b, v2.16b, v1.16b
+; CHECK-NEXT: ext v3.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT: orr v0.8b, v0.8b, v3.8b
+; CHECK-NEXT: movi d3, #0000000000000000
+; CHECK-NEXT: cmeq v0.2d, v0.2d, v3.2d
+; CHECK-NEXT: dup v0.2d, v0.d[0]
+; CHECK-NEXT: bsl v0.16b, v1.16b, v2.16b
; CHECK-NEXT: ret
%cmp = icmp slt <2 x i64> %mask, zeroinitializer
%cmp.bc = bitcast <2 x i1> %cmp to i2
>From 5c4e92bfe3d248cd98dc03a2b42599f1d006ecbb Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Sun, 22 Mar 2026 16:12:46 +0800
Subject: [PATCH 2/6] Fix code format
---
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 8535937402bd5..f7234c8be72e0 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -25511,7 +25511,8 @@ static bool getBoolVectorBitcastCompare(SDValue Vec, SDValue RHS,
SDValue &CompareLHS,
SDValue &CompareRHS) {
EVT VecVT = Vec.getValueType();
- assert(VecVT.isFixedLengthVector() && VecVT.getVectorElementType() == MVT::i1 &&
+ assert(VecVT.isFixedLengthVector() &&
+ VecVT.getVectorElementType() == MVT::i1 &&
"Expected a fixed-length bool vector");
unsigned NumElts = VecVT.getVectorNumElements();
>From 3207467fbdd4850a483f94ba4657060fce5f325f Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Sun, 22 Mar 2026 16:18:58 +0800
Subject: [PATCH 3/6] Fix test on neon-anyof-splat
---
llvm/test/CodeGen/AArch64/neon-anyof-splat.ll | 48 +++++++++----------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll b/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll
index cd414120e2939..77aee0eca1c4a 100644
--- a/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll
+++ b/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll
@@ -12,13 +12,13 @@ target triple = "aarch64-linux-gnu"
define <4 x i32> @any_of_select_vf4(<4 x i32> %mask, <4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: any_of_select_vf4:
; CHECK: // %bb.0:
-; CHECK-NEXT: cmlt v0.4s, v0.4s, #0
-; CHECK-NEXT: ext v3.16b, v0.16b, v0.16b, #8
-; CHECK-NEXT: orr v0.8b, v0.8b, v3.8b
-; CHECK-NEXT: movi d3, #0000000000000000
-; CHECK-NEXT: cmeq v0.2d, v0.2d, v3.2d
-; CHECK-NEXT: dup v0.2d, v0.d[0]
-; CHECK-NEXT: bsl v0.16b, v1.16b, v2.16b
+; CHECK-NEXT: cmlt v0.4s, v0.4s, #0
+; CHECK-DAG: movi d[[ZERO:[0-9]+]], #0000000000000000
+; CHECK-DAG: ext v[[TMP:[0-9]+]].16b, v0.16b, v0.16b, #8
+; CHECK-DAG: orr v0.8b, v0.8b, v[[TMP]].8b
+; CHECK: cmeq v0.2d, v0.2d, v[[ZERO]].2d
+; CHECK-NEXT: dup v0.2d, v0.d[0]
+; CHECK-NEXT: bsl v0.16b, v1.16b, v2.16b
; CHECK-NEXT: ret
%cmp = icmp slt <4 x i32> %mask, zeroinitializer
%cmp.bc = bitcast <4 x i1> %cmp to i4
@@ -30,13 +30,13 @@ define <4 x i32> @any_of_select_vf4(<4 x i32> %mask, <4 x i32> %a, <4 x i32> %b)
define <2 x i64> @any_of_select_vf2(<2 x i64> %mask, <2 x i64> %a, <2 x i64> %b) {
; CHECK-LABEL: any_of_select_vf2:
; CHECK: // %bb.0:
-; CHECK-NEXT: cmlt v0.2d, v0.2d, #0
-; CHECK-NEXT: ext v3.16b, v0.16b, v0.16b, #8
-; CHECK-NEXT: orr v0.8b, v0.8b, v3.8b
-; CHECK-NEXT: movi d3, #0000000000000000
-; CHECK-NEXT: cmeq v0.2d, v0.2d, v3.2d
-; CHECK-NEXT: dup v0.2d, v0.d[0]
-; CHECK-NEXT: bsl v0.16b, v1.16b, v2.16b
+; CHECK-NEXT: cmlt v0.2d, v0.2d, #0
+; CHECK-DAG: movi d[[ZERO:[0-9]+]], #0000000000000000
+; CHECK-DAG: ext v[[TMP:[0-9]+]].16b, v0.16b, v0.16b, #8
+; CHECK-DAG: orr v0.8b, v0.8b, v[[TMP]].8b
+; CHECK: cmeq v0.2d, v0.2d, v[[ZERO]].2d
+; CHECK-NEXT: dup v0.2d, v0.d[0]
+; CHECK-NEXT: bsl v0.16b, v1.16b, v2.16b
; CHECK-NEXT: ret
%cmp = icmp slt <2 x i64> %mask, zeroinitializer
%cmp.bc = bitcast <2 x i1> %cmp to i2
@@ -48,16 +48,16 @@ define <2 x i64> @any_of_select_vf2(<2 x i64> %mask, <2 x i64> %a, <2 x i64> %b)
define <32 x i8> @any_of_select_vf32(<32 x i8> %mask, <32 x i8> %a, <32 x i8> %b) {
; CHECK-LABEL: any_of_select_vf32:
; CHECK: // %bb.0:
-; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: cmlt v0.16b, v0.16b, #0
-; CHECK-NEXT: umaxv b0, v0.16b
-; CHECK-NEXT: fmov w8, s0
-; CHECK-NEXT: tst w8, #0x1
-; CHECK-NEXT: csetm w8, ne
-; CHECK-NEXT: dup v1.16b, w8
-; CHECK-NEXT: mov v0.16b, v1.16b
-; CHECK-NEXT: bsl v1.16b, v5.16b, v3.16b
-; CHECK-NEXT: bsl v0.16b, v4.16b, v2.16b
+; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: cmlt v0.16b, v0.16b, #0
+; CHECK-NEXT: umaxv b0, v0.16b
+; CHECK-NEXT: fmov w8, s0
+; CHECK-NEXT: tst w8, #0x1
+; CHECK-NEXT: csetm w8, ne
+; CHECK-NEXT: dup v1.16b, w8
+; CHECK-NEXT: mov v0.16b, v1.16b
+; CHECK-NEXT: bsl v1.16b, v5.16b, v3.16b
+; CHECK-NEXT: bsl v0.16b, v4.16b, v2.16b
; CHECK-NEXT: ret
%cmp = icmp slt <32 x i8> %mask, zeroinitializer
%cmp.bc = bitcast <32 x i1> %cmp to i32
>From b888c62bd8ccd090a427a5187ce5e66392c38e34 Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Wed, 1 Apr 2026 14:58:19 +0800
Subject: [PATCH 4/6] regenerate neon-anyof-splat.ll with
update_llc_test_checks
---
llvm/test/CodeGen/AArch64/neon-anyof-splat.ll | 48 +++++++++----------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll b/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll
index 77aee0eca1c4a..c7857aa2d64e1 100644
--- a/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll
+++ b/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll
@@ -12,13 +12,13 @@ target triple = "aarch64-linux-gnu"
define <4 x i32> @any_of_select_vf4(<4 x i32> %mask, <4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: any_of_select_vf4:
; CHECK: // %bb.0:
-; CHECK-NEXT: cmlt v0.4s, v0.4s, #0
-; CHECK-DAG: movi d[[ZERO:[0-9]+]], #0000000000000000
-; CHECK-DAG: ext v[[TMP:[0-9]+]].16b, v0.16b, v0.16b, #8
-; CHECK-DAG: orr v0.8b, v0.8b, v[[TMP]].8b
-; CHECK: cmeq v0.2d, v0.2d, v[[ZERO]].2d
-; CHECK-NEXT: dup v0.2d, v0.d[0]
-; CHECK-NEXT: bsl v0.16b, v1.16b, v2.16b
+; CHECK-NEXT: cmlt v0.4s, v0.4s, #0
+; CHECK-NEXT: movi d4, #0000000000000000
+; CHECK-NEXT: ext v3.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT: orr v0.8b, v0.8b, v3.8b
+; CHECK-NEXT: cmeq v0.2d, v0.2d, v4.2d
+; CHECK-NEXT: dup v0.2d, v0.d[0]
+; CHECK-NEXT: bsl v0.16b, v1.16b, v2.16b
; CHECK-NEXT: ret
%cmp = icmp slt <4 x i32> %mask, zeroinitializer
%cmp.bc = bitcast <4 x i1> %cmp to i4
@@ -30,13 +30,13 @@ define <4 x i32> @any_of_select_vf4(<4 x i32> %mask, <4 x i32> %a, <4 x i32> %b)
define <2 x i64> @any_of_select_vf2(<2 x i64> %mask, <2 x i64> %a, <2 x i64> %b) {
; CHECK-LABEL: any_of_select_vf2:
; CHECK: // %bb.0:
-; CHECK-NEXT: cmlt v0.2d, v0.2d, #0
-; CHECK-DAG: movi d[[ZERO:[0-9]+]], #0000000000000000
-; CHECK-DAG: ext v[[TMP:[0-9]+]].16b, v0.16b, v0.16b, #8
-; CHECK-DAG: orr v0.8b, v0.8b, v[[TMP]].8b
-; CHECK: cmeq v0.2d, v0.2d, v[[ZERO]].2d
-; CHECK-NEXT: dup v0.2d, v0.d[0]
-; CHECK-NEXT: bsl v0.16b, v1.16b, v2.16b
+; CHECK-NEXT: cmlt v0.2d, v0.2d, #0
+; CHECK-NEXT: movi d4, #0000000000000000
+; CHECK-NEXT: ext v3.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT: orr v0.8b, v0.8b, v3.8b
+; CHECK-NEXT: cmeq v0.2d, v0.2d, v4.2d
+; CHECK-NEXT: dup v0.2d, v0.d[0]
+; CHECK-NEXT: bsl v0.16b, v1.16b, v2.16b
; CHECK-NEXT: ret
%cmp = icmp slt <2 x i64> %mask, zeroinitializer
%cmp.bc = bitcast <2 x i1> %cmp to i2
@@ -48,16 +48,16 @@ define <2 x i64> @any_of_select_vf2(<2 x i64> %mask, <2 x i64> %a, <2 x i64> %b)
define <32 x i8> @any_of_select_vf32(<32 x i8> %mask, <32 x i8> %a, <32 x i8> %b) {
; CHECK-LABEL: any_of_select_vf32:
; CHECK: // %bb.0:
-; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: cmlt v0.16b, v0.16b, #0
-; CHECK-NEXT: umaxv b0, v0.16b
-; CHECK-NEXT: fmov w8, s0
-; CHECK-NEXT: tst w8, #0x1
-; CHECK-NEXT: csetm w8, ne
-; CHECK-NEXT: dup v1.16b, w8
-; CHECK-NEXT: mov v0.16b, v1.16b
-; CHECK-NEXT: bsl v1.16b, v5.16b, v3.16b
-; CHECK-NEXT: bsl v0.16b, v4.16b, v2.16b
+; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: cmlt v0.16b, v0.16b, #0
+; CHECK-NEXT: umaxv b0, v0.16b
+; CHECK-NEXT: fmov w8, s0
+; CHECK-NEXT: tst w8, #0x1
+; CHECK-NEXT: csetm w8, ne
+; CHECK-NEXT: dup v1.16b, w8
+; CHECK-NEXT: mov v0.16b, v1.16b
+; CHECK-NEXT: bsl v1.16b, v5.16b, v3.16b
+; CHECK-NEXT: bsl v0.16b, v4.16b, v2.16b
; CHECK-NEXT: ret
%cmp = icmp slt <32 x i8> %mask, zeroinitializer
%cmp.bc = bitcast <32 x i1> %cmp to i32
>From 785a77168d85c9456bc4b427e945c23eaaf0410a Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Wed, 1 Apr 2026 16:23:15 +0800
Subject: [PATCH 5/6] generate addp for <16 x i1> and fix build errors
---
.../Target/AArch64/AArch64ISelLowering.cpp | 28 +++++++++++++++++--
.../AArch64/bool-vector-bitcast-compare.ll | 26 +++++++++++++++--
.../test/CodeGen/AArch64/dag-combine-setcc.ll | 6 ++--
.../illegal-floating-point-vector-compares.ll | 10 +++----
llvm/test/CodeGen/AArch64/neon-anyof-splat.ll | 14 ++++------
5 files changed, 62 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 6f0c7f7a011bd..595af0348a77a 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -25934,10 +25934,14 @@ static bool getBoolVectorBitcastCompare(SDValue Vec, SDValue RHS,
if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16)
return false;
+ auto getCanonicalCompareVecVT = [&]() {
+ unsigned BitsPerElement = std::max(64 / NumElts, 8u);
+ return MVT::getVectorVT(MVT::getIntegerVT(BitsPerElement), NumElts);
+ };
+
EVT CompareVecVT = tryGetOriginalBoolVectorType(Vec);
if (!CompareVecVT.isSimple() || CompareVecVT.getSizeInBits() > 128) {
- unsigned BitsPerElement = std::max(64 / NumElts, 8u);
- CompareVecVT = MVT::getVectorVT(MVT::getIntegerVT(BitsPerElement), NumElts);
+ CompareVecVT = getCanonicalCompareVecVT();
}
CompareVecVT = CompareVecVT.changeVectorElementTypeToInteger();
@@ -25945,9 +25949,27 @@ static bool getBoolVectorBitcastCompare(SDValue Vec, SDValue RHS,
return false;
SDValue CompareBits = DAG.getSExtOrTrunc(Vec, DL, CompareVecVT);
+ unsigned CompareBitsSize = CompareBits.getValueSizeInBits();
+
+ // Use a canonical 64/128-bit vector representation before bitcasting to a
+ // scalar view. Some legal original vector types are smaller than 64-bit,
+ // which would make the direct scalar bitcasts below invalid.
+ if (CompareBitsSize != 64 && CompareBitsSize != 128) {
+ CompareVecVT = getCanonicalCompareVecVT();
+ CompareBits = DAG.getSExtOrTrunc(Vec, DL, CompareVecVT);
+ CompareBitsSize = CompareBits.getValueSizeInBits();
+ }
+
+ if (CompareBitsSize != 64 && CompareBitsSize != 128)
+ return false;
- if (CompareVecVT.getSizeInBits() == 64) {
+ if (CompareBitsSize == 64) {
CompareLHS = DAG.getBitcast(MVT::i64, CompareBits);
+ } else if (isNullConstant(RHS)) {
+ SDValue PairwiseBits = DAG.getBitcast(MVT::v2i64, CompareBits);
+ SDValue Lo = DAG.getExtractVectorElt(DL, MVT::i64, PairwiseBits, 0);
+ SDValue Hi = DAG.getExtractVectorElt(DL, MVT::i64, PairwiseBits, 1);
+ CompareLHS = DAG.getNode(ISD::ADD, DL, MVT::i64, Lo, Hi);
} else {
SDValue Lo, Hi;
std::tie(Lo, Hi) = DAG.SplitVector(CompareBits, DL);
diff --git a/llvm/test/CodeGen/AArch64/bool-vector-bitcast-compare.ll b/llvm/test/CodeGen/AArch64/bool-vector-bitcast-compare.ll
index 67616b3501af8..a9794bcfeeb7f 100644
--- a/llvm/test/CodeGen/AArch64/bool-vector-bitcast-compare.ll
+++ b/llvm/test/CodeGen/AArch64/bool-vector-bitcast-compare.ll
@@ -66,8 +66,7 @@ define i64 @match_any_byte_16(<16 x i8> %haystack, i8 %needle) {
; CHECK-NEXT: dup v1.16b, w0
; CHECK-NEXT: mov w8, #999 // =0x3e7
; CHECK-NEXT: cmeq v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8
-; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x9, d0
; CHECK-NEXT: cmp x9, #0
; CHECK-NEXT: mov w9, #777 // =0x309
@@ -82,3 +81,26 @@ bb1:
%5 = select i1 %4, i64 777, i64 999
ret i64 %5
}
+
+define i64 @match_any_byte_4(<4 x i8> %haystack, i8 %needle) {
+; CHECK-LABEL: match_any_byte_4:
+; CHECK: // %bb.0: // %bb1
+; CHECK-NEXT: dup v1.4h, w0
+; CHECK-NEXT: bic v0.4h, #255, lsl #8
+; CHECK-NEXT: mov w8, #999 // =0x3e7
+; CHECK-NEXT: bic v1.4h, #255, lsl #8
+; CHECK-NEXT: cmeq v0.4h, v0.4h, v1.4h
+; CHECK-NEXT: fmov x9, d0
+; CHECK-NEXT: cmp x9, #0
+; CHECK-NEXT: mov w9, #777 // =0x309
+; CHECK-NEXT: csel x0, x9, x8, ne
+; CHECK-NEXT: ret
+bb1:
+ %0 = insertelement <4 x i8> poison, i8 %needle, i64 0
+ %1 = shufflevector <4 x i8> %0, <4 x i8> poison, <4 x i32> zeroinitializer
+ %2 = icmp eq <4 x i8> %haystack, %1
+ %3 = bitcast <4 x i1> %2 to i4
+ %4 = icmp ne i4 %3, 0
+ %5 = select i1 %4, i64 777, i64 999
+ ret i64 %5
+}
diff --git a/llvm/test/CodeGen/AArch64/dag-combine-setcc.ll b/llvm/test/CodeGen/AArch64/dag-combine-setcc.ll
index 7255212f14623..25bbbd3c13944 100644
--- a/llvm/test/CodeGen/AArch64/dag-combine-setcc.ll
+++ b/llvm/test/CodeGen/AArch64/dag-combine-setcc.ll
@@ -19,8 +19,7 @@ define i1 @combine_setcc_eq_vecreduce_or_v16i1(<16 x i8> %a) {
; CHECK-LABEL: combine_setcc_eq_vecreduce_or_v16i1:
; CHECK: // %bb.0:
; CHECK-NEXT: cmeq v0.16b, v0.16b, #0
-; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8
-; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x8, d0
; CHECK-NEXT: cmp x8, #0
; CHECK-NEXT: cset w0, eq
@@ -87,8 +86,7 @@ define i1 @combine_setcc_ne_vecreduce_or_v16i1(<16 x i8> %a) {
; CHECK-LABEL: combine_setcc_ne_vecreduce_or_v16i1:
; CHECK: // %bb.0:
; CHECK-NEXT: cmtst v0.16b, v0.16b, v0.16b
-; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8
-; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x8, d0
; CHECK-NEXT: cmp x8, #0
; CHECK-NEXT: cset w0, ne
diff --git a/llvm/test/CodeGen/AArch64/illegal-floating-point-vector-compares.ll b/llvm/test/CodeGen/AArch64/illegal-floating-point-vector-compares.ll
index 676888a3d97f1..140e2a99bb4b2 100644
--- a/llvm/test/CodeGen/AArch64/illegal-floating-point-vector-compares.ll
+++ b/llvm/test/CodeGen/AArch64/illegal-floating-point-vector-compares.ll
@@ -25,15 +25,15 @@ define i1 @unordered_floating_point_compare_on_v8f32(<8 x float> %a_vec) {
define i1 @unordered_floating_point_compare_on_v16f32(<16 x float> %a_vec) {
; CHECK-LABEL: unordered_floating_point_compare_on_v16f32:
; CHECK: // %bb.0:
-; CHECK-NEXT: fcmgt v1.4s, v1.4s, #0.0
-; CHECK-NEXT: fcmgt v0.4s, v0.4s, #0.0
; CHECK-NEXT: fcmgt v3.4s, v3.4s, #0.0
; CHECK-NEXT: fcmgt v2.4s, v2.4s, #0.0
+; CHECK-NEXT: fcmgt v1.4s, v1.4s, #0.0
+; CHECK-NEXT: fcmgt v0.4s, v0.4s, #0.0
+; CHECK-NEXT: uzp1 v2.8h, v2.8h, v3.8h
; CHECK-NEXT: uzp1 v0.8h, v0.8h, v1.8h
-; CHECK-NEXT: uzp1 v1.8h, v2.8h, v3.8h
+; CHECK-NEXT: uzp1 v0.16b, v0.16b, v2.16b
; CHECK-NEXT: mvn v0.16b, v0.16b
-; CHECK-NEXT: orn v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: xtn v0.8b, v0.8h
+; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x8, d0
; CHECK-NEXT: cmp x8, #0
; CHECK-NEXT: cset w0, eq
diff --git a/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll b/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll
index c7857aa2d64e1..7385f62881bec 100644
--- a/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll
+++ b/llvm/test/CodeGen/AArch64/neon-anyof-splat.ll
@@ -13,10 +13,9 @@ define <4 x i32> @any_of_select_vf4(<4 x i32> %mask, <4 x i32> %a, <4 x i32> %b)
; CHECK-LABEL: any_of_select_vf4:
; CHECK: // %bb.0:
; CHECK-NEXT: cmlt v0.4s, v0.4s, #0
-; CHECK-NEXT: movi d4, #0000000000000000
-; CHECK-NEXT: ext v3.16b, v0.16b, v0.16b, #8
-; CHECK-NEXT: orr v0.8b, v0.8b, v3.8b
-; CHECK-NEXT: cmeq v0.2d, v0.2d, v4.2d
+; CHECK-NEXT: movi d3, #0000000000000000
+; CHECK-NEXT: addp d0, v0.2d
+; CHECK-NEXT: cmeq v0.2d, v0.2d, v3.2d
; CHECK-NEXT: dup v0.2d, v0.d[0]
; CHECK-NEXT: bsl v0.16b, v1.16b, v2.16b
; CHECK-NEXT: ret
@@ -31,10 +30,9 @@ define <2 x i64> @any_of_select_vf2(<2 x i64> %mask, <2 x i64> %a, <2 x i64> %b)
; CHECK-LABEL: any_of_select_vf2:
; CHECK: // %bb.0:
; CHECK-NEXT: cmlt v0.2d, v0.2d, #0
-; CHECK-NEXT: movi d4, #0000000000000000
-; CHECK-NEXT: ext v3.16b, v0.16b, v0.16b, #8
-; CHECK-NEXT: orr v0.8b, v0.8b, v3.8b
-; CHECK-NEXT: cmeq v0.2d, v0.2d, v4.2d
+; CHECK-NEXT: movi d3, #0000000000000000
+; CHECK-NEXT: addp d0, v0.2d
+; CHECK-NEXT: cmeq v0.2d, v0.2d, v3.2d
; CHECK-NEXT: dup v0.2d, v0.d[0]
; CHECK-NEXT: bsl v0.16b, v1.16b, v2.16b
; CHECK-NEXT: ret
>From e62eb93e7029540196a282a40d6a29eebaccb384 Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Sun, 19 Apr 2026 17:00:56 +0800
Subject: [PATCH 6/6] update
---
.../Target/AArch64/AArch64ISelLowering.cpp | 17 +--
.../AArch64/bool-vector-bitcast-compare.ll | 107 +++++++++++-------
.../test/CodeGen/AArch64/dag-combine-setcc.ll | 10 +-
3 files changed, 75 insertions(+), 59 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 595af0348a77a..32ea2cf408966 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -25963,25 +25963,20 @@ static bool getBoolVectorBitcastCompare(SDValue Vec, SDValue RHS,
if (CompareBitsSize != 64 && CompareBitsSize != 128)
return false;
+ bool IsNull = isNullConstant(RHS);
if (CompareBitsSize == 64) {
CompareLHS = DAG.getBitcast(MVT::i64, CompareBits);
- } else if (isNullConstant(RHS)) {
+ CompareRHS = IsNull ? DAG.getConstant(0, DL, MVT::i64)
+ : DAG.getAllOnesConstant(DL, MVT::i64);
+ } else {
SDValue PairwiseBits = DAG.getBitcast(MVT::v2i64, CompareBits);
SDValue Lo = DAG.getExtractVectorElt(DL, MVT::i64, PairwiseBits, 0);
SDValue Hi = DAG.getExtractVectorElt(DL, MVT::i64, PairwiseBits, 1);
CompareLHS = DAG.getNode(ISD::ADD, DL, MVT::i64, Lo, Hi);
- } else {
- SDValue Lo, Hi;
- std::tie(Lo, Hi) = DAG.SplitVector(CompareBits, DL);
-
- unsigned CombineOpc = isNullConstant(RHS) ? ISD::OR : ISD::AND;
- CompareLHS =
- DAG.getNode(CombineOpc, DL, MVT::i64, DAG.getBitcast(MVT::i64, Lo),
- DAG.getBitcast(MVT::i64, Hi));
+ CompareRHS = IsNull ? DAG.getConstant(0, DL, MVT::i64)
+ : DAG.getSignedConstant(-2, DL, MVT::i64);
}
- CompareRHS = isNullConstant(RHS) ? DAG.getConstant(0, DL, MVT::i64)
- : DAG.getAllOnesConstant(DL, MVT::i64);
return true;
}
diff --git a/llvm/test/CodeGen/AArch64/bool-vector-bitcast-compare.ll b/llvm/test/CodeGen/AArch64/bool-vector-bitcast-compare.ll
index a9794bcfeeb7f..17dc782caa0e5 100644
--- a/llvm/test/CodeGen/AArch64/bool-vector-bitcast-compare.ll
+++ b/llvm/test/CodeGen/AArch64/bool-vector-bitcast-compare.ll
@@ -1,15 +1,16 @@
-; RUN: llc -global-isel=false -mtriple=aarch64-linux-gnu -o - %s | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=aarch64-linux-gnu -o - %s | FileCheck %s
define i64 @match_any_byte(<8 x i8> %haystack, i8 %needle) {
; CHECK-LABEL: match_any_byte:
-; CHECK: // %bb.0: // %bb1
-; CHECK-NEXT: dup v1.8b, w0
-; CHECK-NEXT: mov w8, #999 // =0x3e7
-; CHECK-NEXT: cmeq v0.8b, v0.8b, v1.8b
-; CHECK-NEXT: fmov x9, d0
-; CHECK-NEXT: cmp x9, #0
-; CHECK-NEXT: mov w9, #777 // =0x309
-; CHECK-NEXT: csel x0, x9, x8, ne
+; CHECK: // %bb.0: // %bb1
+; CHECK-NEXT: dup v1.8b, w0
+; CHECK-NEXT: mov w8, #999 // =0x3e7
+; CHECK-NEXT: cmeq v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: fmov x9, d0
+; CHECK-NEXT: cmp x9, #0
+; CHECK-NEXT: mov w9, #777 // =0x309
+; CHECK-NEXT: csel x0, x9, x8, ne
; CHECK-NEXT: ret
bb1:
%0 = insertelement <8 x i8> poison, i8 %needle, i64 0
@@ -23,14 +24,14 @@ bb1:
define i64 @match_all_byte(<8 x i8> %haystack, i8 %needle) {
; CHECK-LABEL: match_all_byte:
-; CHECK: // %bb.0
-; CHECK-NEXT: dup v1.8b, w0
-; CHECK-NEXT: mov w8, #999 // =0x3e7
-; CHECK-NEXT: cmeq v0.8b, v0.8b, v1.8b
-; CHECK-NEXT: fmov x9, d0
-; CHECK-NEXT: cmn x9, #1
-; CHECK-NEXT: mov w9, #777 // =0x309
-; CHECK-NEXT: csel x0, x9, x8, eq
+; CHECK: // %bb.0: // %bb1
+; CHECK-NEXT: dup v1.8b, w0
+; CHECK-NEXT: mov w8, #999 // =0x3e7
+; CHECK-NEXT: cmeq v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: fmov x9, d0
+; CHECK-NEXT: cmn x9, #1
+; CHECK-NEXT: mov w9, #777 // =0x309
+; CHECK-NEXT: csel x0, x9, x8, eq
; CHECK-NEXT: ret
bb1:
%0 = insertelement <8 x i8> poison, i8 %needle, i64 0
@@ -44,12 +45,12 @@ bb1:
define i1 @match_any_bool(<8 x i8> %haystack, i8 %needle) {
; CHECK-LABEL: match_any_bool:
-; CHECK: // %bb.0
-; CHECK-NEXT: dup v1.8b, w0
-; CHECK-NEXT: cmeq v0.8b, v0.8b, v1.8b
-; CHECK-NEXT: fmov x8, d0
-; CHECK-NEXT: cmp x8, #0
-; CHECK-NEXT: cset w0, ne
+; CHECK: // %bb.0: // %bb1
+; CHECK-NEXT: dup v1.8b, w0
+; CHECK-NEXT: cmeq v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: fmov x8, d0
+; CHECK-NEXT: cmp x8, #0
+; CHECK-NEXT: cset w0, ne
; CHECK-NEXT: ret
bb1:
%0 = insertelement <8 x i8> poison, i8 %needle, i64 0
@@ -62,15 +63,15 @@ bb1:
define i64 @match_any_byte_16(<16 x i8> %haystack, i8 %needle) {
; CHECK-LABEL: match_any_byte_16:
-; CHECK: // %bb.0
-; CHECK-NEXT: dup v1.16b, w0
-; CHECK-NEXT: mov w8, #999 // =0x3e7
-; CHECK-NEXT: cmeq v0.16b, v0.16b, v1.16b
-; CHECK-NEXT: addp d0, v0.2d
-; CHECK-NEXT: fmov x9, d0
-; CHECK-NEXT: cmp x9, #0
-; CHECK-NEXT: mov w9, #777 // =0x309
-; CHECK-NEXT: csel x0, x9, x8, ne
+; CHECK: // %bb.0: // %bb1
+; CHECK-NEXT: dup v1.16b, w0
+; CHECK-NEXT: mov w8, #999 // =0x3e7
+; CHECK-NEXT: cmeq v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: addp d0, v0.2d
+; CHECK-NEXT: fmov x9, d0
+; CHECK-NEXT: cmp x9, #0
+; CHECK-NEXT: mov w9, #777 // =0x309
+; CHECK-NEXT: csel x0, x9, x8, ne
; CHECK-NEXT: ret
bb1:
%0 = insertelement <16 x i8> poison, i8 %needle, i64 0
@@ -82,18 +83,40 @@ bb1:
ret i64 %5
}
+define i64 @match_all_byte_16(<16 x i8> %haystack, i8 %needle) {
+; CHECK-LABEL: match_all_byte_16:
+; CHECK: // %bb.0: // %bb1
+; CHECK-NEXT: dup v1.16b, w0
+; CHECK-NEXT: mov w8, #999 // =0x3e7
+; CHECK-NEXT: cmeq v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: addp d0, v0.2d
+; CHECK-NEXT: fmov x9, d0
+; CHECK-NEXT: cmn x9, #2
+; CHECK-NEXT: mov w9, #777 // =0x309
+; CHECK-NEXT: csel x0, x9, x8, eq
+; CHECK-NEXT: ret
+bb1:
+ %0 = insertelement <16 x i8> poison, i8 %needle, i64 0
+ %1 = shufflevector <16 x i8> %0, <16 x i8> poison, <16 x i32> zeroinitializer
+ %2 = icmp eq <16 x i8> %haystack, %1
+ %3 = bitcast <16 x i1> %2 to i16
+ %4 = icmp eq i16 %3, -1
+ %5 = select i1 %4, i64 777, i64 999
+ ret i64 %5
+}
+
define i64 @match_any_byte_4(<4 x i8> %haystack, i8 %needle) {
; CHECK-LABEL: match_any_byte_4:
-; CHECK: // %bb.0: // %bb1
-; CHECK-NEXT: dup v1.4h, w0
-; CHECK-NEXT: bic v0.4h, #255, lsl #8
-; CHECK-NEXT: mov w8, #999 // =0x3e7
-; CHECK-NEXT: bic v1.4h, #255, lsl #8
-; CHECK-NEXT: cmeq v0.4h, v0.4h, v1.4h
-; CHECK-NEXT: fmov x9, d0
-; CHECK-NEXT: cmp x9, #0
-; CHECK-NEXT: mov w9, #777 // =0x309
-; CHECK-NEXT: csel x0, x9, x8, ne
+; CHECK: // %bb.0: // %bb1
+; CHECK-NEXT: dup v1.4h, w0
+; CHECK-NEXT: bic v0.4h, #255, lsl #8
+; CHECK-NEXT: mov w8, #999 // =0x3e7
+; CHECK-NEXT: bic v1.4h, #255, lsl #8
+; CHECK-NEXT: cmeq v0.4h, v0.4h, v1.4h
+; CHECK-NEXT: fmov x9, d0
+; CHECK-NEXT: cmp x9, #0
+; CHECK-NEXT: mov w9, #777 // =0x309
+; CHECK-NEXT: csel x0, x9, x8, ne
; CHECK-NEXT: ret
bb1:
%0 = insertelement <4 x i8> poison, i8 %needle, i64 0
diff --git a/llvm/test/CodeGen/AArch64/dag-combine-setcc.ll b/llvm/test/CodeGen/AArch64/dag-combine-setcc.ll
index 25bbbd3c13944..4e2aa56591652 100644
--- a/llvm/test/CodeGen/AArch64/dag-combine-setcc.ll
+++ b/llvm/test/CodeGen/AArch64/dag-combine-setcc.ll
@@ -147,10 +147,9 @@ define i1 @combine_setcc_eq_vecreduce_and_v16i1(<16 x i8> %a) {
; CHECK-LABEL: combine_setcc_eq_vecreduce_and_v16i1:
; CHECK: // %bb.0:
; CHECK-NEXT: cmeq v0.16b, v0.16b, #0
-; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8
-; CHECK-NEXT: and v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x8, d0
-; CHECK-NEXT: cmn x8, #1
+; CHECK-NEXT: cmn x8, #2
; CHECK-NEXT: cset w0, eq
; CHECK-NEXT: ret
%cmp1 = icmp eq <16 x i8> %a, zeroinitializer
@@ -209,10 +208,9 @@ define i1 @combine_setcc_ne_vecreduce_and_v16i1(<16 x i8> %a) {
; CHECK-LABEL: combine_setcc_ne_vecreduce_and_v16i1:
; CHECK: // %bb.0:
; CHECK-NEXT: cmtst v0.16b, v0.16b, v0.16b
-; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8
-; CHECK-NEXT: and v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x8, d0
-; CHECK-NEXT: cmn x8, #1
+; CHECK-NEXT: cmn x8, #2
; CHECK-NEXT: cset w0, ne
; CHECK-NEXT: ret
%cmp1 = icmp ne <16 x i8> %a, zeroinitializer
More information about the llvm-commits
mailing list