diff options
-rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 56 |
1 files changed, 29 insertions, 27 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 660255612ee..f1be359862c 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -9097,6 +9097,28 @@ static SmallVector<int, 64> createTargetShuffleMask(ArrayRef<int> Mask, return TargetMask; } +// Attempt to create a shuffle mask from a VSELECT condition mask. +static bool createShuffleMaskFromVSELECT(SmallVectorImpl<int> &Mask, + SDValue Cond) { + if (!ISD::isBuildVectorOfConstantSDNodes(Cond.getNode())) + return false; + + unsigned Size = Cond.getValueType().getVectorNumElements(); + Mask.resize(Size, SM_SentinelUndef); + + for (int i = 0; i != (int)Size; ++i) { + SDValue CondElt = Cond.getOperand(i); + Mask[i] = i; + // Arbitrarily choose from the 2nd operand if the select condition element + // is undef. + // TODO: Can we do better by matching patterns such as even/odd? + if (CondElt.isUndef() || isNullConstant(CondElt)) + Mask[i] += Size; + } + + return true; +} + // Check if the shuffle mask is suitable for the AVX vpunpcklwd or vpunpckhwd // instructions. static bool isUnpackWdShuffleMask(ArrayRef<int> Mask, MVT VT) { @@ -15135,26 +15157,15 @@ static SDValue lowerVSELECTtoVectorShuffle(SDValue Op, SDValue Cond = Op.getOperand(0); SDValue LHS = Op.getOperand(1); SDValue RHS = Op.getOperand(2); - SDLoc dl(Op); MVT VT = Op.getSimpleValueType(); - if (!ISD::isBuildVectorOfConstantSDNodes(Cond.getNode())) - return SDValue(); - auto *CondBV = cast<BuildVectorSDNode>(Cond); - // Only non-legal VSELECTs reach this lowering, convert those into generic // shuffles and re-use the shuffle lowering path for blends. SmallVector<int, 32> Mask; - for (int i = 0, Size = VT.getVectorNumElements(); i < Size; ++i) { - SDValue CondElt = CondBV->getOperand(i); - int M = i; - // We can't map undef to undef here. They have different meanings. Treat - // as the same as zero. - if (CondElt.isUndef() || isNullConstant(CondElt)) - M += Size; - Mask.push_back(M); - } - return DAG.getVectorShuffle(VT, dl, LHS, RHS, Mask); + if (createShuffleMaskFromVSELECT(Mask, Cond)) + return DAG.getVectorShuffle(VT, SDLoc(Op), LHS, RHS, Mask); + + return SDValue(); } SDValue X86TargetLowering::LowerVSELECT(SDValue Op, SelectionDAG &DAG) const { @@ -32560,18 +32571,9 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG, // Convert vselects with constant condition into shuffles. if (ISD::isBuildVectorOfConstantSDNodes(Cond.getNode()) && DCI.isBeforeLegalizeOps()) { - SmallVector<int, 64> Mask(VT.getVectorNumElements(), -1); - for (int i = 0, Size = Mask.size(); i != Size; ++i) { - SDValue CondElt = Cond->getOperand(i); - Mask[i] = i; - // Arbitrarily choose from the 2nd operand if the select condition element - // is undef. - // TODO: Can we do better by matching patterns such as even/odd? - if (CondElt.isUndef() || isNullConstant(CondElt)) - Mask[i] += Size; - } - - return DAG.getVectorShuffle(VT, DL, LHS, RHS, Mask); + SmallVector<int, 64> Mask; + if (createShuffleMaskFromVSELECT(Mask, Cond)) + return DAG.getVectorShuffle(VT, DL, LHS, RHS, Mask); } // If we have SSE[12] support, try to form min/max nodes. SSE min/max |