[X86][SSE] MatchVectorAllZeroTest - handle OR vector reductions (REAPPLIED)

This patch extends MatchVectorAllZeroTest to handle OR vector reduction patterns where the result is compared against zero.

Reapplied with a fix for a chromium regression due to a missing isNullConstant() check in combineSetCC: https://bugs.chromium.org/p/chromium/issues/detail?id=1097758

Fixes PR45378

Differential Revision: https://reviews.llvm.org/D81547
This commit is contained in:
Simon Pilgrim 2020-06-29 15:24:49 +01:00
parent 57ad8f4730
commit 333aa690f4
3 changed files with 451 additions and 771 deletions

View File

@ -21374,12 +21374,22 @@ static SDValue LowerVectorAllZero(const SDLoc &DL, SDValue V, ISD::CondCode CC,
SelectionDAG &DAG, X86::CondCode &X86CC) {
EVT VT = V.getValueType();
// Quit if less than 128-bits or not splittable to 128/256-bit vector.
if (VT.getSizeInBits() < 128 || !isPowerOf2_32(VT.getSizeInBits()))
return SDValue();
assert((CC == ISD::SETEQ || CC == ISD::SETNE) && "Unsupported ISD::CondCode");
X86CC = (CC == ISD::SETEQ ? X86::COND_E : X86::COND_NE);
// For sub-128-bit vector, cast to (legal) integer and compare with zero.
if (VT.getSizeInBits() < 128) {
EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
if (!DAG.getTargetLoweringInfo().isTypeLegal(IntVT))
return SDValue();
return DAG.getNode(X86ISD::CMP, DL, MVT::i32, DAG.getBitcast(IntVT, V),
DAG.getConstant(0, DL, IntVT));
}
// Quit if not splittable to 128/256-bit vector.
if (!isPowerOf2_32(VT.getSizeInBits()))
return SDValue();
// Split down to 128/256-bit vector.
unsigned TestSize = Subtarget.hasAVX() ? 256 : 128;
while (VT.getSizeInBits() > TestSize) {
@ -21403,18 +21413,19 @@ static SDValue LowerVectorAllZero(const SDLoc &DL, SDValue V, ISD::CondCode CC,
DAG.getConstant(0xFFFF, DL, MVT::i32));
}
// Check whether an OR'd tree is PTEST-able, or if we can fallback to
// Check whether an OR'd reduction tree is PTEST-able, or if we can fallback to
// CMP(MOVMSK(PCMPEQB(X,0))).
static SDValue MatchVectorAllZeroTest(SDValue Op, ISD::CondCode CC,
const SDLoc &DL,
const X86Subtarget &Subtarget,
SelectionDAG &DAG, SDValue &X86CC) {
assert(Op.getOpcode() == ISD::OR && "Only check OR'd tree.");
assert((CC == ISD::SETEQ || CC == ISD::SETNE) && "Unsupported ISD::CondCode");
if (!Subtarget.hasSSE2() || !Op->hasOneUse())
return SDValue();
SmallVector<SDValue, 8> VecIns;
if (matchScalarReduction(Op, ISD::OR, VecIns)) {
if (Op.getOpcode() == ISD::OR && matchScalarReduction(Op, ISD::OR, VecIns)) {
EVT VT = VecIns[0].getValueType();
assert(llvm::all_of(VecIns,
[VT](SDValue V) { return VT == V.getValueType(); }) &&
@ -21424,8 +21435,6 @@ static SDValue MatchVectorAllZeroTest(SDValue Op, ISD::CondCode CC,
if (VT.getSizeInBits() < 128 || !isPowerOf2_32(VT.getSizeInBits()))
return SDValue();
SDLoc DL(Op);
// If more than one full vector is evaluated, OR them first before PTEST.
for (unsigned Slot = 0, e = VecIns.size(); e - Slot > 1;
Slot += 2, e += 1) {
@ -21444,6 +21453,19 @@ static SDValue MatchVectorAllZeroTest(SDValue Op, ISD::CondCode CC,
}
}
if (Op.getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
ISD::NodeType BinOp;
if (SDValue Match =
DAG.matchBinOpReduction(Op.getNode(), BinOp, {ISD::OR})) {
X86::CondCode CCode;
if (SDValue V =
LowerVectorAllZero(DL, Match, CC, Subtarget, DAG, CCode)) {
X86CC = DAG.getTargetConstant(CCode, DL, MVT::i8);
return V;
}
}
}
return SDValue();
}
@ -22594,11 +22616,10 @@ SDValue X86TargetLowering::emitFlagsForSetcc(SDValue Op0, SDValue Op1,
// Try to use PTEST/PMOVMSKB for a tree ORs equality compared with 0.
// TODO: We could do AND tree with all 1s as well by using the C flag.
if (Op0.getOpcode() == ISD::OR && isNullConstant(Op1) &&
(CC == ISD::SETEQ || CC == ISD::SETNE)) {
if (SDValue CmpZ = MatchVectorAllZeroTest(Op0, CC, Subtarget, DAG, X86CC))
if (isNullConstant(Op1) && (CC == ISD::SETEQ || CC == ISD::SETNE))
if (SDValue CmpZ =
MatchVectorAllZeroTest(Op0, CC, dl, Subtarget, DAG, X86CC))
return CmpZ;
}
// Try to lower using KORTEST or KTEST.
if (SDValue Test = EmitAVX512Test(Op0, Op1, CC, dl, DAG, Subtarget, X86CC))
@ -46120,6 +46141,14 @@ static SDValue combineSetCC(SDNode *N, SelectionDAG &DAG,
if (CC == ISD::SETNE || CC == ISD::SETEQ) {
if (SDValue V = combineVectorSizedSetCCEquality(N, DAG, Subtarget))
return V;
if (VT == MVT::i1 && isNullConstant(RHS)) {
SDValue X86CC;
if (SDValue V =
MatchVectorAllZeroTest(LHS, CC, DL, Subtarget, DAG, X86CC))
return DAG.getNode(ISD::TRUNCATE, DL, VT,
DAG.getNode(X86ISD::SETCC, DL, MVT::i8, X86CC, V));
}
}
if (VT.isVector() && VT.getVectorElementType() == MVT::i1 &&

View File

@ -9,43 +9,29 @@
declare i64 @llvm.experimental.vector.reduce.or.v2i64(<2 x i64>)
define i1 @parseHeaders(i64 * %ptr) nounwind {
; SSE-LABEL: parseHeaders:
; SSE: # %bb.0:
; SSE-NEXT: movdqu (%rdi), %xmm0
; SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,0,1]
; SSE-NEXT: por %xmm0, %xmm1
; SSE-NEXT: movq %xmm1, %rax
; SSE-NEXT: testq %rax, %rax
; SSE-NEXT: sete %al
; SSE-NEXT: retq
; SSE2-LABEL: parseHeaders:
; SSE2: # %bb.0:
; SSE2-NEXT: movdqu (%rdi), %xmm0
; SSE2-NEXT: pxor %xmm1, %xmm1
; SSE2-NEXT: pcmpeqb %xmm0, %xmm1
; SSE2-NEXT: pmovmskb %xmm1, %eax
; SSE2-NEXT: cmpl $65535, %eax # imm = 0xFFFF
; SSE2-NEXT: sete %al
; SSE2-NEXT: retq
;
; AVX1-LABEL: parseHeaders:
; AVX1: # %bb.0:
; AVX1-NEXT: vmovdqu (%rdi), %xmm0
; AVX1-NEXT: vpshufd {{.*#+}} xmm1 = xmm0[2,3,0,1]
; AVX1-NEXT: vpor %xmm1, %xmm0, %xmm0
; AVX1-NEXT: vmovq %xmm0, %rax
; AVX1-NEXT: testq %rax, %rax
; AVX1-NEXT: sete %al
; AVX1-NEXT: retq
; SSE41-LABEL: parseHeaders:
; SSE41: # %bb.0:
; SSE41-NEXT: movdqu (%rdi), %xmm0
; SSE41-NEXT: ptest %xmm0, %xmm0
; SSE41-NEXT: sete %al
; SSE41-NEXT: retq
;
; AVX2-LABEL: parseHeaders:
; AVX2: # %bb.0:
; AVX2-NEXT: vpbroadcastq 8(%rdi), %xmm0
; AVX2-NEXT: vpor (%rdi), %xmm0, %xmm0
; AVX2-NEXT: vmovq %xmm0, %rax
; AVX2-NEXT: testq %rax, %rax
; AVX2-NEXT: sete %al
; AVX2-NEXT: retq
;
; AVX512-LABEL: parseHeaders:
; AVX512: # %bb.0:
; AVX512-NEXT: vpbroadcastq 8(%rdi), %xmm0
; AVX512-NEXT: vpor (%rdi), %xmm0, %xmm0
; AVX512-NEXT: vmovq %xmm0, %rax
; AVX512-NEXT: testq %rax, %rax
; AVX512-NEXT: sete %al
; AVX512-NEXT: retq
; AVX-LABEL: parseHeaders:
; AVX: # %bb.0:
; AVX-NEXT: vmovdqu (%rdi), %xmm0
; AVX-NEXT: vptest %xmm0, %xmm0
; AVX-NEXT: sete %al
; AVX-NEXT: retq
%vptr = bitcast i64 * %ptr to <2 x i64> *
%vload = load <2 x i64>, <2 x i64> * %vptr, align 8
%vreduce = call i64 @llvm.experimental.vector.reduce.or.v2i64(<2 x i64> %vload)

File diff suppressed because it is too large Load Diff