if (!Subtarget.hasSSE2() || (Subtarget.hasAVX512() && !PreferMovMsk))
return SDValue();
- // If the upper half of the ops are undef, then try to bitcast the lower half
- // and extend.
+ // If the upper ops of a concatenation are undef, then try to bitcast the
+ // lower op and extend.
SmallVector<SDValue, 4> SubSrcOps;
if (collectConcatOps(Src.getNode(), SubSrcOps, DAG) &&
- SubSrcOps.size() == 2) {
+ SubSrcOps.size() >= 2) {
SDValue LowerOp = SubSrcOps[0];
- SDValue UpperOp = SubSrcOps[1];
- if (LowerOp.getOpcode() == ISD::SETCC && UpperOp.isUndef()) {
- EVT HalfVT = VT.getHalfSizedIntegerVT(*DAG.getContext());
- if (SDValue V = combineBitcastvxi1(DAG, HalfVT, LowerOp, DL, Subtarget))
- return DAG.getNode(ISD::ANY_EXTEND, DL, VT, V);
+ ArrayRef<SDValue> UpperOps(std::next(SubSrcOps.begin()), SubSrcOps.end());
+ if (LowerOp.getOpcode() == ISD::SETCC &&
+ all_of(UpperOps, [](SDValue Op) { return Op.isUndef(); })) {
+ EVT SubVT = VT.getIntegerVT(
+ *DAG.getContext(), LowerOp.getValueType().getVectorMinNumElements());
+ if (SDValue V = combineBitcastvxi1(DAG, SubVT, LowerOp, DL, Subtarget)) {
+ EVT IntVT = VT.getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
+ return DAG.getBitcast(VT, DAG.getNode(ISD::ANY_EXTEND, DL, IntVT, V));
+ }
}
}
; SSE2-SSSE3: # %bb.0:
; SSE2-SSSE3-NEXT: pxor %xmm1, %xmm1
; SSE2-SSSE3-NEXT: pcmpeqd %xmm0, %xmm1
-; SSE2-SSSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm1[1,3,3,2]
-; SSE2-SSSE3-NEXT: pshufd {{.*#+}} xmm1 = xmm1[0,2,2,3]
-; SSE2-SSSE3-NEXT: pand %xmm0, %xmm1
-; SSE2-SSSE3-NEXT: pshuflw {{.*#+}} xmm0 = xmm1[0,2,2,3,4,5,6,7]
-; SSE2-SSSE3-NEXT: psllw $15, %xmm0
-; SSE2-SSSE3-NEXT: packsswb %xmm0, %xmm0
-; SSE2-SSSE3-NEXT: pmovmskb %xmm0, %eax
+; SSE2-SSSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm1[1,0,3,2]
+; SSE2-SSSE3-NEXT: pand %xmm1, %xmm0
+; SSE2-SSSE3-NEXT: movmskpd %xmm0, %eax
; SSE2-SSSE3-NEXT: # kill: def $al killed $al killed $eax
; SSE2-SSSE3-NEXT: retq
;
; AVX12: # %bb.0:
; AVX12-NEXT: vpxor %xmm1, %xmm1, %xmm1
; AVX12-NEXT: vpcmpeqq %xmm1, %xmm0, %xmm0
-; AVX12-NEXT: vpackssdw %xmm0, %xmm0, %xmm0
-; AVX12-NEXT: vpackssdw %xmm0, %xmm0, %xmm0
-; AVX12-NEXT: vpsllw $15, %xmm0, %xmm0
-; AVX12-NEXT: vpacksswb %xmm0, %xmm0, %xmm0
-; AVX12-NEXT: vpmovmskb %xmm0, %eax
+; AVX12-NEXT: vmovmskpd %xmm0, %eax
; AVX12-NEXT: # kill: def $al killed $al killed $eax
; AVX12-NEXT: retq
;