From: Sanjay Patel Date: Mon, 5 Dec 2016 15:45:27 +0000 (+0000) Subject: [x86] fold fand (fxor X, -1) Y --> fandn X, Y X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=da70d5a32a83f370626b72c085e82908b90f1798;p=llvm [x86] fold fand (fxor X, -1) Y --> fandn X, Y I noticed this gap in the scalar FP-logic matching with: D26712 and: rL287171 Differential Revision: https://reviews.llvm.org/D27385 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288675 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 6b23b6187a9..128dbff1219 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -31764,6 +31764,34 @@ static SDValue getNullFPConstForNullVal(SDValue V, SelectionDAG &DAG, return V; } +static SDValue combineFAndFNotToFAndn(SDNode *N, SelectionDAG &DAG, + const X86Subtarget &Subtarget) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + EVT VT = N->getValueType(0); + SDLoc DL(N); + + // Vector types are handled in combineANDXORWithAllOnesIntoANDNP(). + if (!((VT == MVT::f32 && Subtarget.hasSSE1()) || + (VT == MVT::f64 && Subtarget.hasSSE2()))) + return SDValue(); + + auto isAllOnesConstantFP = [](SDValue V) { + auto *C = dyn_cast(V); + return C && C->getConstantFPValue()->isAllOnesValue(); + }; + + // fand (fxor X, -1), Y --> fandn X, Y + if (N0.getOpcode() == X86ISD::FXOR && isAllOnesConstantFP(N0.getOperand(1))) + return DAG.getNode(X86ISD::FANDN, DL, VT, N0.getOperand(0), N1); + + // fand X, (fxor Y, -1) --> fandn Y, X + if (N1.getOpcode() == X86ISD::FXOR && isAllOnesConstantFP(N1.getOperand(1))) + return DAG.getNode(X86ISD::FANDN, DL, VT, N1.getOperand(0), N0); + + return SDValue(); +} + /// Do target-specific dag combines on X86ISD::FAND nodes. static SDValue combineFAnd(SDNode *N, SelectionDAG &DAG, const X86Subtarget &Subtarget) { @@ -31775,6 +31803,9 @@ static SDValue combineFAnd(SDNode *N, SelectionDAG &DAG, if (SDValue V = getNullFPConstForNullVal(N->getOperand(1), DAG, Subtarget)) return V; + if (SDValue V = combineFAndFNotToFAndn(N, DAG, Subtarget)) + return V; + return lowerX86FPLogicOp(N, DAG, Subtarget); } diff --git a/test/CodeGen/X86/fp-logic-replace.ll b/test/CodeGen/X86/fp-logic-replace.ll index 50e2c1b2029..0a233fd9b64 100644 --- a/test/CodeGen/X86/fp-logic-replace.ll +++ b/test/CodeGen/X86/fp-logic-replace.ll @@ -29,16 +29,13 @@ define double @FsANDPSrr(double %x, double %y) { define double @FsANDNPSrr(double %x, double %y) { ; SSE-LABEL: FsANDNPSrr: ; SSE: # BB#0: -; SSE-NEXT: movsd {{.*#+}} xmm2 = mem[0],zero -; SSE-NEXT: xorpd %xmm1, %xmm2 -; SSE-NEXT: andpd %xmm2, %xmm0 +; SSE-NEXT: andnps %xmm0, %xmm1 +; SSE-NEXT: movaps %xmm1, %xmm0 ; SSE-NEXT: retq ; ; AVX-LABEL: FsANDNPSrr: ; AVX: # BB#0: -; AVX-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX-NEXT: vxorpd %xmm2, %xmm1, %xmm1 -; AVX-NEXT: vandpd %xmm1, %xmm0, %xmm0 +; AVX-NEXT: vandnps %xmm0, %xmm1, %xmm0 ; AVX-NEXT: retq ; %bc1 = bitcast double %x to i64