summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2008-07-22 21:13:36 +0000
committerEvan Cheng <evan.cheng@apple.com>2008-07-22 21:13:36 +0000
commitace3c17798d49245593cd9d2312a68e1ebafae56 (patch)
treeb293802579cb53d6092f37e9eef407d4da8c752f
parent292578676524036842aecb2d932e3995dddd9c2a (diff)
downloadllvm-ace3c17798d49245593cd9d2312a68e1ebafae56.tar.gz
llvm-ace3c17798d49245593cd9d2312a68e1ebafae56.tar.bz2
llvm-ace3c17798d49245593cd9d2312a68e1ebafae56.tar.xz
Factor out SSE 4 wide shuffle lowering code into its own function. No functionality changes.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53933 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp210
1 files changed, 106 insertions, 104 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index fb4f005c9b..2ebda55060 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -3645,6 +3645,109 @@ static SDOperand getVZextMovL(MVT VT, MVT OpVT,
DAG.getNode(ISD::BIT_CONVERT, OpVT, SrcOp)));
}
+/// LowerVECTOR_SHUFFLE_4wide - Handle all 4 wide cases with a number of
+/// shuffles.
+static SDOperand
+LowerVECTOR_SHUFFLE_4wide(SDOperand V1, SDOperand V2,
+ SDOperand PermMask, MVT VT, SelectionDAG &DAG) {
+ MVT MaskVT = PermMask.getValueType();
+ MVT MaskEVT = MaskVT.getVectorElementType();
+ SmallVector<std::pair<int, int>, 8> Locs;
+ Locs.reserve(4);
+ SmallVector<SDOperand, 8> Mask1(4, DAG.getNode(ISD::UNDEF, MaskEVT));
+ SmallVector<SDOperand, 8> Mask2(4, DAG.getNode(ISD::UNDEF, MaskEVT));
+ unsigned NumHi = 0;
+ unsigned NumLo = 0;
+ // If no more than two elements come from either vector. This can be
+ // implemented with two shuffles. First shuffle gather the elements.
+ // The second shuffle, which takes the first shuffle as both of its
+ // vector operands, put the elements into the right order.
+ for (unsigned i = 0; i != 4; ++i) {
+ SDOperand Elt = PermMask.getOperand(i);
+ if (Elt.getOpcode() == ISD::UNDEF) {
+ Locs[i] = std::make_pair(-1, -1);
+ } else {
+ unsigned Val = cast<ConstantSDNode>(Elt)->getValue();
+ if (Val < 4) {
+ Locs[i] = std::make_pair(0, NumLo);
+ Mask1[NumLo] = Elt;
+ NumLo++;
+ } else {
+ Locs[i] = std::make_pair(1, NumHi);
+ if (2+NumHi < 4)
+ Mask1[2+NumHi] = Elt;
+ NumHi++;
+ }
+ }
+ }
+ if (NumLo <= 2 && NumHi <= 2) {
+ V1 = DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
+ DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
+ &Mask1[0], Mask1.size()));
+ for (unsigned i = 0; i != 4; ++i) {
+ if (Locs[i].first == -1)
+ continue;
+ else {
+ unsigned Idx = (i < 2) ? 0 : 4;
+ Idx += Locs[i].first * 2 + Locs[i].second;
+ Mask2[i] = DAG.getConstant(Idx, MaskEVT);
+ }
+ }
+
+ return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V1,
+ DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
+ &Mask2[0], Mask2.size()));
+ }
+
+ // Break it into (shuffle shuffle_hi, shuffle_lo).
+ Locs.clear();
+ SmallVector<SDOperand,8> LoMask(4, DAG.getNode(ISD::UNDEF, MaskEVT));
+ SmallVector<SDOperand,8> HiMask(4, DAG.getNode(ISD::UNDEF, MaskEVT));
+ SmallVector<SDOperand,8> *MaskPtr = &LoMask;
+ unsigned MaskIdx = 0;
+ unsigned LoIdx = 0;
+ unsigned HiIdx = 2;
+ for (unsigned i = 0; i != 4; ++i) {
+ if (i == 2) {
+ MaskPtr = &HiMask;
+ MaskIdx = 1;
+ LoIdx = 0;
+ HiIdx = 2;
+ }
+ SDOperand Elt = PermMask.getOperand(i);
+ if (Elt.getOpcode() == ISD::UNDEF) {
+ Locs[i] = std::make_pair(-1, -1);
+ } else if (cast<ConstantSDNode>(Elt)->getValue() < 4) {
+ Locs[i] = std::make_pair(MaskIdx, LoIdx);
+ (*MaskPtr)[LoIdx] = Elt;
+ LoIdx++;
+ } else {
+ Locs[i] = std::make_pair(MaskIdx, HiIdx);
+ (*MaskPtr)[HiIdx] = Elt;
+ HiIdx++;
+ }
+ }
+
+ SDOperand LoShuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
+ DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
+ &LoMask[0], LoMask.size()));
+ SDOperand HiShuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
+ DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
+ &HiMask[0], HiMask.size()));
+ SmallVector<SDOperand, 8> MaskOps;
+ for (unsigned i = 0; i != 4; ++i) {
+ if (Locs[i].first == -1) {
+ MaskOps.push_back(DAG.getNode(ISD::UNDEF, MaskEVT));
+ } else {
+ unsigned Idx = Locs[i].first * 4 + Locs[i].second;
+ MaskOps.push_back(DAG.getConstant(Idx, MaskEVT));
+ }
+ }
+ return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, LoShuffle, HiShuffle,
+ DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
+ &MaskOps[0], MaskOps.size()));
+}
+
SDOperand
X86TargetLowering::LowerVECTOR_SHUFFLE(SDOperand Op, SelectionDAG &DAG) {
SDOperand V1 = Op.getOperand(0);
@@ -3851,110 +3954,9 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDOperand Op, SelectionDAG &DAG) {
return NewOp;
}
- // Handle all 4 wide cases with a number of shuffles.
- if (NumElems == 4 && !isMMX) {
- // Don't do this for MMX.
- MVT MaskVT = PermMask.getValueType();
- MVT MaskEVT = MaskVT.getVectorElementType();
- SmallVector<std::pair<int, int>, 8> Locs;
- Locs.reserve(NumElems);
- SmallVector<SDOperand, 8> Mask1(NumElems,
- DAG.getNode(ISD::UNDEF, MaskEVT));
- SmallVector<SDOperand, 8> Mask2(NumElems,
- DAG.getNode(ISD::UNDEF, MaskEVT));
- unsigned NumHi = 0;
- unsigned NumLo = 0;
- // If no more than two elements come from either vector. This can be
- // implemented with two shuffles. First shuffle gather the elements.
- // The second shuffle, which takes the first shuffle as both of its
- // vector operands, put the elements into the right order.
- for (unsigned i = 0; i != NumElems; ++i) {
- SDOperand Elt = PermMask.getOperand(i);
- if (Elt.getOpcode() == ISD::UNDEF) {
- Locs[i] = std::make_pair(-1, -1);
- } else {
- unsigned Val = cast<ConstantSDNode>(Elt)->getValue();
- if (Val < NumElems) {
- Locs[i] = std::make_pair(0, NumLo);
- Mask1[NumLo] = Elt;
- NumLo++;
- } else {
- Locs[i] = std::make_pair(1, NumHi);
- if (2+NumHi < NumElems)
- Mask1[2+NumHi] = Elt;
- NumHi++;
- }
- }
- }
- if (NumLo <= 2 && NumHi <= 2) {
- V1 = DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
- DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
- &Mask1[0], Mask1.size()));
- for (unsigned i = 0; i != NumElems; ++i) {
- if (Locs[i].first == -1)
- continue;
- else {
- unsigned Idx = (i < NumElems/2) ? 0 : NumElems;
- Idx += Locs[i].first * (NumElems/2) + Locs[i].second;
- Mask2[i] = DAG.getConstant(Idx, MaskEVT);
- }
- }
-
- return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V1,
- DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
- &Mask2[0], Mask2.size()));
- }
-
- // Break it into (shuffle shuffle_hi, shuffle_lo).
- Locs.clear();
- SmallVector<SDOperand,8> LoMask(NumElems, DAG.getNode(ISD::UNDEF, MaskEVT));
- SmallVector<SDOperand,8> HiMask(NumElems, DAG.getNode(ISD::UNDEF, MaskEVT));
- SmallVector<SDOperand,8> *MaskPtr = &LoMask;
- unsigned MaskIdx = 0;
- unsigned LoIdx = 0;
- unsigned HiIdx = NumElems/2;
- for (unsigned i = 0; i != NumElems; ++i) {
- if (i == NumElems/2) {
- MaskPtr = &HiMask;
- MaskIdx = 1;
- LoIdx = 0;
- HiIdx = NumElems/2;
- }
- SDOperand Elt = PermMask.getOperand(i);
- if (Elt.getOpcode() == ISD::UNDEF) {
- Locs[i] = std::make_pair(-1, -1);
- } else if (cast<ConstantSDNode>(Elt)->getValue() < NumElems) {
- Locs[i] = std::make_pair(MaskIdx, LoIdx);
- (*MaskPtr)[LoIdx] = Elt;
- LoIdx++;
- } else {
- Locs[i] = std::make_pair(MaskIdx, HiIdx);
- (*MaskPtr)[HiIdx] = Elt;
- HiIdx++;
- }
- }
-
- SDOperand LoShuffle =
- DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
- DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
- &LoMask[0], LoMask.size()));
- SDOperand HiShuffle =
- DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
- DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
- &HiMask[0], HiMask.size()));
- SmallVector<SDOperand, 8> MaskOps;
- for (unsigned i = 0; i != NumElems; ++i) {
- if (Locs[i].first == -1) {
- MaskOps.push_back(DAG.getNode(ISD::UNDEF, MaskEVT));
- } else {
- unsigned Idx = Locs[i].first * NumElems + Locs[i].second;
- MaskOps.push_back(DAG.getConstant(Idx, MaskEVT));
- }
- }
- return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, LoShuffle, HiShuffle,
- DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
- &MaskOps[0], MaskOps.size()));
- }
+ // Handle all 4 wide cases with a number of shuffles except for MMX.
+ if (NumElems == 4 && !isMMX)
+ return LowerVECTOR_SHUFFLE_4wide(V1, V2, PermMask, VT, DAG);
return SDOperand();
}