diff options
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp')
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp | 151 |
1 files changed, 125 insertions, 26 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp index 9d0e4beea87..264a2d16c29 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp @@ -75,6 +75,10 @@ HexagonTargetLowering::VectorPair HexagonTargetLowering::opSplit(SDValue Vec, const SDLoc &dl, SelectionDAG &DAG) const { TypePair Tys = typeSplit(ty(Vec)); + if (Vec.getOpcode() == HexagonISD::QCAT) { +assert(0); + return VectorPair(Vec.getOperand(0), Vec.getOperand(1)); + } return DAG.SplitVector(Vec, dl, Tys.first, Tys.second); } @@ -799,7 +803,26 @@ HexagonTargetLowering::LowerHvxConcatVectors(SDValue Op, SelectionDAG &DAG) unsigned HwLen = Subtarget.getVectorLength(); unsigned NumOp = Op.getNumOperands(); assert(isPowerOf2_32(NumOp) && HwLen % NumOp == 0); - (void)NumOp; + + SDValue Op0 = Op.getOperand(0); + + // If the operands are HVX types (i.e. not scalar predicates), then + // defer the concatenation, and create QCAT instead. + if (Subtarget.isHVXVectorType(ty(Op0), true)) { + if (NumOp == 2) + return DAG.getNode(HexagonISD::QCAT, dl, VecTy, Op0, Op.getOperand(1)); + + ArrayRef<SDUse> U(Op.getNode()->ops()); + SmallVector<SDValue,4> SV(U.begin(), U.end()); + ArrayRef<SDValue> Ops(SV); + + MVT HalfTy = typeSplit(VecTy).first; + SDValue V0 = DAG.getNode(ISD::CONCAT_VECTORS, dl, HalfTy, + Ops.take_front(NumOp/2)); + SDValue V1 = DAG.getNode(ISD::CONCAT_VECTORS, dl, HalfTy, + Ops.take_back(NumOp/2)); + return DAG.getNode(HexagonISD::QCAT, dl, VecTy, V0, V1); + } // Count how many bytes (in a vector register) each bit in VecTy // corresponds to. @@ -889,7 +912,7 @@ HexagonTargetLowering::LowerHvxInsertSubvector(SDValue Op, SelectionDAG &DAG) SDValue HexagonTargetLowering::LowerHvxMul(SDValue Op, SelectionDAG &DAG) const { MVT ResTy = ty(Op); - assert(ResTy.isVector()); + assert(ResTy.isVector() && isHvxSingleTy(ResTy)); const SDLoc &dl(Op); SmallVector<int,256> ShuffMask; @@ -1047,30 +1070,6 @@ HexagonTargetLowering::LowerHvxMulh(SDValue Op, SelectionDAG &DAG) const { } SDValue -HexagonTargetLowering::LowerHvxSetCC(SDValue Op, SelectionDAG &DAG) const { - MVT ResTy = ty(Op); - MVT VecTy = ty(Op.getOperand(0)); - assert(VecTy == ty(Op.getOperand(1))); - unsigned HwLen = Subtarget.getVectorLength(); - const SDLoc &dl(Op); - - SDValue Cmp = Op.getOperand(2); - ISD::CondCode CC = cast<CondCodeSDNode>(Cmp)->get(); - - if (VecTy.getSizeInBits() == 16*HwLen) { - VectorPair P0 = opSplit(Op.getOperand(0), dl, DAG); - VectorPair P1 = opSplit(Op.getOperand(1), dl, DAG); - MVT HalfTy = typeSplit(ResTy).first; - - SDValue V0 = DAG.getSetCC(dl, HalfTy, P0.first, P1.first, CC); - SDValue V1 = DAG.getSetCC(dl, HalfTy, P0.second, P1.second, CC); - return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResTy, V1, V0); - } - - return SDValue(); -} - -SDValue HexagonTargetLowering::LowerHvxExtend(SDValue Op, SelectionDAG &DAG) const { // Sign- and zero-extends are legal. assert(Op.getOpcode() == ISD::ANY_EXTEND_VECTOR_INREG); @@ -1082,3 +1081,103 @@ HexagonTargetLowering::LowerHvxShift(SDValue Op, SelectionDAG &DAG) const { return Op; } +SDValue +HexagonTargetLowering::SplitHvxPairOp(SDValue Op, SelectionDAG &DAG) const { + assert(!Op.isMachineOpcode()); + SmallVector<SDValue,2> OpsL, OpsH; + const SDLoc &dl(Op); + + auto SplitVTNode = [&DAG,this] (const VTSDNode *N) { + MVT Ty = typeSplit(N->getVT().getSimpleVT()).first; + SDValue TV = DAG.getValueType(Ty); + return std::make_pair(TV, TV); + }; + + for (SDValue A : Op.getNode()->ops()) { + VectorPair P = Subtarget.isHVXVectorType(ty(A), true) + ? opSplit(A, dl, DAG) + : std::make_pair(A, A); + // Special case for type operand. + if (Op.getOpcode() == ISD::SIGN_EXTEND_INREG) { + if (const auto *N = dyn_cast<const VTSDNode>(A.getNode())) + P = SplitVTNode(N); + } + OpsL.push_back(P.first); + OpsH.push_back(P.second); + } + + MVT ResTy = ty(Op); + MVT HalfTy = typeSplit(ResTy).first; + SDValue L = DAG.getNode(Op.getOpcode(), dl, HalfTy, OpsL); + SDValue H = DAG.getNode(Op.getOpcode(), dl, HalfTy, OpsH); + SDValue S = DAG.getNode(ISD::CONCAT_VECTORS, dl, ResTy, L, H); + return S; +} + +SDValue +HexagonTargetLowering::LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const { + unsigned Opc = Op.getOpcode(); + bool IsPairOp = isHvxPairTy(ty(Op)) || + llvm::any_of(Op.getNode()->ops(), [this] (SDValue V) { + return isHvxPairTy(ty(V)); + }); + + if (IsPairOp) { + switch (Opc) { + default: + break; + case ISD::MUL: + case ISD::MULHS: + case ISD::MULHU: + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::SRA: + case ISD::SHL: + case ISD::SRL: + case ISD::SETCC: + case ISD::VSELECT: + case ISD::SIGN_EXTEND_INREG: + return SplitHvxPairOp(Op, DAG); + } + } + + switch (Opc) { + default: + break; + case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG); + case ISD::INSERT_SUBVECTOR: return LowerINSERT_SUBVECTOR(Op, DAG); + case ISD::INSERT_VECTOR_ELT: return LowerINSERT_VECTOR_ELT(Op, DAG); + case ISD::EXTRACT_SUBVECTOR: return LowerEXTRACT_SUBVECTOR(Op, DAG); + case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG); + case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG); + case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG); + case ISD::ANY_EXTEND: return LowerANY_EXTEND(Op, DAG); + case ISD::SIGN_EXTEND: return LowerSIGN_EXTEND(Op, DAG); + case ISD::ZERO_EXTEND: return LowerZERO_EXTEND(Op, DAG); + case ISD::SRA: + case ISD::SHL: + case ISD::SRL: return LowerVECTOR_SHIFT(Op, DAG); + case ISD::MUL: return LowerHvxMul(Op, DAG); + case ISD::MULHS: + case ISD::MULHU: return LowerHvxMulh(Op, DAG); + case ISD::ANY_EXTEND_VECTOR_INREG: return LowerHvxExtend(Op, DAG); + case ISD::SETCC: + case ISD::INTRINSIC_VOID: return Op; + } +#ifndef NDEBUG + Op.dumpr(&DAG); +#endif + llvm_unreachable("Unhandled HVX operation"); +} + +bool +HexagonTargetLowering::isHvxOperation(SDValue Op) const { + // If the type of the result, or any operand type are HVX vector types, + // this is an HVX operation. + return Subtarget.isHVXVectorType(ty(Op)) || + llvm::any_of(Op.getNode()->ops(), + [this] (SDValue V) { + return Subtarget.isHVXVectorType(ty(V), true); + }); +} |