[llvm] 642d016 - [WebAssembly] Fix wide bitmask fallback in performBitcastCombine (#190915)

via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 22 22:54:14 PDT 2026


Author: hanbeom
Date: 2026-04-23T14:54:09+09:00
New Revision: 642d0167de9cb222c12f74cfa8861919337d99c5

URL: https://github.com/llvm/llvm-project/commit/642d0167de9cb222c12f74cfa8861919337d99c5
DIFF: https://github.com/llvm/llvm-project/commit/642d0167de9cb222c12f74cfa8861919337d99c5.diff

LOG: [WebAssembly] Fix wide bitmask fallback in performBitcastCombine (#190915)

The wide <N x i1> -> iN fallback in performBitcastCombine hardcoded
v16i1/i16 partial masks for every chunk. That is only valid for
16-lane chunks and can crash for cases such as v32i16, where each
concat operand is v8i16 and the partial mask should be v8i1/i8.

Derive the per-chunk mask and integer types from the actual concat
operand type when reconstructing the final scalar bitmask.

Fixed: https://github.com/llvm/llvm-project/issues/190306

Added: 
    

Modified: 
    llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
    llvm/test/CodeGen/WebAssembly/simd-bitmask.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index a3a873ebefb81..3f0c247d626ab 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -3363,9 +3363,6 @@ static SDValue performBitcastCombine(SDNode *N,
 
   // bitcast <N x i1>(setcc ...) to concat iN, where N = 32 and 64 (illegal)
   if (NumElts == 32 || NumElts == 64) {
-    // Strategy: We will setcc them separately in v16i8 -> v16i1
-    // Bitcast them to i16, extend them to either i32 or i64.
-    // Add them together, shifting left 1 by 1.
     SDValue Concat, SetCCVector;
     ISD::CondCode SetCond;
 
@@ -3375,33 +3372,61 @@ static SDValue performBitcastCombine(SDNode *N,
     if (Concat.getOpcode() != ISD::CONCAT_VECTORS)
       return SDValue();
 
-    uint64_t ElementWidth =
-        SetCCVector.getValueType().getVectorElementType().getFixedSizeInBits();
-
-    SmallVector<SDValue> VectorsToShuffle;
-    for (size_t I = 0; I < Concat->ops().size(); I++) {
-      VectorsToShuffle.push_back(DAG.getBitcast(
-          MVT::i16,
-          DAG.getSetCC(DL, MVT::v16i1, Concat->ops()[I],
-                       extractSubVector(SetCCVector, I * (128 / ElementWidth),
-                                        DAG, DL, 128),
-                       SetCond)));
-    }
-
-    MVT ReturnType = VectorsToShuffle.size() == 2 ? MVT::i32 : MVT::i64;
-    SDValue ReturningInteger = DAG.getConstant(0, DL, ReturnType);
-
-    for (SDValue V : VectorsToShuffle) {
-      ReturningInteger = DAG.getNode(
-          ISD::SHL, DL, ReturnType,
-          {ReturningInteger, DAG.getShiftAmountConstant(16, ReturnType, DL)});
+    // Reconstruct the wide bitmask from each CONCAT_VECTORS operand.
+    // Derive the per-chunk mask/integer types from the actual operand type
+    // instead of hardcoding v16i1 / i16 for every chunk.
+    EVT ConcatOperandVT = Concat.getOperand(0).getValueType();
+    unsigned ConcatOperandNumElts = ConcatOperandVT.getVectorNumElements();
+
+    EVT ConcatOperandMaskVT =
+        EVT::getVectorVT(*DAG.getContext(), MVT::i1,
+                         ElementCount::getFixed(ConcatOperandNumElts));
+    EVT ConcatOperandBitmaskVT =
+        EVT::getIntegerVT(*DAG.getContext(), ConcatOperandNumElts);
+    EVT ReturnVT = N->getValueType(0);
+    SDValue ReconstructedBitmask = DAG.getConstant(0, DL, ReturnVT);
+    // Example:
+    //   v32i16 = concat(v8i16, v8i16, v8i16, v8i16)
+    //     -> v8i1 + v8i1 + v8i1 + v8i1
+    //     -> i8   + i8   + i8   + i8
+    //     -> reconstructed i32 bitmask
+    for (size_t I = 0; I < Concat->ops().size(); ++I) {
+      SDValue ConcatOperand = Concat.getOperand(I);
+      assert(ConcatOperand.getValueType() == ConcatOperandVT &&
+             "concat_vectors operands must have the same type");
+
+      SDValue SetCCVectorOperand =
+          extractSubVector(SetCCVector, I * ConcatOperandNumElts, DAG, DL, 128);
+      if (!SetCCVectorOperand ||
+          SetCCVectorOperand.getValueType() != ConcatOperandVT)
+        return SDValue();
+
+      // Build the per-chunk mask using the correct chunk type:
+      //   v16i8 -> v16i1 -> i16
+      //   v8i16 -> v8i1  -> i8
+      //   v4i32 -> v4i1  -> i4
+      //   v2i64 -> v2i1  -> i2
+      SDValue ConcatOperandMask = DAG.getSetCC(
+          DL, ConcatOperandMaskVT, ConcatOperand, SetCCVectorOperand, SetCond);
+      SDValue ConcatOperandBitmask =
+          DAG.getBitcast(ConcatOperandBitmaskVT, ConcatOperandMask);
+      SDValue ExtendedConcatOperandBitmask =
+          DAG.getZExtOrTrunc(ConcatOperandBitmask, DL, ReturnVT);
+
+      // Shift the previously reconstructed bits to make room for this chunk.
+      if (I != 0) {
+        ReconstructedBitmask = DAG.getNode(
+            ISD::SHL, DL, ReturnVT, ReconstructedBitmask,
+            DAG.getShiftAmountConstant(ConcatOperandNumElts, ReturnVT, DL));
+      }
 
-      SDValue ExtendedV = DAG.getZExtOrTrunc(V, DL, ReturnType);
-      ReturningInteger =
-          DAG.getNode(ISD::ADD, DL, ReturnType, {ReturningInteger, ExtendedV});
+      // Merge disjoint partial bitmasks with OR.
+      ReconstructedBitmask =
+          DAG.getNode(ISD::OR, DL, ReturnVT, ReconstructedBitmask,
+                      ExtendedConcatOperandBitmask);
     }
 
-    return ReturningInteger;
+    return ReconstructedBitmask;
   }
 
   return SDValue();

diff  --git a/llvm/test/CodeGen/WebAssembly/simd-bitmask.ll b/llvm/test/CodeGen/WebAssembly/simd-bitmask.ll
index 5f6647691b723..42cdce5833d12 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-bitmask.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-bitmask.ll
@@ -309,3 +309,701 @@ define i64 @manual_bitmask_v64i8(<64 x i8> %v) {
   %2 = bitcast <64 x i1> %1 to i64
   ret i64 %2
 }
+
+define i32 @bitmask_v32i16(<32 x i16> %v) {
+; CHECK-LABEL: bitmask_v32i16:
+; CHECK:         .functype bitmask_v32i16 (v128, v128, v128, v128) -> (i32)
+; CHECK-NEXT:    .local v128
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    local.get 0
+; CHECK-NEXT:    v128.const 0, 0, 0, 0, 0, 0, 0, 0
+; CHECK-NEXT:    local.tee 4
+; CHECK-NEXT:    i16x8.eq
+; CHECK-NEXT:    i16x8.bitmask
+; CHECK-NEXT:    i32.const 24
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    local.get 1
+; CHECK-NEXT:    local.get 4
+; CHECK-NEXT:    i16x8.eq
+; CHECK-NEXT:    i16x8.bitmask
+; CHECK-NEXT:    i32.const 16
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 2
+; CHECK-NEXT:    local.get 4
+; CHECK-NEXT:    i16x8.eq
+; CHECK-NEXT:    i16x8.bitmask
+; CHECK-NEXT:    i32.const 8
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 3
+; CHECK-NEXT:    local.get 4
+; CHECK-NEXT:    i16x8.eq
+; CHECK-NEXT:    i16x8.bitmask
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    # fallthrough-return
+  %cmp = icmp eq <32 x i16> %v, zeroinitializer
+  %bitmask = bitcast <32 x i1> %cmp to i32
+  ret i32 %bitmask
+}
+
+define i32 @bitmask_v32i32(<32 x i32> %v) {
+; CHECK-LABEL: bitmask_v32i32:
+; CHECK:         .functype bitmask_v32i32 (v128, v128, v128, v128, v128, v128, v128, v128) -> (i32)
+; CHECK-NEXT:    .local v128
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    local.get 0
+; CHECK-NEXT:    v128.const 0, 0, 0, 0
+; CHECK-NEXT:    local.tee 8
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i32.const 12
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    local.get 1
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i32.const 8
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 2
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i32.const 4
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 3
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    i32.const 8
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    local.get 4
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i32.const 4
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 5
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    i32.const 8
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    local.get 6
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i32.const 4
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 7
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    # fallthrough-return
+  %cmp = icmp eq <32 x i32> %v, zeroinitializer
+  %bitmask = bitcast <32 x i1> %cmp to i32
+  ret i32 %bitmask
+}
+
+define i32 @bitmask_v32i64(<32 x i64> %v) {
+; CHECK-LABEL: bitmask_v32i64:
+; CHECK:         .functype bitmask_v32i64 (v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128) -> (i32)
+; CHECK-NEXT:    .local v128
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    local.get 0
+; CHECK-NEXT:    v128.const 0, 0
+; CHECK-NEXT:    local.tee 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.const 6
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    local.get 1
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.const 4
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 2
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.const 2
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 3
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    i32.const 4
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    local.get 4
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.const 2
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 5
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    i32.const 4
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    local.get 6
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.const 2
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 7
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    i32.const 4
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.const 2
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 9
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    i32.const 4
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    local.get 10
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.const 2
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 11
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    i32.const 4
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    local.get 12
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.const 2
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 13
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    i32.const 4
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    local.get 14
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.const 2
+; CHECK-NEXT:    i32.shl
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    local.get 15
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i32.or
+; CHECK-NEXT:    # fallthrough-return
+  %cmp = icmp eq <32 x i64> %v, zeroinitializer
+  %bitmask = bitcast <32 x i1> %cmp to i32
+  ret i32 %bitmask
+}
+
+define i64 @bitmask_v64i16(<64 x i16> %v) {
+; CHECK-LABEL: bitmask_v64i16:
+; CHECK:         .functype bitmask_v64i16 (v128, v128, v128, v128, v128, v128, v128, v128) -> (i64)
+; CHECK-NEXT:    .local v128
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    local.get 0
+; CHECK-NEXT:    v128.const 0, 0, 0, 0, 0, 0, 0, 0
+; CHECK-NEXT:    local.tee 8
+; CHECK-NEXT:    i16x8.eq
+; CHECK-NEXT:    i16x8.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 24
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 1
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i16x8.eq
+; CHECK-NEXT:    i16x8.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 16
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 2
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i16x8.eq
+; CHECK-NEXT:    i16x8.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 8
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 3
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i16x8.eq
+; CHECK-NEXT:    i16x8.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 16
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 4
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i16x8.eq
+; CHECK-NEXT:    i16x8.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 8
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 5
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i16x8.eq
+; CHECK-NEXT:    i16x8.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 16
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 6
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i16x8.eq
+; CHECK-NEXT:    i16x8.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 8
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 7
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    i16x8.eq
+; CHECK-NEXT:    i16x8.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    # fallthrough-return
+  %cmp = icmp eq <64 x i16> %v, zeroinitializer
+  %bitmask = bitcast <64 x i1> %cmp to i64
+  ret i64 %bitmask
+}
+
+define i64 @bitmask_v64i32(<64 x i32> %v) {
+; CHECK-LABEL: bitmask_v64i32:
+; CHECK:         .functype bitmask_v64i32 (v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128) -> (i64)
+; CHECK-NEXT:    .local v128
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    local.get 0
+; CHECK-NEXT:    v128.const 0, 0, 0, 0
+; CHECK-NEXT:    local.tee 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 12
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 1
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 8
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 2
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 3
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 8
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 4
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 5
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 8
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 6
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 7
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 8
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 9
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 8
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 10
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 11
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 8
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 12
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 13
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 8
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 14
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 15
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    i32x4.eq
+; CHECK-NEXT:    i32x4.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    # fallthrough-return
+  %cmp = icmp eq <64 x i32> %v, zeroinitializer
+  %bitmask = bitcast <64 x i1> %cmp to i64
+  ret i64 %bitmask
+}
+
+define i64 @bitmask_v64i64(<64 x i64> %v) {
+; CHECK-LABEL: bitmask_v64i64:
+; CHECK:         .functype bitmask_v64i64 (v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128, v128) -> (i64)
+; CHECK-NEXT:    .local v128
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    local.get 0
+; CHECK-NEXT:    v128.const 0, 0
+; CHECK-NEXT:    local.tee 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 6
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 1
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 2
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 3
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 4
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 5
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 6
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 7
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 8
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 9
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 10
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 11
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 12
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 13
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 14
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 15
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 16
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 17
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 18
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 19
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 20
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 21
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 22
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 23
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 24
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 25
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 26
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 27
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 28
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 29
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    i64.const 4
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    local.get 30
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.const 2
+; CHECK-NEXT:    i64.shl
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    local.get 31
+; CHECK-NEXT:    local.get 32
+; CHECK-NEXT:    i64x2.eq
+; CHECK-NEXT:    i64x2.bitmask
+; CHECK-NEXT:    i64.extend_i32_u
+; CHECK-NEXT:    i64.or
+; CHECK-NEXT:    # fallthrough-return
+  %cmp = icmp eq <64 x i64> %v, zeroinitializer
+  %bitmask = bitcast <64 x i1> %cmp to i64
+  ret i64 %bitmask
+}


        


More information about the llvm-commits mailing list