aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/X86/X86ISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/X86/X86ISelLowering.cpp')
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp84
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;
}