mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-26 07:29:55 +00:00
- Added support to turn "vector clear elements", e.g. pand V, <-1, -1, 0, -1>
to a vector shuffle. - VECTOR_SHUFFLE lowering change in preparation for more efficient codegen of vector shuffle with zero (or any splat) vector. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27875 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
44f1f09b4e
commit
39623daef6
@ -1501,45 +1501,51 @@ bool X86::isPSHUFLWMask(SDNode *N) {
|
|||||||
|
|
||||||
/// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand
|
/// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand
|
||||||
/// specifies a shuffle of elements that is suitable for input to SHUFP*.
|
/// specifies a shuffle of elements that is suitable for input to SHUFP*.
|
||||||
bool X86::isSHUFPMask(SDNode *N) {
|
static bool isSHUFPMask(std::vector<SDOperand> &N) {
|
||||||
assert(N->getOpcode() == ISD::BUILD_VECTOR);
|
unsigned NumElems = N.size();
|
||||||
|
if (NumElems != 2 && NumElems != 4) return false;
|
||||||
|
|
||||||
unsigned NumElems = N->getNumOperands();
|
unsigned Half = NumElems / 2;
|
||||||
if (NumElems == 2) {
|
for (unsigned i = 0; i < Half; ++i)
|
||||||
// The only cases that ought be handled by SHUFPD is
|
if (!isUndefOrInRange(N[i], 0, NumElems))
|
||||||
// Dest { 2, 1 } <= shuffle( Dest { 1, 0 }, Src { 3, 2 }
|
return false;
|
||||||
// Dest { 3, 0 } <= shuffle( Dest { 1, 0 }, Src { 3, 2 }
|
for (unsigned i = Half; i < NumElems; ++i)
|
||||||
// Expect bit 0 == 1, bit1 == 2
|
if (!isUndefOrInRange(N[i], NumElems, NumElems*2))
|
||||||
SDOperand Bit0 = N->getOperand(0);
|
return false;
|
||||||
SDOperand Bit1 = N->getOperand(1);
|
|
||||||
if (isUndefOrEqual(Bit0, 0) && isUndefOrEqual(Bit1, 3))
|
|
||||||
return true;
|
|
||||||
if (isUndefOrEqual(Bit0, 1) && isUndefOrEqual(Bit1, 2))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NumElems != 4) return false;
|
|
||||||
|
|
||||||
// Each half must refer to only one of the vector.
|
|
||||||
for (unsigned i = 0; i < 2; ++i) {
|
|
||||||
SDOperand Arg = N->getOperand(i);
|
|
||||||
if (Arg.getOpcode() == ISD::UNDEF) continue;
|
|
||||||
assert(isa<ConstantSDNode>(Arg) && "Invalid VECTOR_SHUFFLE mask!");
|
|
||||||
unsigned Val = cast<ConstantSDNode>(Arg)->getValue();
|
|
||||||
if (Val >= 4) return false;
|
|
||||||
}
|
|
||||||
for (unsigned i = 2; i < 4; ++i) {
|
|
||||||
SDOperand Arg = N->getOperand(i);
|
|
||||||
if (Arg.getOpcode() == ISD::UNDEF) continue;
|
|
||||||
assert(isa<ConstantSDNode>(Arg) && "Invalid VECTOR_SHUFFLE mask!");
|
|
||||||
unsigned Val = cast<ConstantSDNode>(Arg)->getValue();
|
|
||||||
if (Val < 4) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool X86::isSHUFPMask(SDNode *N) {
|
||||||
|
assert(N->getOpcode() == ISD::BUILD_VECTOR);
|
||||||
|
std::vector<SDOperand> Ops(N->op_begin(), N->op_end());
|
||||||
|
return ::isSHUFPMask(Ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// isCommutedSHUFP - Returns true if the shuffle mask is except
|
||||||
|
/// the reverse of what x86 shuffles want. x86 shuffles requires the lower
|
||||||
|
/// half elements to come from vector 1 (which would equal the dest.) and
|
||||||
|
/// the upper half to come from vector 2.
|
||||||
|
static bool isCommutedSHUFP(std::vector<SDOperand> &Ops) {
|
||||||
|
unsigned NumElems = Ops.size();
|
||||||
|
if (NumElems != 2 && NumElems != 4) return false;
|
||||||
|
|
||||||
|
unsigned Half = NumElems / 2;
|
||||||
|
for (unsigned i = 0; i < Half; ++i)
|
||||||
|
if (!isUndefOrInRange(Ops[i], NumElems, NumElems*2))
|
||||||
|
return false;
|
||||||
|
for (unsigned i = Half; i < NumElems; ++i)
|
||||||
|
if (!isUndefOrInRange(Ops[i], 0, NumElems))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isCommutedSHUFP(SDNode *N) {
|
||||||
|
assert(N->getOpcode() == ISD::BUILD_VECTOR);
|
||||||
|
std::vector<SDOperand> Ops(N->op_begin(), N->op_end());
|
||||||
|
return isCommutedSHUFP(Ops);
|
||||||
|
}
|
||||||
|
|
||||||
/// isMOVHLPSMask - Return true if the specified VECTOR_SHUFFLE operand
|
/// isMOVHLPSMask - Return true if the specified VECTOR_SHUFFLE operand
|
||||||
/// specifies a shuffle of elements that is suitable for input to MOVHLPS.
|
/// specifies a shuffle of elements that is suitable for input to MOVHLPS.
|
||||||
bool X86::isMOVHLPSMask(SDNode *N) {
|
bool X86::isMOVHLPSMask(SDNode *N) {
|
||||||
@ -1600,46 +1606,64 @@ bool X86::isMOVHPMask(SDNode *N) {
|
|||||||
|
|
||||||
/// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand
|
/// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand
|
||||||
/// specifies a shuffle of elements that is suitable for input to UNPCKL.
|
/// specifies a shuffle of elements that is suitable for input to UNPCKL.
|
||||||
bool X86::isUNPCKLMask(SDNode *N) {
|
bool static isUNPCKLMask(std::vector<SDOperand> &N, bool V2IsSplat = false) {
|
||||||
assert(N->getOpcode() == ISD::BUILD_VECTOR);
|
unsigned NumElems = N.size();
|
||||||
|
|
||||||
unsigned NumElems = N->getNumOperands();
|
|
||||||
if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16)
|
if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (unsigned i = 0, j = 0; i != NumElems; i += 2, ++j) {
|
for (unsigned i = 0, j = 0; i != NumElems; i += 2, ++j) {
|
||||||
SDOperand BitI = N->getOperand(i);
|
SDOperand BitI = N[i];
|
||||||
SDOperand BitI1 = N->getOperand(i+1);
|
SDOperand BitI1 = N[i+1];
|
||||||
if (!isUndefOrEqual(BitI, j))
|
if (!isUndefOrEqual(BitI, j))
|
||||||
return false;
|
return false;
|
||||||
if (!isUndefOrEqual(BitI1, j + NumElems))
|
if (V2IsSplat) {
|
||||||
return false;
|
if (isUndefOrEqual(BitI1, NumElems))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (!isUndefOrEqual(BitI1, j + NumElems))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool X86::isUNPCKLMask(SDNode *N, bool V2IsSplat) {
|
||||||
|
assert(N->getOpcode() == ISD::BUILD_VECTOR);
|
||||||
|
std::vector<SDOperand> Ops(N->op_begin(), N->op_end());
|
||||||
|
return ::isUNPCKLMask(Ops, V2IsSplat);
|
||||||
|
}
|
||||||
|
|
||||||
/// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand
|
/// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand
|
||||||
/// specifies a shuffle of elements that is suitable for input to UNPCKH.
|
/// specifies a shuffle of elements that is suitable for input to UNPCKH.
|
||||||
bool X86::isUNPCKHMask(SDNode *N) {
|
bool static isUNPCKHMask(std::vector<SDOperand> &N, bool V2IsSplat = false) {
|
||||||
assert(N->getOpcode() == ISD::BUILD_VECTOR);
|
unsigned NumElems = N.size();
|
||||||
|
|
||||||
unsigned NumElems = N->getNumOperands();
|
|
||||||
if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16)
|
if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (unsigned i = 0, j = 0; i != NumElems; i += 2, ++j) {
|
for (unsigned i = 0, j = 0; i != NumElems; i += 2, ++j) {
|
||||||
SDOperand BitI = N->getOperand(i);
|
SDOperand BitI = N[i];
|
||||||
SDOperand BitI1 = N->getOperand(i+1);
|
SDOperand BitI1 = N[i+1];
|
||||||
if (!isUndefOrEqual(BitI, j + NumElems/2))
|
if (!isUndefOrEqual(BitI, j + NumElems/2))
|
||||||
return false;
|
return false;
|
||||||
if (!isUndefOrEqual(BitI1, j + NumElems/2 + NumElems))
|
if (V2IsSplat) {
|
||||||
return false;
|
if (isUndefOrEqual(BitI1, NumElems))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (!isUndefOrEqual(BitI1, j + NumElems/2 + NumElems))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool X86::isUNPCKHMask(SDNode *N, bool V2IsSplat) {
|
||||||
|
assert(N->getOpcode() == ISD::BUILD_VECTOR);
|
||||||
|
std::vector<SDOperand> Ops(N->op_begin(), N->op_end());
|
||||||
|
return ::isUNPCKHMask(Ops, V2IsSplat);
|
||||||
|
}
|
||||||
|
|
||||||
/// isUNPCKL_v_undef_Mask - Special case of isUNPCKLMask for canonical form
|
/// isUNPCKL_v_undef_Mask - Special case of isUNPCKLMask for canonical form
|
||||||
/// of vector_shuffle v, v, <0, 4, 1, 5>, i.e. vector_shuffle v, undef,
|
/// of vector_shuffle v, v, <0, 4, 1, 5>, i.e. vector_shuffle v, undef,
|
||||||
/// <0, 0, 1, 1>
|
/// <0, 0, 1, 1>
|
||||||
@ -1665,18 +1689,16 @@ bool X86::isUNPCKL_v_undef_Mask(SDNode *N) {
|
|||||||
|
|
||||||
/// isMOVSMask - Return true if the specified VECTOR_SHUFFLE operand
|
/// isMOVSMask - Return true if the specified VECTOR_SHUFFLE operand
|
||||||
/// specifies a shuffle of elements that is suitable for input to MOVS{S|D}.
|
/// specifies a shuffle of elements that is suitable for input to MOVS{S|D}.
|
||||||
bool X86::isMOVSMask(SDNode *N) {
|
static bool isMOVSMask(std::vector<SDOperand> &N) {
|
||||||
assert(N->getOpcode() == ISD::BUILD_VECTOR);
|
unsigned NumElems = N.size();
|
||||||
|
|
||||||
unsigned NumElems = N->getNumOperands();
|
|
||||||
if (NumElems != 2 && NumElems != 4)
|
if (NumElems != 2 && NumElems != 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!isUndefOrEqual(N->getOperand(0), NumElems))
|
if (!isUndefOrEqual(N[0], NumElems))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (unsigned i = 1; i < NumElems; ++i) {
|
for (unsigned i = 1; i < NumElems; ++i) {
|
||||||
SDOperand Arg = N->getOperand(i);
|
SDOperand Arg = N[i];
|
||||||
if (!isUndefOrEqual(Arg, i))
|
if (!isUndefOrEqual(Arg, i))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1684,6 +1706,43 @@ bool X86::isMOVSMask(SDNode *N) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool X86::isMOVSMask(SDNode *N) {
|
||||||
|
assert(N->getOpcode() == ISD::BUILD_VECTOR);
|
||||||
|
std::vector<SDOperand> Ops(N->op_begin(), N->op_end());
|
||||||
|
return ::isMOVSMask(Ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// isCommutedMOVS - Returns true if the shuffle mask is except the reverse
|
||||||
|
/// of what x86 movs want. X86 movs requires the lowest element to be lowest
|
||||||
|
/// element of vector 2 and the other elements to come from vector 1 in order.
|
||||||
|
static bool isCommutedMOVS(std::vector<SDOperand> &Ops, bool V2IsSplat = false) {
|
||||||
|
unsigned NumElems = Ops.size();
|
||||||
|
if (NumElems != 2 && NumElems != 4)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!isUndefOrEqual(Ops[0], 0))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (unsigned i = 1; i < NumElems; ++i) {
|
||||||
|
SDOperand Arg = Ops[i];
|
||||||
|
if (V2IsSplat) {
|
||||||
|
if (!isUndefOrEqual(Arg, NumElems))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (!isUndefOrEqual(Arg, i+NumElems))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isCommutedMOVS(SDNode *N, bool V2IsSplat = false) {
|
||||||
|
assert(N->getOpcode() == ISD::BUILD_VECTOR);
|
||||||
|
std::vector<SDOperand> Ops(N->op_begin(), N->op_end());
|
||||||
|
return isCommutedMOVS(Ops);
|
||||||
|
}
|
||||||
|
|
||||||
/// isMOVSHDUPMask - Return true if the specified VECTOR_SHUFFLE operand
|
/// isMOVSHDUPMask - Return true if the specified VECTOR_SHUFFLE operand
|
||||||
/// specifies a shuffle of elements that is suitable for input to MOVSHDUP.
|
/// specifies a shuffle of elements that is suitable for input to MOVSHDUP.
|
||||||
bool X86::isMOVSHDUPMask(SDNode *N) {
|
bool X86::isMOVSHDUPMask(SDNode *N) {
|
||||||
@ -1958,23 +2017,57 @@ static bool ShouldXformToMOVLP(SDNode *V1, SDNode *Mask) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isLowerFromV2UpperFromV1 - Returns true if the shuffle mask is except
|
/// isSplatVector - Returns true if N is a BUILD_VECTOR node whose elements are
|
||||||
/// the reverse of what x86 shuffles want. x86 shuffles requires the lower
|
/// all the same.
|
||||||
/// half elements to come from vector 1 (which would equal the dest.) and
|
static bool isSplatVector(SDNode *N) {
|
||||||
/// the upper half to come from vector 2.
|
if (N->getOpcode() != ISD::BUILD_VECTOR)
|
||||||
static bool isLowerFromV2UpperFromV1(SDOperand Op) {
|
return false;
|
||||||
assert(Op.getOpcode() == ISD::BUILD_VECTOR);
|
|
||||||
|
|
||||||
unsigned NumElems = Op.getNumOperands();
|
SDOperand SplatValue = N->getOperand(0);
|
||||||
for (unsigned i = 0, e = NumElems/2; i != e; ++i)
|
for (unsigned i = 1, e = N->getNumOperands(); i != e; ++i)
|
||||||
if (!isUndefOrInRange(Op.getOperand(i), NumElems, NumElems*2))
|
if (N->getOperand(i) != SplatValue)
|
||||||
return false;
|
|
||||||
for (unsigned i = NumElems/2; i != NumElems; ++i)
|
|
||||||
if (!isUndefOrInRange(Op.getOperand(i), 0, NumElems))
|
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// NormalizeMask - V2 is a splat, modify the mask (if needed) so all elements
|
||||||
|
/// that point to V2 points to its first element.
|
||||||
|
static SDOperand NormalizeMask(SDOperand Mask, SelectionDAG &DAG) {
|
||||||
|
assert(Mask.getOpcode() == ISD::BUILD_VECTOR);
|
||||||
|
|
||||||
|
bool Changed = false;
|
||||||
|
std::vector<SDOperand> MaskVec;
|
||||||
|
unsigned NumElems = Mask.getNumOperands();
|
||||||
|
for (unsigned i = 0; i != NumElems; ++i) {
|
||||||
|
SDOperand Arg = Mask.getOperand(i);
|
||||||
|
if (Arg.getOpcode() != ISD::UNDEF) {
|
||||||
|
unsigned Val = cast<ConstantSDNode>(Arg)->getValue();
|
||||||
|
if (Val > NumElems) {
|
||||||
|
Arg = DAG.getConstant(NumElems, Arg.getValueType());
|
||||||
|
Changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MaskVec.push_back(Arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Changed)
|
||||||
|
Mask = DAG.getNode(ISD::BUILD_VECTOR, Mask.getValueType(), MaskVec);
|
||||||
|
return Mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getMOVSMask - Returns a vector_shuffle mask for an movs{s|d} operation
|
||||||
|
/// of specified width.
|
||||||
|
static SDOperand getMOVSMask(unsigned NumElems, SelectionDAG &DAG) {
|
||||||
|
MVT::ValueType MaskVT = MVT::getIntVectorWithNumElements(NumElems);
|
||||||
|
MVT::ValueType BaseVT = MVT::getVectorBaseType(MaskVT);
|
||||||
|
|
||||||
|
std::vector<SDOperand> MaskVec;
|
||||||
|
MaskVec.push_back(DAG.getConstant(NumElems, BaseVT));
|
||||||
|
for (unsigned i = 1; i != NumElems; ++i)
|
||||||
|
MaskVec.push_back(DAG.getConstant(i, BaseVT));
|
||||||
|
return DAG.getNode(ISD::BUILD_VECTOR, MaskVT, MaskVec);
|
||||||
|
}
|
||||||
|
|
||||||
/// getUnpacklMask - Returns a vector_shuffle mask for an unpackl operation
|
/// getUnpacklMask - Returns a vector_shuffle mask for an unpackl operation
|
||||||
/// of specified width.
|
/// of specified width.
|
||||||
static SDOperand getUnpacklMask(unsigned NumElems, SelectionDAG &DAG) {
|
static SDOperand getUnpacklMask(unsigned NumElems, SelectionDAG &DAG) {
|
||||||
@ -1988,6 +2081,20 @@ static SDOperand getUnpacklMask(unsigned NumElems, SelectionDAG &DAG) {
|
|||||||
return DAG.getNode(ISD::BUILD_VECTOR, MaskVT, MaskVec);
|
return DAG.getNode(ISD::BUILD_VECTOR, MaskVT, MaskVec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getUnpackhMask - Returns a vector_shuffle mask for an unpackh operation
|
||||||
|
/// of specified width.
|
||||||
|
static SDOperand getUnpackhMask(unsigned NumElems, SelectionDAG &DAG) {
|
||||||
|
MVT::ValueType MaskVT = MVT::getIntVectorWithNumElements(NumElems);
|
||||||
|
MVT::ValueType BaseVT = MVT::getVectorBaseType(MaskVT);
|
||||||
|
unsigned Half = NumElems/2;
|
||||||
|
std::vector<SDOperand> MaskVec;
|
||||||
|
for (unsigned i = 0; i != Half; ++i) {
|
||||||
|
MaskVec.push_back(DAG.getConstant(i + Half, BaseVT));
|
||||||
|
MaskVec.push_back(DAG.getConstant(i + NumElems + Half, BaseVT));
|
||||||
|
}
|
||||||
|
return DAG.getNode(ISD::BUILD_VECTOR, MaskVT, MaskVec);
|
||||||
|
}
|
||||||
|
|
||||||
/// PromoteSplat - Promote a splat of v8i16 or v16i8 to v4i32.
|
/// PromoteSplat - Promote a splat of v8i16 or v16i8 to v4i32.
|
||||||
///
|
///
|
||||||
static SDOperand PromoteSplat(SDOperand Op, SelectionDAG &DAG) {
|
static SDOperand PromoteSplat(SDOperand Op, SelectionDAG &DAG) {
|
||||||
@ -2817,6 +2924,7 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
SDOperand PermMask = Op.getOperand(2);
|
SDOperand PermMask = Op.getOperand(2);
|
||||||
MVT::ValueType VT = Op.getValueType();
|
MVT::ValueType VT = Op.getValueType();
|
||||||
unsigned NumElems = PermMask.getNumOperands();
|
unsigned NumElems = PermMask.getNumOperands();
|
||||||
|
bool V2IsSplat = isSplatVector(V2.Val);
|
||||||
|
|
||||||
if (isSplatMask(PermMask.Val)) {
|
if (isSplatMask(PermMask.Val)) {
|
||||||
if (NumElems <= 4) return Op;
|
if (NumElems <= 4) return Op;
|
||||||
@ -2824,10 +2932,6 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
return PromoteSplat(Op, DAG);
|
return PromoteSplat(Op, DAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShouldXformToMOVHLPS(PermMask.Val) ||
|
|
||||||
ShouldXformToMOVLP(V1.Val, PermMask.Val))
|
|
||||||
return CommuteVectorShuffle(Op, DAG);
|
|
||||||
|
|
||||||
if (X86::isMOVSMask(PermMask.Val) ||
|
if (X86::isMOVSMask(PermMask.Val) ||
|
||||||
X86::isMOVSHDUPMask(PermMask.Val) ||
|
X86::isMOVSHDUPMask(PermMask.Val) ||
|
||||||
X86::isMOVSLDUPMask(PermMask.Val) ||
|
X86::isMOVSLDUPMask(PermMask.Val) ||
|
||||||
@ -2836,15 +2940,45 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
X86::isMOVLPMask(PermMask.Val))
|
X86::isMOVLPMask(PermMask.Val))
|
||||||
return Op;
|
return Op;
|
||||||
|
|
||||||
if (X86::isUNPCKLMask(PermMask.Val) ||
|
if (ShouldXformToMOVHLPS(PermMask.Val) ||
|
||||||
X86::isUNPCKL_v_undef_Mask(PermMask.Val) ||
|
ShouldXformToMOVLP(V1.Val, PermMask.Val))
|
||||||
X86::isUNPCKHMask(PermMask.Val))
|
return CommuteVectorShuffle(Op, DAG);
|
||||||
// Leave the VECTOR_SHUFFLE alone. It matches {P}UNPCKL*.
|
|
||||||
|
if (isCommutedMOVS(PermMask.Val, V2IsSplat)) {
|
||||||
|
if (V2IsSplat) {
|
||||||
|
// V2 is a splat, so the mask may be malformed. That is, it may point
|
||||||
|
// to any V2 element. The instruction selectior won't like this. Get
|
||||||
|
// a corrected mask and commute to form a proper MOVS{S|D}.
|
||||||
|
SDOperand NewMask = getMOVSMask(NumElems, DAG);
|
||||||
|
Op = DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2, NewMask);
|
||||||
|
}
|
||||||
|
return CommuteVectorShuffle(Op, DAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (X86::isUNPCKL_v_undef_Mask(PermMask.Val) ||
|
||||||
|
X86::isUNPCKLMask(PermMask.Val) ||
|
||||||
|
X86::isUNPCKHMask(PermMask.Val, V2IsSplat))
|
||||||
return Op;
|
return Op;
|
||||||
|
|
||||||
|
if (V2IsSplat) {
|
||||||
|
// Normalize mask so all entries that point to V2 points to its first
|
||||||
|
// element then try to match unpck{h|l} again. If match, return a
|
||||||
|
// new vector_shuffle with the corrected mask.
|
||||||
|
SDOperand NewMask = NormalizeMask(PermMask, DAG);
|
||||||
|
if (NewMask.Val != PermMask.Val) {
|
||||||
|
if (X86::isUNPCKLMask(PermMask.Val, true)) {
|
||||||
|
SDOperand NewMask = getUnpacklMask(NumElems, DAG);
|
||||||
|
return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2, NewMask);
|
||||||
|
} else if (X86::isUNPCKHMask(PermMask.Val, true)) {
|
||||||
|
SDOperand NewMask = getUnpackhMask(NumElems, DAG);
|
||||||
|
return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2, NewMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Normalize the node to match x86 shuffle ops if needed
|
// Normalize the node to match x86 shuffle ops if needed
|
||||||
if (V2.getOpcode() != ISD::UNDEF)
|
if (V2.getOpcode() != ISD::UNDEF)
|
||||||
if (isLowerFromV2UpperFromV1(PermMask)) {
|
if (isCommutedSHUFP(PermMask.Val)) {
|
||||||
Op = CommuteVectorShuffle(Op, DAG);
|
Op = CommuteVectorShuffle(Op, DAG);
|
||||||
V1 = Op.getOperand(0);
|
V1 = Op.getOperand(0);
|
||||||
V2 = Op.getOperand(1);
|
V2 = Op.getOperand(1);
|
||||||
@ -3041,7 +3175,6 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
if (Idx == 0)
|
if (Idx == 0)
|
||||||
return Op;
|
return Op;
|
||||||
|
|
||||||
// TODO: if Idex == 2, we can use unpckhps
|
|
||||||
// SHUFPS the element to the lowest double word, then movss.
|
// SHUFPS the element to the lowest double word, then movss.
|
||||||
MVT::ValueType MaskVT = MVT::getIntVectorWithNumElements(4);
|
MVT::ValueType MaskVT = MVT::getIntVectorWithNumElements(4);
|
||||||
SDOperand IdxNode = DAG.getConstant((Idx < 2) ? Idx : Idx+4,
|
SDOperand IdxNode = DAG.getConstant((Idx < 2) ? Idx : Idx+4,
|
||||||
@ -3372,3 +3505,17 @@ X86TargetLowering::isShuffleMaskLegal(SDOperand Mask, MVT::ValueType VT) const {
|
|||||||
X86::isUNPCKL_v_undef_Mask(Mask.Val) ||
|
X86::isUNPCKL_v_undef_Mask(Mask.Val) ||
|
||||||
X86::isUNPCKHMask(Mask.Val));
|
X86::isUNPCKHMask(Mask.Val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool X86TargetLowering::isVectorClearMaskLegal(std::vector<SDOperand> &BVOps,
|
||||||
|
MVT::ValueType EVT,
|
||||||
|
SelectionDAG &DAG) const {
|
||||||
|
unsigned NumElts = BVOps.size();
|
||||||
|
// Only do shuffles on 128-bit vector types for now.
|
||||||
|
if (MVT::getSizeInBits(EVT) * NumElts == 64) return false;
|
||||||
|
if (NumElts == 2) return true;
|
||||||
|
if (NumElts == 4) {
|
||||||
|
return (isMOVSMask(BVOps) || isCommutedMOVS(BVOps, true) ||
|
||||||
|
isSHUFPMask(BVOps) || isCommutedSHUFP(BVOps));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -219,11 +219,11 @@ namespace llvm {
|
|||||||
|
|
||||||
/// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand
|
/// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand
|
||||||
/// specifies a shuffle of elements that is suitable for input to UNPCKL.
|
/// specifies a shuffle of elements that is suitable for input to UNPCKL.
|
||||||
bool isUNPCKLMask(SDNode *N);
|
bool isUNPCKLMask(SDNode *N, bool V2IsSplat = false);
|
||||||
|
|
||||||
/// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand
|
/// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand
|
||||||
/// specifies a shuffle of elements that is suitable for input to UNPCKH.
|
/// specifies a shuffle of elements that is suitable for input to UNPCKH.
|
||||||
bool isUNPCKHMask(SDNode *N);
|
bool isUNPCKHMask(SDNode *N, bool V2IsSplat = false);
|
||||||
|
|
||||||
/// isUNPCKL_v_undef_Mask - Special case of isUNPCKLMask for canonical form
|
/// isUNPCKL_v_undef_Mask - Special case of isUNPCKLMask for canonical form
|
||||||
/// of vector_shuffle v, v, <0, 4, 1, 5>, i.e. vector_shuffle v, undef,
|
/// of vector_shuffle v, v, <0, 4, 1, 5>, i.e. vector_shuffle v, undef,
|
||||||
@ -333,6 +333,14 @@ namespace llvm {
|
|||||||
/// By default, if a target supports the VECTOR_SHUFFLE node, all mask values
|
/// By default, if a target supports the VECTOR_SHUFFLE node, all mask values
|
||||||
/// are assumed to be legal.
|
/// are assumed to be legal.
|
||||||
virtual bool isShuffleMaskLegal(SDOperand Mask, MVT::ValueType VT) const;
|
virtual bool isShuffleMaskLegal(SDOperand Mask, MVT::ValueType VT) const;
|
||||||
|
|
||||||
|
/// isVectorClearMaskLegal - Similar to isShuffleMaskLegal. This is
|
||||||
|
/// used by Targets can use this to indicate if there is a suitable
|
||||||
|
/// VECTOR_SHUFFLE that can be used to replace a VAND with a constant
|
||||||
|
/// pool entry.
|
||||||
|
virtual bool isVectorClearMaskLegal(std::vector<SDOperand> &BVOps,
|
||||||
|
MVT::ValueType EVT,
|
||||||
|
SelectionDAG &DAG) const;
|
||||||
private:
|
private:
|
||||||
// C Calling Convention implementation.
|
// C Calling Convention implementation.
|
||||||
std::vector<SDOperand> LowerCCCArguments(Function &F, SelectionDAG &DAG);
|
std::vector<SDOperand> LowerCCCArguments(Function &F, SelectionDAG &DAG);
|
||||||
|
Loading…
Reference in New Issue
Block a user