diff options
author | Kevin Qin <Kevin.Qin@arm.com> | 2014-01-22 06:11:03 +0000 |
---|---|---|
committer | Kevin Qin <Kevin.Qin@arm.com> | 2014-01-22 06:11:03 +0000 |
commit | 0af7a7db530b62f20b6d5766e1a95816fc8eb66e (patch) | |
tree | b9ab31db34752f5c2a377de09cff776045c948f9 /lib/Target/AArch64 | |
parent | 0c1b9ec2dc1f5899a5c711d6ee4d8d66f1174e39 (diff) | |
download | llvm-0af7a7db530b62f20b6d5766e1a95816fc8eb66e.tar.gz llvm-0af7a7db530b62f20b6d5766e1a95816fc8eb66e.tar.bz2 llvm-0af7a7db530b62f20b6d5766e1a95816fc8eb66e.tar.xz |
[AArch64 NEON] Try to generate CONCAT_VECTOR when lowering BUILD_VECTOR or SHUFFLE_VECTOR.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199791 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/AArch64')
-rw-r--r-- | lib/Target/AArch64/AArch64ISelLowering.cpp | 113 | ||||
-rw-r--r-- | lib/Target/AArch64/AArch64ISelLowering.h | 6 |
2 files changed, 90 insertions, 29 deletions
diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp index 27277c47f3..4aae9e59e2 100644 --- a/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -4154,21 +4154,70 @@ AArch64TargetLowering::isFMAFasterThanFMulAndFAdd(EVT VT) const { return false; } -// Check whether a Build Vector could be presented as Shuffle Vector. If yes, -// try to call LowerVECTOR_SHUFFLE to lower it. +// Check whether a shuffle_vecotor could be presented as conact_vector. +bool AArch64TargetLowering::isConactVector(SDValue Op,SelectionDAG &DAG, + SDValue V0, SDValue V1, + const int* Mask, + SDValue &Res) const { + SDLoc DL(Op); + EVT VT = Op.getValueType(); + unsigned NumElts = VT.getVectorNumElements(); + unsigned V0NumElts = V0.getValueType().getVectorNumElements(); + bool isContactVector = true; + bool splitV0 = false; + int offset = 0; + for (int I = 0, E = NumElts; I != E; I++){ + if (Mask[I] != I + offset) { + if(I && !splitV0 && Mask[I] == I + (int)V0NumElts / 2) { + splitV0 = true; + offset = V0NumElts / 2; + } else { + isContactVector = false; + break; + } + } + } + if (isContactVector) { + EVT CastVT = EVT::getVectorVT(*DAG.getContext(), + VT.getVectorElementType(), NumElts / 2); + if(CastVT.getSizeInBits() < 64) + return false; + + if (splitV0) { + assert(V0NumElts >= NumElts / 2 && + "invalid operand for extract_subvector!"); + V0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, CastVT, V0, + DAG.getConstant(0, MVT::i64)); + } + if (NumElts != V1.getValueType().getVectorNumElements() * 2) { + assert(V1.getValueType().getVectorNumElements() >= NumElts / 2 && + "invalid operand for extract_subvector!"); + V1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, CastVT, V1, + DAG.getConstant(0, MVT::i64)); + } + Res = DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, V0, V1); + return true; + } + return false; +} + +// Check whether a Build Vector could be presented as Shuffle Vector. +// This Shuffle Vector maybe not legalized, so the length of its operand and +// the length of result may not equal. bool AArch64TargetLowering::isKnownShuffleVector(SDValue Op, SelectionDAG &DAG, - SDValue &Res) const { + SDValue &V0, SDValue &V1, + int *Mask) const { SDLoc DL(Op); EVT VT = Op.getValueType(); unsigned NumElts = VT.getVectorNumElements(); unsigned V0NumElts = 0; - int Mask[16]; - SDValue V0, V1; // Check if all elements are extracted from less than 3 vectors. for (unsigned i = 0; i < NumElts; ++i) { SDValue Elt = Op.getOperand(i); - if (Elt.getOpcode() != ISD::EXTRACT_VECTOR_ELT) + if (Elt.getOpcode() != ISD::EXTRACT_VECTOR_ELT || + Elt.getOperand(0).getValueType().getVectorElementType() != + VT.getVectorElementType()) return false; if (V0.getNode() == 0) { @@ -4189,25 +4238,7 @@ bool AArch64TargetLowering::isKnownShuffleVector(SDValue Op, SelectionDAG &DAG, return false; } } - - if (!V1.getNode() && V0NumElts == NumElts * 2) { - V1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, V0, - DAG.getConstant(NumElts, MVT::i64)); - V0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, V0, - DAG.getConstant(0, MVT::i64)); - V0NumElts = V0.getValueType().getVectorNumElements(); - } - - if (V1.getNode() && NumElts == V0NumElts && - V0NumElts == V1.getValueType().getVectorNumElements()) { - SDValue Shuffle = DAG.getVectorShuffle(VT, DL, V0, V1, Mask); - if(Shuffle.getOpcode() != ISD::VECTOR_SHUFFLE) - Res = Shuffle; - else - Res = LowerVECTOR_SHUFFLE(Shuffle, DAG); - return true; - } else - return false; + return true; } // If this is a case we can't handle, return null and let the default @@ -4413,9 +4444,31 @@ AArch64TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, return SDValue(); // Try to lower this in lowering ShuffleVector way. - SDValue Shuf; - if (isKnownShuffleVector(Op, DAG, Shuf)) - return Shuf; + SDValue V0, V1; + int Mask[16]; + if (isKnownShuffleVector(Op, DAG, V0, V1, Mask)) { + unsigned V0NumElts = V0.getValueType().getVectorNumElements(); + if (!V1.getNode() && V0NumElts == NumElts * 2) { + V1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, V0, + DAG.getConstant(NumElts, MVT::i64)); + V0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, V0, + DAG.getConstant(0, MVT::i64)); + V0NumElts = V0.getValueType().getVectorNumElements(); + } + + if (V1.getNode() && NumElts == V0NumElts && + V0NumElts == V1.getValueType().getVectorNumElements()) { + SDValue Shuffle = DAG.getVectorShuffle(VT, DL, V0, V1, Mask); + if(Shuffle.getOpcode() != ISD::VECTOR_SHUFFLE) + return Shuffle; + else + return LowerVECTOR_SHUFFLE(Shuffle, DAG); + } else { + SDValue Res; + if(isConactVector(Op, DAG, V0, V1, Mask, Res)) + return Res; + } + } // If all else fails, just use a sequence of INSERT_VECTOR_ELT when we // know the default expansion would otherwise fall back on something even @@ -4601,6 +4654,10 @@ AArch64TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, return DAG.getNode(ISDNo, dl, VT, V1, V2); } + SDValue Res; + if (isConactVector(Op, DAG, V1, V2, &ShuffleMask[0], Res)) + return Res; + // If the element of shuffle mask are all the same constant, we can // transform it into either NEON_VDUP or NEON_VDUPLANE if (ShuffleVectorSDNode::isSplatMask(&ShuffleMask[0], VT)) { diff --git a/lib/Target/AArch64/AArch64ISelLowering.h b/lib/Target/AArch64/AArch64ISelLowering.h index 3879663e57..8baf992a2b 100644 --- a/lib/Target/AArch64/AArch64ISelLowering.h +++ b/lib/Target/AArch64/AArch64ISelLowering.h @@ -232,7 +232,11 @@ public: SDLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const; - bool isKnownShuffleVector(SDValue Op, SelectionDAG &DAG, SDValue &Res) const; + bool isConactVector(SDValue Op,SelectionDAG &DAG, SDValue V0, SDValue V1, + const int* Mask, SDValue &Res) const; + + bool isKnownShuffleVector(SDValue Op, SelectionDAG &DAG, SDValue &V0, + SDValue &V1, int *Mask) const; SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, const AArch64Subtarget *ST) const; |