diff options
| author | Evan Cheng <evan.cheng@apple.com> | 2006-04-28 07:03:38 +0000 |
|---|---|---|
| committer | Evan Cheng <evan.cheng@apple.com> | 2006-04-28 07:03:38 +0000 |
| commit | 3cd4362adee1a4caac44bd3343314a56376a91b3 (patch) | |
| tree | c1070fa73cc7d60e869f732749843dee9f1e0c7b | |
| parent | 1b7a51520ccbfee8d66bb973631c001d04565491 (diff) | |
| download | bcm5719-llvm-3cd4362adee1a4caac44bd3343314a56376a91b3.tar.gz bcm5719-llvm-3cd4362adee1a4caac44bd3343314a56376a91b3.zip | |
Implement four-wide shuffle with 2 shufps if no more than two elements come
from each vector. e.g.
shuffle(G1, G2, 7, 1, 5, 2)
==>
movaps _G2, %xmm0
shufps $151, _G1, %xmm0
shufps $216, %xmm0, %xmm0
llvm-svn: 28011
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index b0dd6a6cee9..06c6d80c43b 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -2676,10 +2676,55 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDOperand Op, SelectionDAG &DAG) { } if (NumElems == 4) { - // Break it into (shuffle shuffle_hi, shuffle_lo). MVT::ValueType MaskVT = PermMask.getValueType(); MVT::ValueType MaskEVT = MVT::getVectorBaseType(MaskVT); - std::map<unsigned, std::pair<int, int> > Locs; + std::vector<std::pair<int, int> > Locs; + Locs.reserve(NumElems); + std::vector<SDOperand> Mask1(NumElems, DAG.getNode(ISD::UNDEF, MaskEVT)); + std::vector<SDOperand> 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)); + 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)); + } + + // Break it into (shuffle shuffle_hi, shuffle_lo). + Locs.clear(); std::vector<SDOperand> LoMask(NumElems, DAG.getNode(ISD::UNDEF, MaskEVT)); std::vector<SDOperand> HiMask(NumElems, DAG.getNode(ISD::UNDEF, MaskEVT)); std::vector<SDOperand> *MaskPtr = &LoMask; |

