"llvm/git@repo.hca.bsc.es:lalbano/llvm-bpevl.git" did not exist on "b12634bf80d28ed8dc28497c3e172a324f089d8f"
Newer
Older
return (Mask[0] < 2 && Mask[1] < 2);
return false;
bool X86::isPSHUFDMask(ShuffleVectorSDNode *N) {
N->getMask(M);
return ::isPSHUFDMask(M, N->getValueType(0));
}
/// isPSHUFHWMask - Return true if the node specifies a shuffle of elements that
/// is suitable for input to PSHUFHW.
Owen Anderson
committed
static bool isPSHUFHWMask(const SmallVectorImpl<int> &Mask, EVT VT) {
Owen Anderson
committed
if (VT != MVT::v8i16)
// Lower quadword copied in order or undef.
for (int i = 0; i != 4; ++i)
if (Mask[i] >= 0 && Mask[i] != i)
for (int i = 4; i != 8; ++i)
if (Mask[i] >= 0 && (Mask[i] < 4 || Mask[i] > 7))
bool X86::isPSHUFHWMask(ShuffleVectorSDNode *N) {
N->getMask(M);
return ::isPSHUFHWMask(M, N->getValueType(0));
}
/// isPSHUFLWMask - Return true if the node specifies a shuffle of elements that
/// is suitable for input to PSHUFLW.
Owen Anderson
committed
static bool isPSHUFLWMask(const SmallVectorImpl<int> &Mask, EVT VT) {
Owen Anderson
committed
if (VT != MVT::v8i16)
// Upper quadword copied in order.
for (int i = 4; i != 8; ++i)
if (Mask[i] >= 0 && Mask[i] != i)
for (int i = 0; i != 4; ++i)
if (Mask[i] >= 4)
return true;
bool X86::isPSHUFLWMask(ShuffleVectorSDNode *N) {
N->getMask(M);
return ::isPSHUFLWMask(M, N->getValueType(0));
}
/// isPALIGNRMask - Return true if the node specifies a shuffle of elements that
/// is suitable for input to PALIGNR.
static bool isPALIGNRMask(const SmallVectorImpl<int> &Mask, EVT VT,
bool hasSSSE3) {
int i, e = VT.getVectorNumElements();
// Do not handle v2i64 / v2f64 shuffles with palignr.
if (e < 4 || !hasSSSE3)
return false;
for (i = 0; i != e; ++i)
if (Mask[i] >= 0)
break;
// All undef, not a palignr.
if (i == e)
return false;
Eli Friedman
committed
// Make sure we're shifting in the right direction.
if (Mask[i] <= i)
return false;
int s = Mask[i] - i;
// Check the rest of the elements to see if they are consecutive.
for (++i; i != e; ++i) {
int m = Mask[i];
Eli Friedman
committed
if (m >= 0 && m != s+i)
return false;
}
return true;
}
bool X86::isPALIGNRMask(ShuffleVectorSDNode *N) {
SmallVector<int, 8> M;
N->getMask(M);
return ::isPALIGNRMask(M, N->getValueType(0), true);
}
/// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to SHUFP*.
Owen Anderson
committed
static bool isSHUFPMask(const SmallVectorImpl<int> &Mask, EVT VT) {
int NumElems = VT.getVectorNumElements();
if (NumElems != 2 && NumElems != 4)
return false;
int Half = NumElems / 2;
for (int i = 0; i < Half; ++i)
if (!isUndefOrInRange(Mask[i], 0, NumElems))
return false;
for (int i = Half; i < NumElems; ++i)
if (!isUndefOrInRange(Mask[i], NumElems, NumElems*2))
return false;
return true;
}
bool X86::isSHUFPMask(ShuffleVectorSDNode *N) {
SmallVector<int, 8> M;
N->getMask(M);
return ::isSHUFPMask(M, N->getValueType(0));
}
/// isCommutedSHUFP - Returns true if the shuffle mask is exactly
/// 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.
Owen Anderson
committed
static bool isCommutedSHUFPMask(const SmallVectorImpl<int> &Mask, EVT VT) {
int NumElems = VT.getVectorNumElements();
return false;
int Half = NumElems / 2;
for (int i = 0; i < Half; ++i)
if (!isUndefOrInRange(Mask[i], NumElems, NumElems*2))
return false;
for (int i = Half; i < NumElems; ++i)
if (!isUndefOrInRange(Mask[i], 0, NumElems))
return false;
return true;
}
static bool isCommutedSHUFP(ShuffleVectorSDNode *N) {
SmallVector<int, 8> M;
N->getMask(M);
return isCommutedSHUFPMask(M, N->getValueType(0));
}
/// isMOVHLPSMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVHLPS.
bool X86::isMOVHLPSMask(ShuffleVectorSDNode *N) {
if (N->getValueType(0).getVectorNumElements() != 4)
return false;
// Expect bit0 == 6, bit1 == 7, bit2 == 2, bit3 == 3
return isUndefOrEqual(N->getMaskElt(0), 6) &&
isUndefOrEqual(N->getMaskElt(1), 7) &&
isUndefOrEqual(N->getMaskElt(2), 2) &&
isUndefOrEqual(N->getMaskElt(3), 3);
/// isMOVHLPS_v_undef_Mask - Special case of isMOVHLPSMask for canonical form
/// of vector_shuffle v, v, <2, 3, 2, 3>, i.e. vector_shuffle v, undef,
/// <2, 3, 2, 3>
bool X86::isMOVHLPS_v_undef_Mask(ShuffleVectorSDNode *N) {
unsigned NumElems = N->getValueType(0).getVectorNumElements();
return isUndefOrEqual(N->getMaskElt(0), 2) &&
isUndefOrEqual(N->getMaskElt(1), 3) &&
isUndefOrEqual(N->getMaskElt(2), 2) &&
isUndefOrEqual(N->getMaskElt(3), 3);
}
/// isMOVLPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVLP{S|D}.
bool X86::isMOVLPMask(ShuffleVectorSDNode *N) {
unsigned NumElems = N->getValueType(0).getVectorNumElements();
if (NumElems != 2 && NumElems != 4)
return false;
if (!isUndefOrEqual(N->getMaskElt(i), i + NumElems))
if (!isUndefOrEqual(N->getMaskElt(i), i))
/// isMOVLHPSMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVLHPS.
bool X86::isMOVLHPSMask(ShuffleVectorSDNode *N) {
unsigned NumElems = N->getValueType(0).getVectorNumElements();
if ((NumElems != 2 && NumElems != 4)
|| N->getValueType(0).getSizeInBits() > 128)
if (!isUndefOrEqual(N->getMaskElt(i), i))
for (unsigned i = 0; i < NumElems/2; ++i)
if (!isUndefOrEqual(N->getMaskElt(i + NumElems/2), i + NumElems))
/// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to UNPCKL.
Owen Anderson
committed
static bool isUNPCKLMask(const SmallVectorImpl<int> &Mask, EVT VT,
bool V2IsSplat = false) {
int NumElts = VT.getVectorNumElements();
if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16)
return false;
// Handle vector lengths > 128 bits. Define a "section" as a set of
// 128 bits. AVX defines UNPCK* to operate independently on 128-bit
// sections.
unsigned NumSections = VT.getSizeInBits() / 128;
if (NumSections == 0 ) NumSections = 1; // Handle MMX
unsigned NumSectionElts = NumElts / NumSections;
unsigned Start = 0;
unsigned End = NumSectionElts;
for (unsigned s = 0; s < NumSections; ++s) {
for (unsigned i = Start, j = s * NumSectionElts;
i != End;
i += 2, ++j) {
int BitI = Mask[i];
int BitI1 = Mask[i+1];
if (!isUndefOrEqual(BitI, j))
return false;
if (V2IsSplat) {
if (!isUndefOrEqual(BitI1, NumElts))
return false;
} else {
if (!isUndefOrEqual(BitI1, j + NumElts))
return false;
}
}
// Process the next 128 bits.
Start += NumSectionElts;
End += NumSectionElts;
}
bool X86::isUNPCKLMask(ShuffleVectorSDNode *N, bool V2IsSplat) {
SmallVector<int, 8> M;
N->getMask(M);
return ::isUNPCKLMask(M, N->getValueType(0), V2IsSplat);
}
/// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to UNPCKH.
static bool isUNPCKHMask(const SmallVectorImpl<int> &Mask, EVT VT,
bool V2IsSplat = false) {
int NumElts = VT.getVectorNumElements();
if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16)
return false;
for (int i = 0, j = 0; i != NumElts; i += 2, ++j) {
int BitI = Mask[i];
int BitI1 = Mask[i+1];
if (!isUndefOrEqual(BitI, j + NumElts/2))
if (V2IsSplat) {
if (isUndefOrEqual(BitI1, NumElts))
return false;
} else {
if (!isUndefOrEqual(BitI1, j + NumElts/2 + NumElts))
return false;
}
}
return true;
}
bool X86::isUNPCKHMask(ShuffleVectorSDNode *N, bool V2IsSplat) {
SmallVector<int, 8> M;
N->getMask(M);
return ::isUNPCKHMask(M, N->getValueType(0), V2IsSplat);
}
/// 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,
/// <0, 0, 1, 1>
Owen Anderson
committed
static bool isUNPCKL_v_undef_Mask(const SmallVectorImpl<int> &Mask, EVT VT) {
int NumElems = VT.getVectorNumElements();
if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16)
// Handle vector lengths > 128 bits. Define a "section" as a set of
// 128 bits. AVX defines UNPCK* to operate independently on 128-bit
// sections.
unsigned NumSections = VT.getSizeInBits() / 128;
if (NumSections == 0 ) NumSections = 1; // Handle MMX
unsigned NumSectionElts = NumElems / NumSections;
for (unsigned s = 0; s < NumSections; ++s) {
for (unsigned i = s * NumSectionElts, j = s * NumSectionElts;
i != NumSectionElts * (s + 1);
i += 2, ++j) {
int BitI = Mask[i];
int BitI1 = Mask[i+1];
if (!isUndefOrEqual(BitI, j))
return false;
if (!isUndefOrEqual(BitI1, j))
return false;
}
return true;
bool X86::isUNPCKL_v_undef_Mask(ShuffleVectorSDNode *N) {
SmallVector<int, 8> M;
N->getMask(M);
return ::isUNPCKL_v_undef_Mask(M, N->getValueType(0));
}
/// isUNPCKH_v_undef_Mask - Special case of isUNPCKHMask for canonical form
/// of vector_shuffle v, v, <2, 6, 3, 7>, i.e. vector_shuffle v, undef,
/// <2, 2, 3, 3>
Owen Anderson
committed
static bool isUNPCKH_v_undef_Mask(const SmallVectorImpl<int> &Mask, EVT VT) {
int NumElems = VT.getVectorNumElements();
if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16)
return false;
for (int i = 0, j = NumElems / 2; i != NumElems; i += 2, ++j) {
int BitI = Mask[i];
int BitI1 = Mask[i+1];
if (!isUndefOrEqual(BitI, j))
return false;
if (!isUndefOrEqual(BitI1, j))
return false;
}
return true;
bool X86::isUNPCKH_v_undef_Mask(ShuffleVectorSDNode *N) {
SmallVector<int, 8> M;
N->getMask(M);
return ::isUNPCKH_v_undef_Mask(M, N->getValueType(0));
}
/// isMOVLMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVSS,
/// MOVSD, and MOVD, i.e. setting the lowest element.
Owen Anderson
committed
static bool isMOVLMask(const SmallVectorImpl<int> &Mask, EVT VT) {
if (VT.getVectorElementType().getSizeInBits() < 32)
return false;
int NumElts = VT.getVectorNumElements();
if (!isUndefOrEqual(Mask[0], NumElts))
return false;
for (int i = 1; i < NumElts; ++i)
if (!isUndefOrEqual(Mask[i], i))
return false;
return true;
}
bool X86::isMOVLMask(ShuffleVectorSDNode *N) {
SmallVector<int, 8> M;
N->getMask(M);
return ::isMOVLMask(M, N->getValueType(0));
}
Bruno Cardoso Lopes
committed
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
/// isVPERMILMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to VPERMIL*.
static bool isVPERMILMask(const SmallVectorImpl<int> &Mask, EVT VT) {
unsigned NumElts = VT.getVectorNumElements();
unsigned NumLanes = VT.getSizeInBits()/128;
// Match any permutation of 128-bit vector with 32/64-bit types
if (NumLanes == 1) {
if (NumElts == 4 || NumElts == 2)
return true;
return false;
}
// Only match 256-bit with 32/64-bit types
if (NumElts != 8 && NumElts != 4)
return false;
// The mask on the high lane should be the same as the low. Actually,
// they can differ if any of the corresponding index in a lane is undef.
int LaneSize = NumElts/NumLanes;
for (int i = 0; i < LaneSize; ++i) {
int HighElt = i+LaneSize;
if (Mask[i] < 0 || Mask[HighElt] < 0)
continue;
if (Mask[HighElt]-Mask[i] != LaneSize)
return false;
}
return true;
}
/// getShuffleVPERMILImmediateediate - Return the appropriate immediate to shuffle
/// the specified VECTOR_MASK mask with VPERMIL* instructions.
static unsigned getShuffleVPERMILImmediate(SDNode *N) {
ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
EVT VT = SVOp->getValueType(0);
int NumElts = VT.getVectorNumElements();
int NumLanes = VT.getSizeInBits()/128;
unsigned Mask = 0;
for (int i = 0; i < NumElts/NumLanes /* lane size */; ++i)
Mask |= SVOp->getMaskElt(i) << (i*2);
return Mask;
}
/// isCommutedMOVL - Returns true if the shuffle mask is except the reverse
/// of what x86 movss 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.
Owen Anderson
committed
static bool isCommutedMOVLMask(const SmallVectorImpl<int> &Mask, EVT VT,
bool V2IsSplat = false, bool V2IsUndef = false) {
int NumOps = VT.getVectorNumElements();
if (NumOps != 2 && NumOps != 4 && NumOps != 8 && NumOps != 16)
if (!isUndefOrEqual(Mask[0], 0))
for (int i = 1; i < NumOps; ++i)
if (!(isUndefOrEqual(Mask[i], i+NumOps) ||
(V2IsUndef && isUndefOrInRange(Mask[i], NumOps, NumOps*2)) ||
(V2IsSplat && isUndefOrEqual(Mask[i], NumOps))))
return false;
static bool isCommutedMOVL(ShuffleVectorSDNode *N, bool V2IsSplat = false,
bool V2IsUndef = false) {
SmallVector<int, 8> M;
N->getMask(M);
return isCommutedMOVLMask(M, N->getValueType(0), V2IsSplat, V2IsUndef);
}
/// isMOVSHDUPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVSHDUP.
Bruno Cardoso Lopes
committed
/// Masks to match: <1, 1, 3, 3> or <1, 1, 3, 3, 5, 5, 7, 7>
bool X86::isMOVSHDUPMask(ShuffleVectorSDNode *N,
const X86Subtarget *Subtarget) {
if (!Subtarget->hasSSE3() && !Subtarget->hasAVX())
Bruno Cardoso Lopes
committed
// The second vector must be undef
if (N->getOperand(1).getOpcode() != ISD::UNDEF)
return false;
EVT VT = N->getValueType(0);
unsigned NumElems = VT.getVectorNumElements();
Bruno Cardoso Lopes
committed
if ((VT.getSizeInBits() == 128 && NumElems != 4) ||
(VT.getSizeInBits() == 256 && NumElems != 8))
return false;
// "i+1" is the value the indexed mask element must have
for (unsigned i = 0; i < NumElems; i += 2)
if (!isUndefOrEqual(N->getMaskElt(i), i+1) ||
!isUndefOrEqual(N->getMaskElt(i+1), i+1))
return false;
Bruno Cardoso Lopes
committed
return true;
}
/// isMOVSLDUPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVSLDUP.
Bruno Cardoso Lopes
committed
/// Masks to match: <0, 0, 2, 2> or <0, 0, 2, 2, 4, 4, 6, 6>
bool X86::isMOVSLDUPMask(ShuffleVectorSDNode *N,
const X86Subtarget *Subtarget) {
if (!Subtarget->hasSSE3() && !Subtarget->hasAVX())
Bruno Cardoso Lopes
committed
// The second vector must be undef
if (N->getOperand(1).getOpcode() != ISD::UNDEF)
return false;
EVT VT = N->getValueType(0);
unsigned NumElems = VT.getVectorNumElements();
Bruno Cardoso Lopes
committed
if ((VT.getSizeInBits() == 128 && NumElems != 4) ||
(VT.getSizeInBits() == 256 && NumElems != 8))
return false;
// "i" is the value the indexed mask element must have
for (unsigned i = 0; i < NumElems; i += 2)
if (!isUndefOrEqual(N->getMaskElt(i), i) ||
!isUndefOrEqual(N->getMaskElt(i+1), i))
return false;
Bruno Cardoso Lopes
committed
return true;
Evan Cheng
committed
/// isMOVDDUPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVDDUP.
bool X86::isMOVDDUPMask(ShuffleVectorSDNode *N) {
int e = N->getValueType(0).getVectorNumElements() / 2;
for (int i = 0; i < e; ++i)
if (!isUndefOrEqual(N->getMaskElt(i), i))
Evan Cheng
committed
return false;
for (int i = 0; i < e; ++i)
if (!isUndefOrEqual(N->getMaskElt(e+i), i))
Evan Cheng
committed
return false;
return true;
}
/// isVEXTRACTF128Index - Return true if the specified
/// EXTRACT_SUBVECTOR operand specifies a vector extract that is
/// suitable for input to VEXTRACTF128.
bool X86::isVEXTRACTF128Index(SDNode *N) {
if (!isa<ConstantSDNode>(N->getOperand(1).getNode()))
return false;
// The index should be aligned on a 128-bit boundary.
uint64_t Index =
cast<ConstantSDNode>(N->getOperand(1).getNode())->getZExtValue();
unsigned VL = N->getValueType(0).getVectorNumElements();
unsigned VBits = N->getValueType(0).getSizeInBits();
unsigned ElSize = VBits / VL;
bool Result = (Index * ElSize) % 128 == 0;
return Result;
}
/// isVINSERTF128Index - Return true if the specified INSERT_SUBVECTOR
/// operand specifies a subvector insert that is suitable for input to
/// VINSERTF128.
bool X86::isVINSERTF128Index(SDNode *N) {
if (!isa<ConstantSDNode>(N->getOperand(2).getNode()))
return false;
// The index should be aligned on a 128-bit boundary.
uint64_t Index =
cast<ConstantSDNode>(N->getOperand(2).getNode())->getZExtValue();
unsigned VL = N->getValueType(0).getVectorNumElements();
unsigned VBits = N->getValueType(0).getSizeInBits();
unsigned ElSize = VBits / VL;
bool Result = (Index * ElSize) % 128 == 0;
return Result;
}
/// getShuffleSHUFImmediate - Return the appropriate immediate to shuffle
/// the specified VECTOR_SHUFFLE mask with PSHUF* and SHUFP* instructions.
unsigned X86::getShuffleSHUFImmediate(SDNode *N) {
ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
int NumOperands = SVOp->getValueType(0).getVectorNumElements();
unsigned Shift = (NumOperands == 4) ? 2 : 1;
unsigned Mask = 0;
for (int i = 0; i < NumOperands; ++i) {
int Val = SVOp->getMaskElt(NumOperands-i-1);
if (Val < 0) Val = 0;
if (Val >= NumOperands) Val -= NumOperands;
Mask |= Val;
return Mask;
}
/// getShufflePSHUFHWImmediate - Return the appropriate immediate to shuffle
/// the specified VECTOR_SHUFFLE mask with the PSHUFHW instruction.
unsigned X86::getShufflePSHUFHWImmediate(SDNode *N) {
ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
unsigned Mask = 0;
// 8 nodes, but we only care about the last 4.
for (unsigned i = 7; i >= 4; --i) {
int Val = SVOp->getMaskElt(i);
if (Val >= 0)
Mask |= (Val - 4);
if (i != 4)
Mask <<= 2;
}
return Mask;
}
/// getShufflePSHUFLWImmediate - Return the appropriate immediate to shuffle
/// the specified VECTOR_SHUFFLE mask with the PSHUFLW instruction.
unsigned X86::getShufflePSHUFLWImmediate(SDNode *N) {
ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
unsigned Mask = 0;
// 8 nodes, but we only care about the first 4.
for (int i = 3; i >= 0; --i) {
int Val = SVOp->getMaskElt(i);
if (Val >= 0)
Mask |= Val;
if (i != 0)
Mask <<= 2;
}
return Mask;
}
/// getShufflePALIGNRImmediate - Return the appropriate immediate to shuffle
/// the specified VECTOR_SHUFFLE mask with the PALIGNR instruction.
unsigned X86::getShufflePALIGNRImmediate(SDNode *N) {
ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
EVT VVT = N->getValueType(0);
unsigned EltSize = VVT.getVectorElementType().getSizeInBits() >> 3;
int Val = 0;
unsigned i, e;
for (i = 0, e = VVT.getVectorNumElements(); i != e; ++i) {
Val = SVOp->getMaskElt(i);
if (Val >= 0)
break;
}
Eli Friedman
committed
assert(Val - i > 0 && "PALIGNR imm should be positive");
return (Val - i) * EltSize;
}
/// getExtractVEXTRACTF128Immediate - Return the appropriate immediate
/// to extract the specified EXTRACT_SUBVECTOR index with VEXTRACTF128
/// instructions.
unsigned X86::getExtractVEXTRACTF128Immediate(SDNode *N) {
if (!isa<ConstantSDNode>(N->getOperand(1).getNode()))
llvm_unreachable("Illegal extract subvector for VEXTRACTF128");
uint64_t Index =
cast<ConstantSDNode>(N->getOperand(1).getNode())->getZExtValue();
EVT VecVT = N->getOperand(0).getValueType();
EVT ElVT = VecVT.getVectorElementType();
unsigned NumElemsPerChunk = 128 / ElVT.getSizeInBits();
return Index / NumElemsPerChunk;
}
/// getInsertVINSERTF128Immediate - Return the appropriate immediate
/// to insert at the specified INSERT_SUBVECTOR index with VINSERTF128
/// instructions.
unsigned X86::getInsertVINSERTF128Immediate(SDNode *N) {
if (!isa<ConstantSDNode>(N->getOperand(2).getNode()))
llvm_unreachable("Illegal insert subvector for VINSERTF128");
uint64_t Index =
cast<ConstantSDNode>(N->getOperand(2).getNode())->getZExtValue();
EVT VecVT = N->getValueType(0);
EVT ElVT = VecVT.getVectorElementType();
unsigned NumElemsPerChunk = 128 / ElVT.getSizeInBits();
return Index / NumElemsPerChunk;
}
Evan Cheng
committed
/// isZeroNode - Returns true if Elt is a constant zero or a floating point
/// constant +0.0.
bool X86::isZeroNode(SDValue Elt) {
return ((isa<ConstantSDNode>(Elt) &&
cast<ConstantSDNode>(Elt)->isNullValue()) ||
Evan Cheng
committed
(isa<ConstantFPSDNode>(Elt) &&
cast<ConstantFPSDNode>(Elt)->getValueAPF().isPosZero()));
}
/// CommuteVectorShuffle - Swap vector_shuffle operands as well as values in
/// their permute mask.
static SDValue CommuteVectorShuffle(ShuffleVectorSDNode *SVOp,
SelectionDAG &DAG) {
Owen Anderson
committed
EVT VT = SVOp->getValueType(0);
unsigned NumElems = VT.getVectorNumElements();
SmallVector<int, 8> MaskVec;
for (unsigned i = 0; i != NumElems; ++i) {
int idx = SVOp->getMaskElt(i);
if (idx < 0)
MaskVec.push_back(idx);
else if (idx < (int)NumElems)
MaskVec.push_back(idx + NumElems);
MaskVec.push_back(idx - NumElems);
return DAG.getVectorShuffle(VT, SVOp->getDebugLoc(), SVOp->getOperand(1),
SVOp->getOperand(0), &MaskVec[0]);
/// CommuteVectorShuffleMask - Change values in a shuffle permute mask assuming
/// the two vector operands have swapped position.
Owen Anderson
committed
static void CommuteVectorShuffleMask(SmallVectorImpl<int> &Mask, EVT VT) {
unsigned NumElems = VT.getVectorNumElements();
for (unsigned i = 0; i != NumElems; ++i) {
int idx = Mask[i];
if (idx < 0)
else if (idx < (int)NumElems)
Mask[i] = idx + NumElems;
Mask[i] = idx - NumElems;
/// ShouldXformToMOVHLPS - Return true if the node should be transformed to
/// match movhlps. The lower half elements should come from upper half of
/// V1 (and in order), and the upper half elements should come from the upper
/// half of V2 (and in order).
static bool ShouldXformToMOVHLPS(ShuffleVectorSDNode *Op) {
if (Op->getValueType(0).getVectorNumElements() != 4)
return false;
for (unsigned i = 0, e = 2; i != e; ++i)
if (!isUndefOrEqual(Op->getMaskElt(i), i+2))
return false;
for (unsigned i = 2; i != 4; ++i)
if (!isUndefOrEqual(Op->getMaskElt(i), i+4))
return false;
return true;
}
/// isScalarLoadToVector - Returns true if the node is a scalar load that
Evan Cheng
committed
/// is promoted to a vector. It also returns the LoadSDNode by reference if
/// required.
static bool isScalarLoadToVector(SDNode *N, LoadSDNode **LD = NULL) {
Evan Cheng
committed
if (N->getOpcode() != ISD::SCALAR_TO_VECTOR)
return false;
N = N->getOperand(0).getNode();
if (!ISD::isNON_EXTLoad(N))
return false;
if (LD)
*LD = cast<LoadSDNode>(N);
return true;
/// ShouldXformToMOVLP{S|D} - Return true if the node should be transformed to
/// match movlp{s|d}. The lower half elements should come from lower half of
/// V1 (and in order), and the upper half elements should come from the upper
/// half of V2 (and in order). And since V1 will become the source of the
/// MOVLP, it must be either a vector load or a scalar load to vector.
static bool ShouldXformToMOVLP(SDNode *V1, SDNode *V2,
ShuffleVectorSDNode *Op) {
if (!ISD::isNON_EXTLoad(V1) && !isScalarLoadToVector(V1))
return false;
// Is V2 is a vector load, don't do this transformation. We will try to use
// load folding shufps op.
if (ISD::isNON_EXTLoad(V2))
return false;
unsigned NumElems = Op->getValueType(0).getVectorNumElements();
if (NumElems != 2 && NumElems != 4)
return false;
for (unsigned i = 0, e = NumElems/2; i != e; ++i)
if (!isUndefOrEqual(Op->getMaskElt(i), i))
return false;
for (unsigned i = NumElems/2; i != NumElems; ++i)
if (!isUndefOrEqual(Op->getMaskElt(i), i+NumElems))
return false;
return true;
/// isSplatVector - Returns true if N is a BUILD_VECTOR node whose elements are
/// all the same.
static bool isSplatVector(SDNode *N) {
if (N->getOpcode() != ISD::BUILD_VECTOR)
return false;
for (unsigned i = 1, e = N->getNumOperands(); i != e; ++i)
if (N->getOperand(i) != SplatValue)
return false;
return true;
}
/// isZeroShuffle - Returns true if N is a VECTOR_SHUFFLE that can be resolved
/// FIXME: move to dag combiner / method on ShuffleVectorSDNode
static bool isZeroShuffle(ShuffleVectorSDNode *N) {
SDValue V1 = N->getOperand(0);
SDValue V2 = N->getOperand(1);
unsigned NumElems = N->getValueType(0).getVectorNumElements();
for (unsigned i = 0; i != NumElems; ++i) {
int Idx = N->getMaskElt(i);
if (Idx >= (int)NumElems) {
unsigned Opc = V2.getOpcode();
if (Opc == ISD::UNDEF || ISD::isBuildVectorAllZeros(V2.getNode()))
Evan Cheng
committed
if (Opc != ISD::BUILD_VECTOR ||
!X86::isZeroNode(V2.getOperand(Idx-NumElems)))
return false;
} else if (Idx >= 0) {
unsigned Opc = V1.getOpcode();
if (Opc == ISD::UNDEF || ISD::isBuildVectorAllZeros(V1.getNode()))
Evan Cheng
committed
if (Opc != ISD::BUILD_VECTOR ||
!X86::isZeroNode(V1.getOperand(Idx)))
return false;
}
}
return true;
}
/// getZeroVector - Returns a vector of specified type with all zero elements.
///
Owen Anderson
committed
static SDValue getZeroVector(EVT VT, bool HasSSE2, SelectionDAG &DAG,
assert(VT.isVector() && "Expected a vector type");
// Always build SSE zero vectors as <4 x i32> bitcasted
Bruno Cardoso Lopes
committed
// to their dest type. This ensures they get CSE'd.
Bruno Cardoso Lopes
committed
if (HasSSE2) { // SSE2
SDValue Cst = DAG.getTargetConstant(0, MVT::i32);
Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Cst, Cst, Cst, Cst);
} else { // SSE1
SDValue Cst = DAG.getTargetConstantFP(+0.0, MVT::f32);
Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4f32, Cst, Cst, Cst, Cst);
}
} else if (VT.getSizeInBits() == 256) { // AVX
// 256-bit logic and arithmetic instructions in AVX are
// all floating-point, no support for integer ops. Default
// to emitting fp zeroed vectors then.
Owen Anderson
committed
SDValue Cst = DAG.getTargetConstantFP(+0.0, MVT::f32);
Bruno Cardoso Lopes
committed
SDValue Ops[] = { Cst, Cst, Cst, Cst, Cst, Cst, Cst, Cst };
Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v8f32, Ops, 8);
Evan Cheng
committed
}
Wesley Peck
committed
return DAG.getNode(ISD::BITCAST, dl, VT, Vec);
}
/// getOnesVector - Returns a vector of specified type with all bits set.
/// Always build ones vectors as <4 x i32>. For 256-bit types, use two
/// <4 x i32> inserted in a <8 x i32> appropriately. Then bitcast to their
/// original type, ensuring they get CSE'd.
Owen Anderson
committed
static SDValue getOnesVector(EVT VT, SelectionDAG &DAG, DebugLoc dl) {
assert(VT.isVector() && "Expected a vector type");
assert((VT.is128BitVector() || VT.is256BitVector())
&& "Expected a 128-bit or 256-bit vector type");
Owen Anderson
committed
SDValue Cst = DAG.getTargetConstant(~0U, MVT::i32);
SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
Cst, Cst, Cst, Cst);
SDValue InsV = Insert128BitVector(DAG.getNode(ISD::UNDEF, dl, MVT::v8i32),
Vec, DAG.getConstant(0, MVT::i32), DAG, dl);
Vec = Insert128BitVector(InsV, Vec,
DAG.getConstant(4 /* NumElems/2 */, MVT::i32), DAG, dl);
}
Wesley Peck
committed
return DAG.getNode(ISD::BITCAST, dl, VT, Vec);
}
/// NormalizeMask - V2 is a splat, modify the mask (if needed) so all elements
/// that point to V2 points to its first element.
static SDValue NormalizeMask(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) {
Owen Anderson
committed
EVT VT = SVOp->getValueType(0);
unsigned NumElems = VT.getVectorNumElements();
bool Changed = false;
SmallVector<int, 8> MaskVec;
SVOp->getMask(MaskVec);
for (unsigned i = 0; i != NumElems; ++i) {
if (MaskVec[i] > (int)NumElems) {
MaskVec[i] = NumElems;
Changed = true;
}
}
if (Changed)
return DAG.getVectorShuffle(VT, SVOp->getDebugLoc(), SVOp->getOperand(0),
SVOp->getOperand(1), &MaskVec[0]);
return SDValue(SVOp, 0);
}
/// getMOVLMask - Returns a vector_shuffle mask for an movs{s|d}, movd
/// operation of specified width.
Owen Anderson
committed
static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1,
SDValue V2) {
unsigned NumElems = VT.getVectorNumElements();
SmallVector<int, 8> Mask;
Mask.push_back(NumElems);
for (unsigned i = 1; i != NumElems; ++i)
Mask.push_back(i);
return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]);
}
/// getUnpackl - Returns a vector_shuffle node for an unpackl operation.
Owen Anderson
committed
static SDValue getUnpackl(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1,
SDValue V2) {
unsigned NumElems = VT.getVectorNumElements();
SmallVector<int, 8> Mask;
for (unsigned i = 0, e = NumElems/2; i != e; ++i) {
Mask.push_back(i);
Mask.push_back(i + NumElems);
return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]);
/// getUnpackh - Returns a vector_shuffle node for an unpackh operation.
Owen Anderson
committed
static SDValue getUnpackh(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1,
SDValue V2) {
unsigned NumElems = VT.getVectorNumElements();
unsigned Half = NumElems/2;
SmallVector<int, 8> Mask;
for (unsigned i = 0; i != Half; ++i) {
Mask.push_back(i + Half);
Mask.push_back(i + NumElems + Half);
}
return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]);
// PromoteSplatv8v16 - All i16 and i8 vector types can't be used directly by
// a generic shuffle instruction because the target has no such instructions.
// Generate shuffles which repeat i16 and i8 several times until they can be
// represented by v4f32 and then be manipulated by target suported shuffles.
static SDValue PromoteSplatv8v16(SDValue V, SelectionDAG &DAG, int &EltNo) {
EVT VT = V.getValueType();
int NumElems = VT.getVectorNumElements();
DebugLoc dl = V.getDebugLoc();
while (NumElems > 4) {
if (EltNo < NumElems/2) {
V = getUnpackl(DAG, dl, VT, V, V);
} else {
V = getUnpackh(DAG, dl, VT, V, V);
EltNo -= NumElems/2;
Evan Cheng
committed
}
NumElems >>= 1;
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
return V;
}
/// getLegalSplat - Generate a legal splat with supported x86 shuffles
static SDValue getLegalSplat(SelectionDAG &DAG, SDValue V, int EltNo) {
EVT VT = V.getValueType();
DebugLoc dl = V.getDebugLoc();
assert((VT.getSizeInBits() == 128 || VT.getSizeInBits() == 256)
&& "Vector size not supported");
bool Is128 = VT.getSizeInBits() == 128;
EVT NVT = Is128 ? MVT::v4f32 : MVT::v8f32;
V = DAG.getNode(ISD::BITCAST, dl, NVT, V);
if (Is128) {
int SplatMask[4] = { EltNo, EltNo, EltNo, EltNo };
V = DAG.getVectorShuffle(NVT, dl, V, DAG.getUNDEF(NVT), &SplatMask[0]);
} else {
// The second half of indicies refer to the higher part, which is a
// duplication of the lower one. This makes this shuffle a perfect match
// for the VPERM instruction.
int SplatMask[8] = { EltNo, EltNo, EltNo, EltNo,
EltNo+4, EltNo+4, EltNo+4, EltNo+4 };
V = DAG.getVectorShuffle(NVT, dl, V, DAG.getUNDEF(NVT), &SplatMask[0]);
}
return DAG.getNode(ISD::BITCAST, dl, VT, V);
}
Bruno Cardoso Lopes
committed
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
/// PromoteVectorToScalarSplat - Since there's no native support for
/// scalar_to_vector for 256-bit AVX, a 128-bit scalar_to_vector +
/// INSERT_SUBVECTOR is generated. Recognize this idiom and do the
/// shuffle before the insertion, this yields less instructions in the end.
static SDValue PromoteVectorToScalarSplat(ShuffleVectorSDNode *SV,
SelectionDAG &DAG) {
EVT SrcVT = SV->getValueType(0);
SDValue V1 = SV->getOperand(0);
DebugLoc dl = SV->getDebugLoc();
int NumElems = SrcVT.getVectorNumElements();
assert(SrcVT.is256BitVector() && "unknown howto handle vector type");
SmallVector<int, 4> Mask;
for (int i = 0; i < NumElems/2; ++i)
Mask.push_back(SV->getMaskElt(i));
EVT SVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getVectorElementType(),
NumElems/2);
SDValue SV1 = DAG.getVectorShuffle(SVT, dl, V1.getOperand(1),
DAG.getUNDEF(SVT), &Mask[0]);
SDValue InsV = Insert128BitVector(DAG.getUNDEF(SrcVT), SV1,
DAG.getConstant(0, MVT::i32), DAG, dl);
return Insert128BitVector(InsV, SV1,
DAG.getConstant(NumElems/2, MVT::i32), DAG, dl);
}
/// PromoteSplat - Promote a splat of v4i32, v8i16 or v16i8 to v4f32 and
/// v8i32, v16i16 or v32i8 to v8f32.
static SDValue PromoteSplat(ShuffleVectorSDNode *SV, SelectionDAG &DAG) {
EVT SrcVT = SV->getValueType(0);