mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[X86][SSE] MatchVectorAllZeroTest - handle OR vector reductions
This patch extends MatchVectorAllZeroTest to handle OR vector reduction patterns where the result is compared against zero. Fixes PR45378 Differential Revision: https://reviews.llvm.org/D81547
This commit is contained in:
parent
0a7c114d32
commit
125618570c
@ -21352,12 +21352,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) {
|
||||
@ -21381,18 +21391,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(); }) &&
|
||||
@ -21402,8 +21413,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) {
|
||||
@ -21422,6 +21431,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();
|
||||
}
|
||||
|
||||
@ -22572,11 +22594,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))
|
||||
@ -45942,6 +45963,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) {
|
||||
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 &&
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user