diff options
| author | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2016-02-16 22:13:49 +0000 |
|---|---|---|
| committer | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2016-02-16 22:13:49 +0000 |
| commit | 7502768c6d9a819e43c9f22f3aa2356d940dede4 (patch) | |
| tree | a25ac95da598039a79eed1ecbdbe45160fb278b1 | |
| parent | 83efea89e8be6bdfe3dbf26ad23bc5b06a817fe0 (diff) | |
| download | bcm5719-llvm-7502768c6d9a819e43c9f22f3aa2356d940dede4.tar.gz bcm5719-llvm-7502768c6d9a819e43c9f22f3aa2356d940dede4.zip | |
[X86] Extract ANDNP combine. NFC.
This makes it IMO more readable and reduces indentation.
llvm-svn: 261020
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 118 |
1 files changed, 57 insertions, 61 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 976c2eea231..4d469503470 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -26087,34 +26087,47 @@ static SDValue CMPEQCombine(SDNode *N, SelectionDAG &DAG, return SDValue(); } -/// CanFoldXORWithAllOnes - Test whether the XOR operand is a AllOnes vector -/// so it can be folded inside ANDNP. -static bool CanFoldXORWithAllOnes(const SDNode *N) { +// Try to fold: (and (xor X, -1), Y) -> (andnp X, Y). +static SDValue combineANDXORWithAllOnesIntoANDNP(SDNode *N, SelectionDAG &DAG) { + assert(N->getOpcode() == ISD::AND); + EVT VT = N->getValueType(0); + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDLoc DL(N); - // Match direct AllOnes for 128 and 256-bit vectors - if (ISD::isBuildVectorAllOnes(N)) - return true; + if (VT != MVT::v2i64 && VT != MVT::v4i64) + return SDValue(); - // Look through a bit convert. - if (N->getOpcode() == ISD::BITCAST) - N = N->getOperand(0).getNode(); - - // Sometimes the operand may come from a insert_subvector building a 256-bit - // allones vector - if (VT.is256BitVector() && - N->getOpcode() == ISD::INSERT_SUBVECTOR) { - SDValue V1 = N->getOperand(0); - SDValue V2 = N->getOperand(1); - - if (V1.getOpcode() == ISD::INSERT_SUBVECTOR && - V1.getOperand(0).getOpcode() == ISD::UNDEF && - ISD::isBuildVectorAllOnes(V1.getOperand(1).getNode()) && - ISD::isBuildVectorAllOnes(V2.getNode())) - return true; - } + // Canonicalize XOR to the left. + if (N1.getOpcode() == ISD::XOR) + std::swap(N0, N1); - return false; + if (N0.getOpcode() != ISD::XOR) + return SDValue(); + + SDValue N00 = N0->getOperand(0); + SDValue N01 = N0->getOperand(1); + + // Look through a bitcast. + if (N01->getOpcode() == ISD::BITCAST) + N01 = N01->getOperand(0); + + // Either match a direct AllOnes for 128 and 256-bit vectors, or an + // insert_subvector building a 256-bit AllOnes vector. + if (!ISD::isBuildVectorAllOnes(N01.getNode())) { + if (!VT.is256BitVector() || N01->getOpcode() != ISD::INSERT_SUBVECTOR) + return SDValue(); + + SDValue V1 = N01->getOperand(0); + SDValue V2 = N01->getOperand(1); + if (V1.getOpcode() != ISD::INSERT_SUBVECTOR || + V1.getOperand(0).getOpcode() != ISD::UNDEF || + !ISD::isBuildVectorAllOnes(V1.getOperand(1).getNode()) || + !ISD::isBuildVectorAllOnes(V2.getNode())) + return SDValue(); + } + return DAG.getNode(X86ISD::ANDNP, DL, VT, N00, N1); } // On AVX/AVX2 the type v8i1 is legalized to v8i16, which is an XMM sized @@ -26340,6 +26353,9 @@ static SDValue PerformAndCombine(SDNode *N, SelectionDAG &DAG, if (SDValue FPLogic = convertIntLogicToFPLogic(N, DAG, Subtarget)) return FPLogic; + if (SDValue R = combineANDXORWithAllOnesIntoANDNP(N, DAG)) + return R; + EVT VT = N->getValueType(0); SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); @@ -26347,47 +26363,27 @@ static SDValue PerformAndCombine(SDNode *N, SelectionDAG &DAG, // Create BEXTR instructions // BEXTR is ((X >> imm) & (2**size-1)) - if (VT == MVT::i32 || VT == MVT::i64) { - // Check for BEXTR. - if ((Subtarget.hasBMI() || Subtarget.hasTBM()) && - (N0.getOpcode() == ISD::SRA || N0.getOpcode() == ISD::SRL)) { - ConstantSDNode *MaskNode = dyn_cast<ConstantSDNode>(N1); - ConstantSDNode *ShiftNode = dyn_cast<ConstantSDNode>(N0.getOperand(1)); - if (MaskNode && ShiftNode) { - uint64_t Mask = MaskNode->getZExtValue(); - uint64_t Shift = ShiftNode->getZExtValue(); - if (isMask_64(Mask)) { - uint64_t MaskSize = countPopulation(Mask); - if (Shift + MaskSize <= VT.getSizeInBits()) - return DAG.getNode(X86ISD::BEXTR, DL, VT, N0.getOperand(0), - DAG.getConstant(Shift | (MaskSize << 8), DL, - VT)); - } - } - } // BEXTR - + if (VT != MVT::i32 && VT != MVT::i64) return SDValue(); - } - // Want to form ANDNP nodes: - // 1) In the hopes of then easily combining them with OR and AND nodes - // to form PBLEND/PSIGN. - // 2) To match ANDN packed intrinsics - if (VT != MVT::v2i64 && VT != MVT::v4i64) + if (!Subtarget.hasBMI() && !Subtarget.hasTBM()) + return SDValue(); + if (N0.getOpcode() != ISD::SRA && N0.getOpcode() != ISD::SRL) return SDValue(); - // Check LHS for vnot - if (N0.getOpcode() == ISD::XOR && - //ISD::isBuildVectorAllOnes(N0.getOperand(1).getNode())) - CanFoldXORWithAllOnes(N0.getOperand(1).getNode())) - return DAG.getNode(X86ISD::ANDNP, DL, VT, N0.getOperand(0), N1); - - // Check RHS for vnot - if (N1.getOpcode() == ISD::XOR && - //ISD::isBuildVectorAllOnes(N1.getOperand(1).getNode())) - CanFoldXORWithAllOnes(N1.getOperand(1).getNode())) - return DAG.getNode(X86ISD::ANDNP, DL, VT, N1.getOperand(0), N0); - + ConstantSDNode *MaskNode = dyn_cast<ConstantSDNode>(N1); + ConstantSDNode *ShiftNode = dyn_cast<ConstantSDNode>(N0.getOperand(1)); + if (MaskNode && ShiftNode) { + uint64_t Mask = MaskNode->getZExtValue(); + uint64_t Shift = ShiftNode->getZExtValue(); + if (isMask_64(Mask)) { + uint64_t MaskSize = countPopulation(Mask); + if (Shift + MaskSize <= VT.getSizeInBits()) + return DAG.getNode(X86ISD::BEXTR, DL, VT, N0.getOperand(0), + DAG.getConstant(Shift | (MaskSize << 8), DL, + VT)); + } + } return SDValue(); } |

