[llvm] [WebAssembly] Fix wide bitmask fallback in performBitcastCombine (PR #190915)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 14 04:15:51 PDT 2026
https://github.com/ParkHanbum updated https://github.com/llvm/llvm-project/pull/190915
>From b78becbd48ff342fb42e7cc3c4596b5a0f90c696 Mon Sep 17 00:00:00 2001
From: Hanbum Park <kese111 at gmail.com>
Date: Wed, 8 Apr 2026 14:57:26 +0900
Subject: [PATCH 1/2] [WebAssembly] Fix wide bitmask fallback in
performBitcastCombine
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: #190306
---
.../WebAssembly/WebAssemblyISelLowering.cpp | 79 ++++++++++++-------
1 file changed, 52 insertions(+), 27 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index efa6a61f82e9d..cac9c97b2262f 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -3354,9 +3354,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;
@@ -3366,33 +3363,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();
>From 0934d0e13754c8cd71ba7c00090a99bbf9795f79 Mon Sep 17 00:00:00 2001
From: Hanbum Park <kese111 at gmail.com>
Date: Fri, 10 Apr 2026 16:58:59 +0900
Subject: [PATCH 2/2] add testcases
---
llvm/test/CodeGen/WebAssembly/simd-bitmask.ll | 698 ++++++++++++++++++
1 file changed, 698 insertions(+)
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