mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
[mips] Correct and improve special-case shuffle instructions.
Summary: The documentation writes vectors highest-index first whereas LLVM-IR writes them lowest-index first. As a result, instructions defined in terms of left_half() and right_half() had the halves reversed. In addition to correcting them, they have been improved to allow shuffles that use the same operand twice or in reverse order. For example, ilvev used to accept masks of the form: <0, n, 2, n+2, 4, n+4, ...> but now accepts: <0, 0, 2, 2, 4, 4, ...> <n, n, n+2, n+2, n+4, n+4, ...> <0, n, 2, n+2, 4, n+4, ...> <n, 0, n+2, 2, n+4, 4, ...> One further improvement is that splati.[bhwd] is now the preferred instruction for splat-like operations. The other special shuffles are no longer used for splats. This lead to the discovery that <0, 0, ...> would not cause splati.[hwd] to be selected and this has also been fixed. This fixes the enc-3des test from the test-suite on Mips64r6 with MSA. Reviewers: vkalintiris Reviewed By: vkalintiris Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D9660 llvm-svn: 237689
This commit is contained in:
parent
93fae60e1e
commit
b7e612b638
@ -113,7 +113,8 @@ bool MipsDAGToDAGISel::selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm) const {
|
||||
bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm,
|
||||
unsigned MinSizeInBits) const {
|
||||
llvm_unreachable("Unimplemented function.");
|
||||
return false;
|
||||
}
|
||||
|
@ -84,7 +84,8 @@ private:
|
||||
SDValue &Offset, SDValue &Alias);
|
||||
|
||||
/// \brief Select constant vector splats.
|
||||
virtual bool selectVSplat(SDNode *N, APInt &Imm) const;
|
||||
virtual bool selectVSplat(SDNode *N, APInt &Imm,
|
||||
unsigned MinSizeInBits) const;
|
||||
/// \brief Select constant vector splats whose value fits in a uimm1.
|
||||
virtual bool selectVSplatUimm1(SDValue N, SDValue &Imm) const;
|
||||
/// \brief Select constant vector splats whose value fits in a uimm2.
|
||||
|
@ -375,7 +375,7 @@ def vsplat_imm_eq_1 : PatLeaf<(build_vector), [{
|
||||
APInt Imm;
|
||||
EVT EltTy = N->getValueType(0).getVectorElementType();
|
||||
|
||||
return selectVSplat (N, Imm) &&
|
||||
return selectVSplat(N, Imm, EltTy.getSizeInBits()) &&
|
||||
Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1;
|
||||
}]>;
|
||||
|
||||
@ -384,7 +384,7 @@ def vsplati64_imm_eq_1 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{
|
||||
SDNode *BV = N->getOperand(0).getNode();
|
||||
EVT EltTy = N->getValueType(0).getVectorElementType();
|
||||
|
||||
return selectVSplat (BV, Imm) &&
|
||||
return selectVSplat(BV, Imm, EltTy.getSizeInBits()) &&
|
||||
Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1;
|
||||
}]>;
|
||||
|
||||
|
@ -473,7 +473,8 @@ bool MipsSEDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base,
|
||||
// Returns true and sets Imm if:
|
||||
// * MSA is enabled
|
||||
// * N is a ISD::BUILD_VECTOR representing a constant splat
|
||||
bool MipsSEDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm) const {
|
||||
bool MipsSEDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm,
|
||||
unsigned MinSizeInBits) const {
|
||||
if (!Subtarget->hasMSA())
|
||||
return false;
|
||||
|
||||
@ -486,9 +487,8 @@ bool MipsSEDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm) const {
|
||||
unsigned SplatBitSize;
|
||||
bool HasAnyUndefs;
|
||||
|
||||
if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
|
||||
HasAnyUndefs, 8,
|
||||
!Subtarget->isLittle()))
|
||||
if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
|
||||
MinSizeInBits, !Subtarget->isLittle()))
|
||||
return false;
|
||||
|
||||
Imm = SplatValue;
|
||||
@ -521,8 +521,9 @@ selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed,
|
||||
if (N->getOpcode() == ISD::BITCAST)
|
||||
N = N->getOperand(0);
|
||||
|
||||
if (selectVSplat (N.getNode(), ImmValue) &&
|
||||
if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
|
||||
ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
|
||||
|
||||
if (( Signed && ImmValue.isSignedIntN(ImmBitSize)) ||
|
||||
(!Signed && ImmValue.isIntN(ImmBitSize))) {
|
||||
Imm = CurDAG->getTargetConstant(ImmValue, SDLoc(N), EltTy);
|
||||
@ -596,7 +597,7 @@ bool MipsSEDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const {
|
||||
if (N->getOpcode() == ISD::BITCAST)
|
||||
N = N->getOperand(0);
|
||||
|
||||
if (selectVSplat (N.getNode(), ImmValue) &&
|
||||
if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
|
||||
ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
|
||||
int32_t Log2 = ImmValue.exactLogBase2();
|
||||
|
||||
@ -627,7 +628,7 @@ bool MipsSEDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const {
|
||||
if (N->getOpcode() == ISD::BITCAST)
|
||||
N = N->getOperand(0);
|
||||
|
||||
if (selectVSplat(N.getNode(), ImmValue) &&
|
||||
if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
|
||||
ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
|
||||
// Extract the run of set bits starting with bit zero from the bitwise
|
||||
// inverse of ImmValue, and test that the inverse of this is the same
|
||||
@ -661,7 +662,7 @@ bool MipsSEDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const {
|
||||
if (N->getOpcode() == ISD::BITCAST)
|
||||
N = N->getOperand(0);
|
||||
|
||||
if (selectVSplat(N.getNode(), ImmValue) &&
|
||||
if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
|
||||
ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
|
||||
// Extract the run of set bits starting with bit zero, and test that the
|
||||
// result is the same as the original value
|
||||
@ -683,7 +684,7 @@ bool MipsSEDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N,
|
||||
if (N->getOpcode() == ISD::BITCAST)
|
||||
N = N->getOperand(0);
|
||||
|
||||
if (selectVSplat(N.getNode(), ImmValue) &&
|
||||
if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
|
||||
ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
|
||||
int32_t Log2 = (~ImmValue).exactLogBase2();
|
||||
|
||||
|
@ -78,7 +78,8 @@ private:
|
||||
SDValue &Offset) const override;
|
||||
|
||||
/// \brief Select constant vector splats.
|
||||
bool selectVSplat(SDNode *N, APInt &Imm) const override;
|
||||
bool selectVSplat(SDNode *N, APInt &Imm,
|
||||
unsigned MinSizeInBits) const override;
|
||||
/// \brief Select constant vector splats whose value fits in a given integer.
|
||||
bool selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed,
|
||||
unsigned ImmBitSize) const;
|
||||
|
@ -2410,7 +2410,7 @@ SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op,
|
||||
// It is therefore possible to lower into SHF when the mask takes the form:
|
||||
// <a, b, c, d, a+4, b+4, c+4, d+4, a+8, b+8, c+8, d+8, ...>
|
||||
// When undef's appear they are treated as if they were whatever value is
|
||||
// necessary in order to fit the above form.
|
||||
// necessary in order to fit the above forms.
|
||||
//
|
||||
// For example:
|
||||
// %2 = shufflevector <8 x i16> %0, <8 x i16> undef,
|
||||
@ -2469,177 +2469,326 @@ static SDValue lowerVECTOR_SHUFFLE_SHF(SDValue Op, EVT ResTy,
|
||||
DAG.getConstant(Imm, DL, MVT::i32), Op->getOperand(0));
|
||||
}
|
||||
|
||||
/// Determine whether a range fits a regular pattern of values.
|
||||
/// This function accounts for the possibility of jumping over the End iterator.
|
||||
template <typename ValType>
|
||||
static bool
|
||||
fitsRegularPattern(typename SmallVectorImpl<ValType>::const_iterator Begin,
|
||||
unsigned CheckStride,
|
||||
typename SmallVectorImpl<ValType>::const_iterator End,
|
||||
ValType ExpectedIndex, unsigned ExpectedIndexStride) {
|
||||
auto &I = Begin;
|
||||
|
||||
while (I != End) {
|
||||
if (*I != -1 && *I != ExpectedIndex)
|
||||
return false;
|
||||
ExpectedIndex += ExpectedIndexStride;
|
||||
|
||||
// Incrementing past End is undefined behaviour so we must increment one
|
||||
// step at a time and check for End at each step.
|
||||
for (unsigned n = 0; n < CheckStride && I != End; ++n, ++I)
|
||||
; // Empty loop body.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Determine whether VECTOR_SHUFFLE is a SPLATI.
|
||||
//
|
||||
// It is a SPLATI when the mask is:
|
||||
// <x, x, x, ...>
|
||||
// where x is any valid index.
|
||||
//
|
||||
// When undef's appear in the mask they are treated as if they were whatever
|
||||
// value is necessary in order to fit the above form.
|
||||
static bool isVECTOR_SHUFFLE_SPLATI(SDValue Op, EVT ResTy,
|
||||
SmallVector<int, 16> Indices,
|
||||
SelectionDAG &DAG) {
|
||||
assert((Indices.size() % 2) == 0);
|
||||
|
||||
int SplatIndex = -1;
|
||||
for (const auto &V : Indices) {
|
||||
if (V != -1) {
|
||||
SplatIndex = V;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fitsRegularPattern<int>(Indices.begin(), 1, Indices.end(), SplatIndex,
|
||||
0);
|
||||
}
|
||||
|
||||
// Lower VECTOR_SHUFFLE into ILVEV (if possible).
|
||||
//
|
||||
// ILVEV interleaves the even elements from each vector.
|
||||
//
|
||||
// It is possible to lower into ILVEV when the mask takes the form:
|
||||
// <0, n, 2, n+2, 4, n+4, ...>
|
||||
// It is possible to lower into ILVEV when the mask consists of two of the
|
||||
// following forms interleaved:
|
||||
// <0, 2, 4, ...>
|
||||
// <n, n+2, n+4, ...>
|
||||
// where n is the number of elements in the vector.
|
||||
// For example:
|
||||
// <0, 0, 2, 2, 4, 4, ...>
|
||||
// <0, n, 2, n+2, 4, n+4, ...>
|
||||
//
|
||||
// When undef's appear in the mask they are treated as if they were whatever
|
||||
// value is necessary in order to fit the above form.
|
||||
// value is necessary in order to fit the above forms.
|
||||
static SDValue lowerVECTOR_SHUFFLE_ILVEV(SDValue Op, EVT ResTy,
|
||||
SmallVector<int, 16> Indices,
|
||||
SelectionDAG &DAG) {
|
||||
assert ((Indices.size() % 2) == 0);
|
||||
int WsIdx = 0;
|
||||
int WtIdx = ResTy.getVectorNumElements();
|
||||
assert((Indices.size() % 2) == 0);
|
||||
|
||||
for (unsigned i = 0; i < Indices.size(); i += 2) {
|
||||
if (Indices[i] != -1 && Indices[i] != WsIdx)
|
||||
return SDValue();
|
||||
if (Indices[i+1] != -1 && Indices[i+1] != WtIdx)
|
||||
return SDValue();
|
||||
WsIdx += 2;
|
||||
WtIdx += 2;
|
||||
}
|
||||
SDValue Wt;
|
||||
SDValue Ws;
|
||||
const auto &Begin = Indices.begin();
|
||||
const auto &End = Indices.end();
|
||||
|
||||
return DAG.getNode(MipsISD::ILVEV, SDLoc(Op), ResTy, Op->getOperand(0),
|
||||
Op->getOperand(1));
|
||||
// Check even elements are taken from the even elements of one half or the
|
||||
// other and pick an operand accordingly.
|
||||
if (fitsRegularPattern<int>(Begin, 2, End, 0, 2))
|
||||
Wt = Op->getOperand(0);
|
||||
else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size(), 2))
|
||||
Wt = Op->getOperand(1);
|
||||
else
|
||||
return SDValue();
|
||||
|
||||
// Check odd elements are taken from the even elements of one half or the
|
||||
// other and pick an operand accordingly.
|
||||
if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 2))
|
||||
Ws = Op->getOperand(0);
|
||||
else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size(), 2))
|
||||
Ws = Op->getOperand(1);
|
||||
else
|
||||
return SDValue();
|
||||
|
||||
return DAG.getNode(MipsISD::ILVEV, SDLoc(Op), ResTy, Ws, Wt);
|
||||
}
|
||||
|
||||
// Lower VECTOR_SHUFFLE into ILVOD (if possible).
|
||||
//
|
||||
// ILVOD interleaves the odd elements from each vector.
|
||||
//
|
||||
// It is possible to lower into ILVOD when the mask takes the form:
|
||||
// <1, n+1, 3, n+3, 5, n+5, ...>
|
||||
// It is possible to lower into ILVOD when the mask consists of two of the
|
||||
// following forms interleaved:
|
||||
// <1, 3, 5, ...>
|
||||
// <n+1, n+3, n+5, ...>
|
||||
// where n is the number of elements in the vector.
|
||||
// For example:
|
||||
// <1, 1, 3, 3, 5, 5, ...>
|
||||
// <1, n+1, 3, n+3, 5, n+5, ...>
|
||||
//
|
||||
// When undef's appear in the mask they are treated as if they were whatever
|
||||
// value is necessary in order to fit the above form.
|
||||
// value is necessary in order to fit the above forms.
|
||||
static SDValue lowerVECTOR_SHUFFLE_ILVOD(SDValue Op, EVT ResTy,
|
||||
SmallVector<int, 16> Indices,
|
||||
SelectionDAG &DAG) {
|
||||
assert ((Indices.size() % 2) == 0);
|
||||
int WsIdx = 1;
|
||||
int WtIdx = ResTy.getVectorNumElements() + 1;
|
||||
assert((Indices.size() % 2) == 0);
|
||||
|
||||
for (unsigned i = 0; i < Indices.size(); i += 2) {
|
||||
if (Indices[i] != -1 && Indices[i] != WsIdx)
|
||||
SDValue Wt;
|
||||
SDValue Ws;
|
||||
const auto &Begin = Indices.begin();
|
||||
const auto &End = Indices.end();
|
||||
|
||||
// Check even elements are taken from the odd elements of one half or the
|
||||
// other and pick an operand accordingly.
|
||||
if (fitsRegularPattern<int>(Begin, 2, End, 1, 2))
|
||||
Wt = Op->getOperand(0);
|
||||
else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size() + 1, 2))
|
||||
Wt = Op->getOperand(1);
|
||||
else
|
||||
return SDValue();
|
||||
if (Indices[i+1] != -1 && Indices[i+1] != WtIdx)
|
||||
|
||||
// Check odd elements are taken from the odd elements of one half or the
|
||||
// other and pick an operand accordingly.
|
||||
if (fitsRegularPattern<int>(Begin + 1, 2, End, 1, 2))
|
||||
Ws = Op->getOperand(0);
|
||||
else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size() + 1, 2))
|
||||
Ws = Op->getOperand(1);
|
||||
else
|
||||
return SDValue();
|
||||
WsIdx += 2;
|
||||
WtIdx += 2;
|
||||
}
|
||||
|
||||
return DAG.getNode(MipsISD::ILVOD, SDLoc(Op), ResTy, Op->getOperand(0),
|
||||
Op->getOperand(1));
|
||||
}
|
||||
|
||||
// Lower VECTOR_SHUFFLE into ILVL (if possible).
|
||||
//
|
||||
// ILVL interleaves consecutive elements from the left half of each vector.
|
||||
//
|
||||
// It is possible to lower into ILVL when the mask takes the form:
|
||||
// <0, n, 1, n+1, 2, n+2, ...>
|
||||
// where n is the number of elements in the vector.
|
||||
//
|
||||
// When undef's appear in the mask they are treated as if they were whatever
|
||||
// value is necessary in order to fit the above form.
|
||||
static SDValue lowerVECTOR_SHUFFLE_ILVL(SDValue Op, EVT ResTy,
|
||||
SmallVector<int, 16> Indices,
|
||||
SelectionDAG &DAG) {
|
||||
assert ((Indices.size() % 2) == 0);
|
||||
int WsIdx = 0;
|
||||
int WtIdx = ResTy.getVectorNumElements();
|
||||
|
||||
for (unsigned i = 0; i < Indices.size(); i += 2) {
|
||||
if (Indices[i] != -1 && Indices[i] != WsIdx)
|
||||
return SDValue();
|
||||
if (Indices[i+1] != -1 && Indices[i+1] != WtIdx)
|
||||
return SDValue();
|
||||
WsIdx ++;
|
||||
WtIdx ++;
|
||||
}
|
||||
|
||||
return DAG.getNode(MipsISD::ILVL, SDLoc(Op), ResTy, Op->getOperand(0),
|
||||
Op->getOperand(1));
|
||||
return DAG.getNode(MipsISD::ILVOD, SDLoc(Op), ResTy, Wt, Ws);
|
||||
}
|
||||
|
||||
// Lower VECTOR_SHUFFLE into ILVR (if possible).
|
||||
//
|
||||
// ILVR interleaves consecutive elements from the right half of each vector.
|
||||
// ILVR interleaves consecutive elements from the right (lowest-indexed) half of
|
||||
// each vector.
|
||||
//
|
||||
// It is possible to lower into ILVR when the mask takes the form:
|
||||
// <x, n+x, x+1, n+x+1, x+2, n+x+2, ...>
|
||||
// where n is the number of elements in the vector and x is half n.
|
||||
// It is possible to lower into ILVR when the mask consists of two of the
|
||||
// following forms interleaved:
|
||||
// <0, 1, 2, ...>
|
||||
// <n, n+1, n+2, ...>
|
||||
// where n is the number of elements in the vector.
|
||||
// For example:
|
||||
// <0, 0, 1, 1, 2, 2, ...>
|
||||
// <0, n, 1, n+1, 2, n+2, ...>
|
||||
//
|
||||
// When undef's appear in the mask they are treated as if they were whatever
|
||||
// value is necessary in order to fit the above form.
|
||||
// value is necessary in order to fit the above forms.
|
||||
static SDValue lowerVECTOR_SHUFFLE_ILVR(SDValue Op, EVT ResTy,
|
||||
SmallVector<int, 16> Indices,
|
||||
SelectionDAG &DAG) {
|
||||
assert ((Indices.size() % 2) == 0);
|
||||
unsigned NumElts = ResTy.getVectorNumElements();
|
||||
int WsIdx = NumElts / 2;
|
||||
int WtIdx = NumElts + NumElts / 2;
|
||||
assert((Indices.size() % 2) == 0);
|
||||
|
||||
for (unsigned i = 0; i < Indices.size(); i += 2) {
|
||||
if (Indices[i] != -1 && Indices[i] != WsIdx)
|
||||
return SDValue();
|
||||
if (Indices[i+1] != -1 && Indices[i+1] != WtIdx)
|
||||
return SDValue();
|
||||
WsIdx ++;
|
||||
WtIdx ++;
|
||||
}
|
||||
SDValue Wt;
|
||||
SDValue Ws;
|
||||
const auto &Begin = Indices.begin();
|
||||
const auto &End = Indices.end();
|
||||
|
||||
return DAG.getNode(MipsISD::ILVR, SDLoc(Op), ResTy, Op->getOperand(0),
|
||||
Op->getOperand(1));
|
||||
// Check even elements are taken from the right (lowest-indexed) elements of
|
||||
// one half or the other and pick an operand accordingly.
|
||||
if (fitsRegularPattern<int>(Begin, 2, End, 0, 1))
|
||||
Wt = Op->getOperand(0);
|
||||
else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size(), 1))
|
||||
Wt = Op->getOperand(1);
|
||||
else
|
||||
return SDValue();
|
||||
|
||||
// Check odd elements are taken from the right (lowest-indexed) elements of
|
||||
// one half or the other and pick an operand accordingly.
|
||||
if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 1))
|
||||
Ws = Op->getOperand(0);
|
||||
else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size(), 1))
|
||||
Ws = Op->getOperand(1);
|
||||
else
|
||||
return SDValue();
|
||||
|
||||
return DAG.getNode(MipsISD::ILVR, SDLoc(Op), ResTy, Ws, Wt);
|
||||
}
|
||||
|
||||
// Lower VECTOR_SHUFFLE into ILVL (if possible).
|
||||
//
|
||||
// ILVL interleaves consecutive elements from the left (highest-indexed) half
|
||||
// of each vector.
|
||||
//
|
||||
// It is possible to lower into ILVL when the mask consists of two of the
|
||||
// following forms interleaved:
|
||||
// <x, x+1, x+2, ...>
|
||||
// <n+x, n+x+1, n+x+2, ...>
|
||||
// where n is the number of elements in the vector and x is half n.
|
||||
// For example:
|
||||
// <x, x, x+1, x+1, x+2, x+2, ...>
|
||||
// <x, n+x, x+1, n+x+1, x+2, n+x+2, ...>
|
||||
//
|
||||
// When undef's appear in the mask they are treated as if they were whatever
|
||||
// value is necessary in order to fit the above forms.
|
||||
static SDValue lowerVECTOR_SHUFFLE_ILVL(SDValue Op, EVT ResTy,
|
||||
SmallVector<int, 16> Indices,
|
||||
SelectionDAG &DAG) {
|
||||
assert((Indices.size() % 2) == 0);
|
||||
|
||||
unsigned HalfSize = Indices.size() / 2;
|
||||
SDValue Wt;
|
||||
SDValue Ws;
|
||||
const auto &Begin = Indices.begin();
|
||||
const auto &End = Indices.end();
|
||||
|
||||
// Check even elements are taken from the left (highest-indexed) elements of
|
||||
// one half or the other and pick an operand accordingly.
|
||||
if (fitsRegularPattern<int>(Begin, 2, End, HalfSize, 1))
|
||||
Wt = Op->getOperand(0);
|
||||
else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size() + HalfSize, 1))
|
||||
Wt = Op->getOperand(1);
|
||||
else
|
||||
return SDValue();
|
||||
|
||||
// Check odd elements are taken from the left (highest-indexed) elements of
|
||||
// one half or the other and pick an operand accordingly.
|
||||
if (fitsRegularPattern<int>(Begin + 1, 2, End, HalfSize, 1))
|
||||
Ws = Op->getOperand(0);
|
||||
else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size() + HalfSize,
|
||||
1))
|
||||
Ws = Op->getOperand(1);
|
||||
else
|
||||
return SDValue();
|
||||
|
||||
return DAG.getNode(MipsISD::ILVL, SDLoc(Op), ResTy, Ws, Wt);
|
||||
}
|
||||
|
||||
// Lower VECTOR_SHUFFLE into PCKEV (if possible).
|
||||
//
|
||||
// PCKEV copies the even elements of each vector into the result vector.
|
||||
//
|
||||
// It is possible to lower into PCKEV when the mask takes the form:
|
||||
// <0, 2, 4, ..., n, n+2, n+4, ...>
|
||||
// It is possible to lower into PCKEV when the mask consists of two of the
|
||||
// following forms concatenated:
|
||||
// <0, 2, 4, ...>
|
||||
// <n, n+2, n+4, ...>
|
||||
// where n is the number of elements in the vector.
|
||||
// For example:
|
||||
// <0, 2, 4, ..., 0, 2, 4, ...>
|
||||
// <0, 2, 4, ..., n, n+2, n+4, ...>
|
||||
//
|
||||
// When undef's appear in the mask they are treated as if they were whatever
|
||||
// value is necessary in order to fit the above form.
|
||||
// value is necessary in order to fit the above forms.
|
||||
static SDValue lowerVECTOR_SHUFFLE_PCKEV(SDValue Op, EVT ResTy,
|
||||
SmallVector<int, 16> Indices,
|
||||
SelectionDAG &DAG) {
|
||||
assert ((Indices.size() % 2) == 0);
|
||||
int Idx = 0;
|
||||
assert((Indices.size() % 2) == 0);
|
||||
|
||||
for (unsigned i = 0; i < Indices.size(); ++i) {
|
||||
if (Indices[i] != -1 && Indices[i] != Idx)
|
||||
SDValue Wt;
|
||||
SDValue Ws;
|
||||
const auto &Begin = Indices.begin();
|
||||
const auto &Mid = Indices.begin() + Indices.size() / 2;
|
||||
const auto &End = Indices.end();
|
||||
|
||||
if (fitsRegularPattern<int>(Begin, 1, Mid, 0, 2))
|
||||
Wt = Op->getOperand(0);
|
||||
else if (fitsRegularPattern<int>(Begin, 1, Mid, Indices.size(), 2))
|
||||
Wt = Op->getOperand(1);
|
||||
else
|
||||
return SDValue();
|
||||
Idx += 2;
|
||||
}
|
||||
|
||||
return DAG.getNode(MipsISD::PCKEV, SDLoc(Op), ResTy, Op->getOperand(0),
|
||||
Op->getOperand(1));
|
||||
if (fitsRegularPattern<int>(Mid, 1, End, 0, 2))
|
||||
Ws = Op->getOperand(0);
|
||||
else if (fitsRegularPattern<int>(Mid, 1, End, Indices.size(), 2))
|
||||
Ws = Op->getOperand(1);
|
||||
else
|
||||
return SDValue();
|
||||
|
||||
return DAG.getNode(MipsISD::PCKEV, SDLoc(Op), ResTy, Ws, Wt);
|
||||
}
|
||||
|
||||
// Lower VECTOR_SHUFFLE into PCKOD (if possible).
|
||||
//
|
||||
// PCKOD copies the odd elements of each vector into the result vector.
|
||||
//
|
||||
// It is possible to lower into PCKOD when the mask takes the form:
|
||||
// <1, 3, 5, ..., n+1, n+3, n+5, ...>
|
||||
// It is possible to lower into PCKOD when the mask consists of two of the
|
||||
// following forms concatenated:
|
||||
// <1, 3, 5, ...>
|
||||
// <n+1, n+3, n+5, ...>
|
||||
// where n is the number of elements in the vector.
|
||||
// For example:
|
||||
// <1, 3, 5, ..., 1, 3, 5, ...>
|
||||
// <1, 3, 5, ..., n+1, n+3, n+5, ...>
|
||||
//
|
||||
// When undef's appear in the mask they are treated as if they were whatever
|
||||
// value is necessary in order to fit the above form.
|
||||
// value is necessary in order to fit the above forms.
|
||||
static SDValue lowerVECTOR_SHUFFLE_PCKOD(SDValue Op, EVT ResTy,
|
||||
SmallVector<int, 16> Indices,
|
||||
SelectionDAG &DAG) {
|
||||
assert ((Indices.size() % 2) == 0);
|
||||
int Idx = 1;
|
||||
assert((Indices.size() % 2) == 0);
|
||||
|
||||
for (unsigned i = 0; i < Indices.size(); ++i) {
|
||||
if (Indices[i] != -1 && Indices[i] != Idx)
|
||||
SDValue Wt;
|
||||
SDValue Ws;
|
||||
const auto &Begin = Indices.begin();
|
||||
const auto &Mid = Indices.begin() + Indices.size() / 2;
|
||||
const auto &End = Indices.end();
|
||||
|
||||
if (fitsRegularPattern<int>(Begin, 1, Mid, 1, 2))
|
||||
Wt = Op->getOperand(0);
|
||||
else if (fitsRegularPattern<int>(Begin, 1, Mid, Indices.size() + 1, 2))
|
||||
Wt = Op->getOperand(1);
|
||||
else
|
||||
return SDValue();
|
||||
Idx += 2;
|
||||
}
|
||||
|
||||
return DAG.getNode(MipsISD::PCKOD, SDLoc(Op), ResTy, Op->getOperand(0),
|
||||
Op->getOperand(1));
|
||||
if (fitsRegularPattern<int>(Mid, 1, End, 1, 2))
|
||||
Ws = Op->getOperand(0);
|
||||
else if (fitsRegularPattern<int>(Mid, 1, End, Indices.size() + 1, 2))
|
||||
Ws = Op->getOperand(1);
|
||||
else
|
||||
return SDValue();
|
||||
|
||||
return DAG.getNode(MipsISD::PCKOD, SDLoc(Op), ResTy, Ws, Wt);
|
||||
}
|
||||
|
||||
// Lower VECTOR_SHUFFLE into VSHF.
|
||||
@ -2715,10 +2864,11 @@ SDValue MipsSETargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
|
||||
for (int i = 0; i < ResTyNumElts; ++i)
|
||||
Indices.push_back(Node->getMaskElt(i));
|
||||
|
||||
SDValue Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG);
|
||||
if (Result.getNode())
|
||||
return Result;
|
||||
Result = lowerVECTOR_SHUFFLE_ILVEV(Op, ResTy, Indices, DAG);
|
||||
// splati.[bhwd] is preferable to the others but is matched from
|
||||
// MipsISD::VSHF.
|
||||
if (isVECTOR_SHUFFLE_SPLATI(Op, ResTy, Indices, DAG))
|
||||
return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG);
|
||||
SDValue Result = lowerVECTOR_SHUFFLE_ILVEV(Op, ResTy, Indices, DAG);
|
||||
if (Result.getNode())
|
||||
return Result;
|
||||
Result = lowerVECTOR_SHUFFLE_ILVOD(Op, ResTy, Indices, DAG);
|
||||
@ -2734,6 +2884,9 @@ SDValue MipsSETargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
|
||||
if (Result.getNode())
|
||||
return Result;
|
||||
Result = lowerVECTOR_SHUFFLE_PCKOD(Op, ResTy, Indices, DAG);
|
||||
if (Result.getNode())
|
||||
return Result;
|
||||
Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG);
|
||||
if (Result.getNode())
|
||||
return Result;
|
||||
return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG);
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user