diff options
| author | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2017-12-07 17:37:28 +0000 |
|---|---|---|
| committer | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2017-12-07 17:37:28 +0000 |
| commit | 039d4d928620de3279d49617141d4bd1061e62fb (patch) | |
| tree | ac4f90f7016de159daf6eacc7377e3b88e761a0b /llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp | |
| parent | d2e93e76b82095cf6c149a501d3a0ff33bfdcc24 (diff) | |
| download | bcm5719-llvm-039d4d928620de3279d49617141d4bd1061e62fb.tar.gz bcm5719-llvm-039d4d928620de3279d49617141d4bd1061e62fb.zip | |
[Hexagon] Generate HVX code for basic arithmetic operations
Handle and, or, xor, add, sub, mul for vectors of i8, i16, and i32.
llvm-svn: 320063
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp')
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp index 6b25f74860e..de2ac42ad51 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp @@ -111,6 +111,37 @@ HexagonTargetLowering::getIndexInWord32(SDValue Idx, MVT ElemTy, } SDValue +HexagonTargetLowering::getByteShuffle(const SDLoc &dl, SDValue Op0, + SDValue Op1, ArrayRef<int> Mask, + SelectionDAG &DAG) const { + MVT OpTy = ty(Op0); + assert(OpTy == ty(Op1)); + + MVT ElemTy = OpTy.getVectorElementType(); + if (ElemTy == MVT::i8) + return DAG.getVectorShuffle(OpTy, dl, Op0, Op1, Mask); + assert(ElemTy.getSizeInBits() >= 8); + + MVT ResTy = tyVector(OpTy, MVT::i8); + unsigned ElemSize = ElemTy.getSizeInBits() / 8; + + SmallVector<int,128> ByteMask; + for (int M : Mask) { + if (M < 0) { + for (unsigned I = 0; I != ElemSize; ++I) + ByteMask.push_back(-1); + } else { + int NewM = M*ElemSize; + for (unsigned I = 0; I != ElemSize; ++I) + ByteMask.push_back(NewM+I); + } + } + assert(ResTy.getVectorNumElements() == ByteMask.size()); + return DAG.getVectorShuffle(ResTy, dl, opCastElem(Op0, MVT::i8, DAG), + opCastElem(Op1, MVT::i8, DAG), ByteMask); +} + +SDValue HexagonTargetLowering::LowerHvxBuildVector(SDValue Op, SelectionDAG &DAG) const { const SDLoc &dl(Op); @@ -276,7 +307,7 @@ HexagonTargetLowering::LowerHvxExtractSubvector(SDValue Op, SelectionDAG &DAG) SDValue HexagonTargetLowering::LowerHvxInsertSubvector(SDValue Op, SelectionDAG &DAG) const { - // Idx may be variable + // Idx may be variable. SDValue IdxV = Op.getOperand(2); auto *IdxN = dyn_cast<ConstantSDNode>(IdxV.getNode()); if (!IdxN) @@ -299,3 +330,56 @@ HexagonTargetLowering::LowerHvxInsertSubvector(SDValue Op, SelectionDAG &DAG) return DAG.getTargetInsertSubreg(Hexagon::vsub_hi, dl, DstTy, DstV, SrcV); return SDValue(); } + +SDValue +HexagonTargetLowering::LowerHvxMul(SDValue Op, SelectionDAG &DAG) const { + MVT ResTy = ty(Op); + if (!ResTy.isVector()) + return SDValue(); + const SDLoc &dl(Op); + SmallVector<int,256> ShuffMask; + + MVT ElemTy = ResTy.getVectorElementType(); + unsigned VecLen = ResTy.getVectorNumElements(); + SDValue Vs = Op.getOperand(0); + SDValue Vt = Op.getOperand(1); + + switch (ElemTy.SimpleTy) { + case MVT::i8: + case MVT::i16: { + // For i8 vectors Vs = (a0, a1, ...), Vt = (b0, b1, ...), + // V6_vmpybv Vs, Vt produces a pair of i16 vectors Hi:Lo, + // where Lo = (a0*b0, a2*b2, ...), Hi = (a1*b1, a3*b3, ...). + // For i16, use V6_vmpyhv, which behaves in an analogous way to + // V6_vmpybv: results Lo and Hi are products of even/odd elements + // respectively. + MVT ExtTy = typeExtElem(ResTy, 2); + unsigned MpyOpc = ElemTy == MVT::i8 ? Hexagon::V6_vmpybv + : Hexagon::V6_vmpyhv; + SDValue M = getNode(MpyOpc, dl, ExtTy, {Vs, Vt}, DAG); + + // Discard high halves of the resulting values, collect the low halves. + for (unsigned I = 0; I < VecLen; I += 2) { + ShuffMask.push_back(I); // Pick even element. + ShuffMask.push_back(I+VecLen); // Pick odd element. + } + VectorPair P = opSplit(opCastElem(M, ElemTy, DAG), dl, DAG); + return getByteShuffle(dl, P.first, P.second, ShuffMask, DAG); + } + case MVT::i32: { + // Use the following sequence for signed word multiply: + // T0 = V6_vmpyiowh Vs, Vt + // T1 = V6_vaslw T0, 16 + // T2 = V6_vmpyiewuh_acc T1, Vs, Vt + SDValue S16 = DAG.getConstant(16, dl, MVT::i32); + SDValue T0 = getNode(Hexagon::V6_vmpyiowh, dl, ResTy, {Vs, Vt}, DAG); + SDValue T1 = getNode(Hexagon::V6_vaslw, dl, ResTy, {T0, S16}, DAG); + SDValue T2 = getNode(Hexagon::V6_vmpyiewuh_acc, dl, ResTy, + {T1, Vs, Vt}, DAG); + return T2; + } + default: + break; + } + return SDValue(); +} |

