summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBob Wilson <bob.wilson@apple.com>2009-08-21 20:54:19 +0000
committerBob Wilson <bob.wilson@apple.com>2009-08-21 20:54:19 +0000
commitc692cb77aaa8b16bcc7fe0c70d47adce94c43911 (patch)
treecc601451c796ca2a04612dad4fc42408a0b578a7 /lib
parent162da3c7b4764e7f685e3ef51798879b31e881c6 (diff)
downloadllvm-c692cb77aaa8b16bcc7fe0c70d47adce94c43911.tar.gz
llvm-c692cb77aaa8b16bcc7fe0c70d47adce94c43911.tar.bz2
llvm-c692cb77aaa8b16bcc7fe0c70d47adce94c43911.tar.xz
Match VTRN, VZIP, and VUZP shuffles. Restore the tests for these operations,
now using shuffles instead of intrinsics. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79673 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp78
-rw-r--r--lib/Target/ARM/ARMISelLowering.h5
2 files changed, 74 insertions, 9 deletions
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index 1c59cb01fa..f04b45dc79 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -2403,6 +2403,53 @@ static bool isVREVMask(const SmallVectorImpl<int> &M, EVT VT,
return true;
}
+static bool isVTRNMask(const SmallVectorImpl<int> &M, EVT VT,
+ unsigned &WhichResult) {
+ unsigned NumElts = VT.getVectorNumElements();
+ WhichResult = (M[0] == 0 ? 0 : 1);
+ for (unsigned i = 0; i < NumElts; i += 2) {
+ if ((unsigned) M[i] != i + WhichResult ||
+ (unsigned) M[i+1] != i + NumElts + WhichResult)
+ return false;
+ }
+ return true;
+}
+
+static bool isVUZPMask(const SmallVectorImpl<int> &M, EVT VT,
+ unsigned &WhichResult) {
+ unsigned NumElts = VT.getVectorNumElements();
+ WhichResult = (M[0] == 0 ? 0 : 1);
+ for (unsigned i = 0; i != NumElts; ++i) {
+ if ((unsigned) M[i] != 2 * i + WhichResult)
+ return false;
+ }
+
+ // VUZP.32 for 64-bit vectors is a pseudo-instruction alias for VTRN.32.
+ if (VT.is64BitVector() && VT.getVectorElementType().getSizeInBits() == 32)
+ return false;
+
+ return true;
+}
+
+static bool isVZIPMask(const SmallVectorImpl<int> &M, EVT VT,
+ unsigned &WhichResult) {
+ unsigned NumElts = VT.getVectorNumElements();
+ WhichResult = (M[0] == 0 ? 0 : 1);
+ unsigned Idx = WhichResult * NumElts / 2;
+ for (unsigned i = 0; i != NumElts; i += 2) {
+ if ((unsigned) M[i] != Idx ||
+ (unsigned) M[i+1] != Idx + NumElts)
+ return false;
+ Idx += 1;
+ }
+
+ // VZIP.32 for 64-bit vectors is a pseudo-instruction alias for VTRN.32.
+ if (VT.is64BitVector() && VT.getVectorElementType().getSizeInBits() == 32)
+ return false;
+
+ return true;
+}
+
static SDValue BuildSplat(SDValue Val, EVT VT, SelectionDAG &DAG, DebugLoc dl) {
// Canonicalize all-zeros and all-ones vectors.
ConstantSDNode *ConstVal = cast<ConstantSDNode>(Val.getNode());
@@ -2504,13 +2551,16 @@ ARMTargetLowering::isShuffleMaskLegal(const SmallVectorImpl<int> &M,
}
bool ReverseVEXT;
- unsigned Imm;
+ unsigned Imm, WhichResult;
return (ShuffleVectorSDNode::isSplatMask(&M[0], VT) ||
isVREVMask(M, VT, 64) ||
isVREVMask(M, VT, 32) ||
isVREVMask(M, VT, 16) ||
- isVEXTMask(M, VT, ReverseVEXT, Imm));
+ isVEXTMask(M, VT, ReverseVEXT, Imm) ||
+ isVTRNMask(M, VT, WhichResult) ||
+ isVUZPMask(M, VT, WhichResult) ||
+ isVZIPMask(M, VT, WhichResult));
}
/// GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit
@@ -2610,11 +2660,9 @@ static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
bool ReverseVEXT;
unsigned Imm;
if (isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
- SDValue Op0 = SVN->getOperand(0);
- SDValue Op1 = SVN->getOperand(1);
if (ReverseVEXT)
- std::swap(Op0, Op1);
- return DAG.getNode(ARMISD::VEXT, dl, VT, Op0, Op1,
+ std::swap(V1, V2);
+ return DAG.getNode(ARMISD::VEXT, dl, VT, V1, V2,
DAG.getConstant(Imm, MVT::i32));
}
@@ -2625,6 +2673,24 @@ static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
if (isVREVMask(ShuffleMask, VT, 16))
return DAG.getNode(ARMISD::VREV16, dl, VT, V1);
+ // Check for Neon shuffles that modify both input vectors in place.
+ // If both results are used, i.e., if there are two shuffles with the same
+ // source operands and with masks corresponding to both results of one of
+ // these operations, DAG memoization will ensure that a single node is
+ // used for both shuffles.
+ unsigned WhichResult;
+ if (isVTRNMask(ShuffleMask, VT, WhichResult))
+ return DAG.getNode(ARMISD::VTRN, dl, DAG.getVTList(VT, VT),
+ V1, V2).getValue(WhichResult);
+ if (isVUZPMask(ShuffleMask, VT, WhichResult))
+ return DAG.getNode(ARMISD::VUZP, dl, DAG.getVTList(VT, VT),
+ V1, V2).getValue(WhichResult);
+ if (isVZIPMask(ShuffleMask, VT, WhichResult))
+ return DAG.getNode(ARMISD::VZIP, dl, DAG.getVTList(VT, VT),
+ V1, V2).getValue(WhichResult);
+
+ // If the shuffle is not directly supported and it has 4 elements, use
+ // the PerfectShuffle-generated table to synthesize it from other shuffles.
if (VT.getVectorNumElements() == 4 &&
(VT.is128BitVector() || VT.is64BitVector())) {
unsigned PFIndexes[4];
diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h
index b2260e2d83..cb88be5513 100644
--- a/lib/Target/ARM/ARMISelLowering.h
+++ b/lib/Target/ARM/ARMISelLowering.h
@@ -132,9 +132,8 @@ namespace llvm {
VREV64, // reverse elements within 64-bit doublewords
VREV32, // reverse elements within 32-bit words
VREV16, // reverse elements within 16-bit halfwords
-
- VZIP, // zip
- VUZP, // unzip
+ VZIP, // zip (interleave)
+ VUZP, // unzip (deinterleave)
VTRN // transpose
};
}