[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