diff options
Diffstat (limited to 'llvm/lib/Target/X86/X86ISelLowering.cpp')
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 84 |
1 files changed, 81 insertions, 3 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 5a4533c4bac4..b080ab7e138c 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -1041,6 +1041,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, setOperationAction(ISD::SMULO, MVT::v16i8, Custom); setOperationAction(ISD::UMULO, MVT::v16i8, Custom); + setOperationAction(ISD::UMULO, MVT::v2i32, Custom); setOperationAction(ISD::FNEG, MVT::v2f64, Custom); setOperationAction(ISD::FABS, MVT::v2f64, Custom); @@ -1255,6 +1256,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, // FIXME: Do we need to handle scalar-to-vector here? setOperationAction(ISD::MUL, MVT::v4i32, Legal); + setOperationAction(ISD::SMULO, MVT::v2i32, Custom); // We directly match byte blends in the backend as they match the VSELECT // condition form. @@ -19302,6 +19304,44 @@ static bool canonicalizeShuffleMaskWithCommute(ArrayRef<int> Mask) { return false; } +static bool canCombineAsMaskOperation(SDValue V1, SDValue V2, + const X86Subtarget &Subtarget) { + if (!Subtarget.hasAVX512()) + return false; + + MVT VT = V1.getSimpleValueType().getScalarType(); + if ((VT == MVT::i16 || VT == MVT::i8) && !Subtarget.hasBWI()) + return false; + + // i8 is better to be widen to i16, because there is PBLENDW for vXi16 + // when the vector bit size is 128 or 256. + if (VT == MVT::i8 && V1.getSimpleValueType().getSizeInBits() < 512) + return false; + + auto HasMaskOperation = [&](SDValue V) { + // TODO: Currently we only check limited opcode. We probably extend + // it to all binary operation by checking TLI.isBinOp(). + switch (V->getOpcode()) { + default: + return false; + case ISD::ADD: + case ISD::SUB: + case ISD::AND: + case ISD::XOR: + break; + } + if (!V->hasOneUse()) + return false; + + return true; + }; + + if (HasMaskOperation(V1) || HasMaskOperation(V2)) + return true; + + return false; +} + // Forward declaration. static SDValue canonicalizeShuffleMaskWithHorizOp( MutableArrayRef<SDValue> Ops, MutableArrayRef<int> Mask, @@ -19377,6 +19417,7 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, const X86Subtarget &Subtarget, // integers to handle flipping the low and high halves of AVX 256-bit vectors. SmallVector<int, 16> WidenedMask; if (VT.getScalarSizeInBits() < 64 && !Is1BitVector && + !canCombineAsMaskOperation(V1, V2, Subtarget) && canWidenShuffleElements(OrigMask, Zeroable, V2IsZero, WidenedMask)) { // Shuffle mask widening should not interfere with a broadcast opportunity // by obfuscating the operands with bitcasts. @@ -32379,6 +32420,43 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N, Results.push_back(Res); return; } + case ISD::SMULO: + case ISD::UMULO: { + EVT VT = N->getValueType(0); + assert(getTypeAction(*DAG.getContext(), VT) == TypeWidenVector && + VT == MVT::v2i32 && "Unexpected VT!"); + bool IsSigned = N->getOpcode() == ISD::SMULO; + unsigned ExtOpc = IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + SDValue Op0 = DAG.getNode(ExtOpc, dl, MVT::v2i64, N->getOperand(0)); + SDValue Op1 = DAG.getNode(ExtOpc, dl, MVT::v2i64, N->getOperand(1)); + SDValue Res = DAG.getNode(ISD::MUL, dl, MVT::v2i64, Op0, Op1); + // Extract the high 32 bits from each result using PSHUFD. + // TODO: Could use SRL+TRUNCATE but that doesn't become a PSHUFD. + SDValue Hi = DAG.getBitcast(MVT::v4i32, Res); + Hi = DAG.getVectorShuffle(MVT::v4i32, dl, Hi, Hi, {1, 3, -1, -1}); + Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, Hi, + DAG.getIntPtrConstant(0, dl)); + + // Truncate the low bits of the result. This will become PSHUFD. + Res = DAG.getNode(ISD::TRUNCATE, dl, VT, Res); + + SDValue HiCmp; + if (IsSigned) { + // SMULO overflows if the high bits don't match the sign of the low. + HiCmp = DAG.getNode(ISD::SRA, dl, VT, Res, DAG.getConstant(31, dl, VT)); + } else { + // UMULO overflows if the high bits are non-zero. + HiCmp = DAG.getConstant(0, dl, VT); + } + SDValue Ovf = DAG.getSetCC(dl, N->getValueType(1), Hi, HiCmp, ISD::SETNE); + + // Widen the result with by padding with undef. + Res = DAG.getNode(ISD::CONCAT_VECTORS, dl, MVT::v4i32, Res, + DAG.getUNDEF(VT)); + Results.push_back(Res); + Results.push_back(Ovf); + return; + } case X86ISD::VPMADDWD: { // Legalize types for X86ISD::VPMADDWD by widening. assert(Subtarget.hasSSE2() && "Requires at least SSE2!"); @@ -37522,8 +37600,8 @@ static bool matchBinaryShuffle(MVT MaskVT, ArrayRef<int> Mask, break; } if (IsBlend) { - if (DAG.computeKnownBits(V1, DemandedZeroV1).isZero() && - DAG.computeKnownBits(V2, DemandedZeroV2).isZero()) { + if (DAG.MaskedVectorIsZero(V1, DemandedZeroV1) && + DAG.MaskedVectorIsZero(V2, DemandedZeroV2)) { Shuffle = ISD::OR; SrcVT = DstVT = MaskVT.changeTypeToInteger(); return true; @@ -41191,7 +41269,7 @@ bool X86TargetLowering::SimplifyDemandedVectorEltsForTargetNode( SDValue Src = Op.getOperand(0); APInt DemandedUpperElts = DemandedElts; DemandedUpperElts.clearLowBits(1); - if (TLO.DAG.computeKnownBits(Src, DemandedUpperElts, Depth + 1).isZero()) + if (TLO.DAG.MaskedVectorIsZero(Src, DemandedUpperElts, Depth + 1)) return TLO.CombineTo(Op, Src); break; } |
