diff options
Diffstat (limited to 'llvm/lib/Target/X86/X86ISelLowering.cpp')
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index b38329eb527..d62bf919d79 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -39101,6 +39101,71 @@ static SDValue combineParity(SDNode *N, SelectionDAG &DAG, return DAG.getNode(ISD::ZERO_EXTEND, DL, N->getValueType(0), Setnp); } + +// Look for (and (bitcast (vXi1 (concat_vectors (vYi1 setcc), undef,))), C) +// Where C is a mask containing the same number of bits as the setcc and +// where the setcc will freely 0 upper bits of k-register. We can replace the +// undef in the concat with 0s and remove the AND. This mainly helps with +// v2i1/v4i1 setcc being casted to scalar. +static SDValue combineScalarAndWithMaskSetcc(SDNode *N, SelectionDAG &DAG, + const X86Subtarget &Subtarget) { + assert(N->getOpcode() == ISD::AND && "Unexpected opcode!"); + + EVT VT = N->getValueType(0); + + // Make sure this is an AND with constant. We will check the value of the + // constant later. + if (!isa<ConstantSDNode>(N->getOperand(1))) + return SDValue(); + + // This is implied by the ConstantSDNode. + assert(!VT.isVector() && "Expected scalar VT!"); + + if (N->getOperand(0).getOpcode() != ISD::BITCAST || + !N->getOperand(0).hasOneUse() || + !N->getOperand(0).getOperand(0).hasOneUse()) + return SDValue(); + + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + SDValue Src = N->getOperand(0).getOperand(0); + EVT SrcVT = Src.getValueType(); + if (!SrcVT.isVector() || SrcVT.getVectorElementType() != MVT::i1 || + !TLI.isTypeLegal(SrcVT)) + return SDValue(); + + if (Src.getOpcode() != ISD::CONCAT_VECTORS) + return SDValue(); + + // We only care about the first subvector of the concat, we expect the + // other subvectors to be ignored due to the AND if we make the change. + SDValue SubVec = Src.getOperand(0); + EVT SubVecVT = SubVec.getValueType(); + + // First subvector should be a setcc with a legal result type. The RHS of the + // AND should be a mask with this many bits. + if (SubVec.getOpcode() != ISD::SETCC || !TLI.isTypeLegal(SubVecVT) || + !N->getConstantOperandAPInt(1).isMask(SubVecVT.getVectorNumElements())) + return SDValue(); + + EVT SetccVT = SubVec.getOperand(0).getValueType(); + if (!TLI.isTypeLegal(SetccVT) || + !(Subtarget.hasVLX() || SetccVT.is512BitVector())) + return SDValue(); + + if (!(Subtarget.hasBWI() || SetccVT.getScalarSizeInBits() >= 32)) + return SDValue(); + + // We passed all the checks. Rebuild the concat_vectors with zeroes + // and cast it back to VT. + SDLoc dl(N); + SmallVector<SDValue, 4> Ops(Src.getNumOperands(), + DAG.getConstant(0, dl, SubVecVT)); + Ops[0] = SubVec; + SDValue Concat = DAG.getNode(ISD::CONCAT_VECTORS, dl, SrcVT, + Ops); + return DAG.getBitcast(VT, Concat); +} + static SDValue combineAnd(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const X86Subtarget &Subtarget) { @@ -39150,6 +39215,9 @@ static SDValue combineAnd(SDNode *N, SelectionDAG &DAG, } } + if (SDValue V = combineScalarAndWithMaskSetcc(N, DAG, Subtarget)) + return V; + if (DCI.isBeforeLegalizeOps()) return SDValue(); |

