diff options
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp')
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp | 222 |
1 files changed, 210 insertions, 12 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp index 7e9ef9dc85b..4b732171805 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp @@ -13,6 +13,168 @@ using namespace llvm; +static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 }; +static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 }; +static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 }; +static const MVT LegalW128[] = { MVT::v256i8, MVT::v128i16, MVT::v64i32 }; + + +void +HexagonTargetLowering::initializeHVXLowering() { + if (Subtarget.useHVX64BOps()) { + addRegisterClass(MVT::v64i8, &Hexagon::HvxVRRegClass); + addRegisterClass(MVT::v32i16, &Hexagon::HvxVRRegClass); + addRegisterClass(MVT::v16i32, &Hexagon::HvxVRRegClass); + addRegisterClass(MVT::v128i8, &Hexagon::HvxWRRegClass); + addRegisterClass(MVT::v64i16, &Hexagon::HvxWRRegClass); + addRegisterClass(MVT::v32i32, &Hexagon::HvxWRRegClass); + // These "short" boolean vector types should be legal because + // they will appear as results of vector compares. If they were + // not legal, type legalization would try to make them legal + // and that would require using operations that do not use or + // produce such types. That, in turn, would imply using custom + // nodes, which would be unoptimizable by the DAG combiner. + // The idea is to rely on target-independent operations as much + // as possible. + addRegisterClass(MVT::v16i1, &Hexagon::HvxQRRegClass); + addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass); + addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass); + addRegisterClass(MVT::v512i1, &Hexagon::HvxQRRegClass); + } else if (Subtarget.useHVX128BOps()) { + addRegisterClass(MVT::v128i8, &Hexagon::HvxVRRegClass); + addRegisterClass(MVT::v64i16, &Hexagon::HvxVRRegClass); + addRegisterClass(MVT::v32i32, &Hexagon::HvxVRRegClass); + addRegisterClass(MVT::v256i8, &Hexagon::HvxWRRegClass); + addRegisterClass(MVT::v128i16, &Hexagon::HvxWRRegClass); + addRegisterClass(MVT::v64i32, &Hexagon::HvxWRRegClass); + addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass); + addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass); + addRegisterClass(MVT::v128i1, &Hexagon::HvxQRRegClass); + addRegisterClass(MVT::v1024i1, &Hexagon::HvxQRRegClass); + } + + // Set up operation actions. + + bool Use64b = Subtarget.useHVX64BOps(); + ArrayRef<MVT> LegalV = Use64b ? LegalV64 : LegalV128; + ArrayRef<MVT> LegalW = Use64b ? LegalW64 : LegalW128; + MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8; + MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8; + + auto setPromoteTo = [this] (unsigned Opc, MVT FromTy, MVT ToTy) { + setOperationAction(Opc, FromTy, Promote); + AddPromotedToType(Opc, FromTy, ToTy); + }; + + setOperationAction(ISD::VECTOR_SHUFFLE, ByteV, Legal); + setOperationAction(ISD::VECTOR_SHUFFLE, ByteW, Legal); + setOperationAction(ISD::AND, ByteV, Legal); + setOperationAction(ISD::OR, ByteV, Legal); + setOperationAction(ISD::XOR, ByteV, Legal); + + for (MVT T : LegalV) { + setIndexedLoadAction(ISD::POST_INC, T, Legal); + setIndexedStoreAction(ISD::POST_INC, T, Legal); + + setOperationAction(ISD::ADD, T, Legal); + setOperationAction(ISD::SUB, T, Legal); + if (T != ByteV) { + setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Legal); + setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Legal); + } + + setOperationAction(ISD::MUL, T, Custom); + setOperationAction(ISD::MULHS, T, Custom); + setOperationAction(ISD::MULHU, T, Custom); + setOperationAction(ISD::BUILD_VECTOR, T, Custom); + // Make concat-vectors custom to handle concats of more than 2 vectors. + setOperationAction(ISD::CONCAT_VECTORS, T, Custom); + setOperationAction(ISD::INSERT_SUBVECTOR, T, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, T, Custom); + setOperationAction(ISD::EXTRACT_SUBVECTOR, T, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, T, Custom); + setOperationAction(ISD::ANY_EXTEND, T, Custom); + setOperationAction(ISD::SIGN_EXTEND, T, Custom); + setOperationAction(ISD::ZERO_EXTEND, T, Custom); + if (T != ByteV) { + setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, T, Custom); + // HVX only has shifts of words and halfwords. + setOperationAction(ISD::SRA, T, Custom); + setOperationAction(ISD::SHL, T, Custom); + setOperationAction(ISD::SRL, T, Custom); + } + + setCondCodeAction(ISD::SETNE, T, Expand); + setCondCodeAction(ISD::SETLE, T, Expand); + setCondCodeAction(ISD::SETGE, T, Expand); + setCondCodeAction(ISD::SETLT, T, Expand); + setCondCodeAction(ISD::SETULE, T, Expand); + setCondCodeAction(ISD::SETUGE, T, Expand); + setCondCodeAction(ISD::SETULT, T, Expand); + } + + for (MVT T : LegalV) { + MVT BoolV = MVT::getVectorVT(MVT::i1, T.getVectorNumElements()); + setOperationAction(ISD::BUILD_VECTOR, BoolV, Custom); + setOperationAction(ISD::CONCAT_VECTORS, BoolV, Custom); + setOperationAction(ISD::INSERT_SUBVECTOR, BoolV, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, BoolV, Custom); + setOperationAction(ISD::EXTRACT_SUBVECTOR, BoolV, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, BoolV, Custom); + } + + for (MVT T : LegalV) { + if (T == ByteV) + continue; + // Promote all shuffles to operate on vectors of bytes. + setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteV); + setPromoteTo(ISD::AND, T, ByteV); + setPromoteTo(ISD::OR, T, ByteV); + setPromoteTo(ISD::XOR, T, ByteV); + } + + for (MVT T : LegalW) { + // Custom-lower BUILD_VECTOR for vector pairs. The standard (target- + // independent) handling of it would convert it to a load, which is + // not always the optimal choice. + setOperationAction(ISD::BUILD_VECTOR, T, Custom); + // Make concat-vectors custom to handle concats of more than 2 vectors. + setOperationAction(ISD::CONCAT_VECTORS, T, Custom); + + // Custom-lower these operations for pairs. Expand them into a concat + // of the corresponding operations on individual vectors. + setOperationAction(ISD::ANY_EXTEND, T, Custom); + setOperationAction(ISD::SIGN_EXTEND, T, Custom); + setOperationAction(ISD::ZERO_EXTEND, T, Custom); + setOperationAction(ISD::SIGN_EXTEND_INREG, T, Custom); + setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, T, Custom); + setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Legal); + setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Legal); + + setOperationAction(ISD::ADD, T, Legal); + setOperationAction(ISD::SUB, T, Legal); + setOperationAction(ISD::MUL, T, Custom); + setOperationAction(ISD::MULHS, T, Custom); + setOperationAction(ISD::MULHU, T, Custom); + setOperationAction(ISD::AND, T, Custom); + setOperationAction(ISD::OR, T, Custom); + setOperationAction(ISD::XOR, T, Custom); + setOperationAction(ISD::SETCC, T, Custom); + setOperationAction(ISD::VSELECT, T, Custom); + if (T != ByteW) { + setOperationAction(ISD::SRA, T, Custom); + setOperationAction(ISD::SHL, T, Custom); + setOperationAction(ISD::SRL, T, Custom); + + // Promote all shuffles to operate on vectors of bytes. + setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteW); + } + + MVT BoolV = MVT::getVectorVT(MVT::i1, T.getVectorNumElements()); + setOperationAction(ISD::SETCC, BoolV, Custom); + } +} + SDValue HexagonTargetLowering::getInt(unsigned IntId, MVT ResTy, ArrayRef<SDValue> Ops, const SDLoc &dl, SelectionDAG &DAG) const { @@ -917,6 +1079,40 @@ HexagonTargetLowering::LowerHvxInsertSubvector(SDValue Op, SelectionDAG &DAG) } SDValue +HexagonTargetLowering::LowerHvxAnyExt(SDValue Op, SelectionDAG &DAG) const { + // Lower any-extends of boolean vectors to sign-extends, since they + // translate directly to Q2V. Zero-extending could also be done equally + // fast, but Q2V is used/recognized in more places. + // For all other vectors, use zero-extend. + MVT ResTy = ty(Op); + SDValue InpV = Op.getOperand(0); + MVT ElemTy = ty(InpV).getVectorElementType(); + if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy)) + return LowerHvxSignExt(Op, DAG); + return DAG.getNode(ISD::ZERO_EXTEND, SDLoc(Op), ResTy, InpV); +} + +SDValue +HexagonTargetLowering::LowerHvxSignExt(SDValue Op, SelectionDAG &DAG) const { + MVT ResTy = ty(Op); + SDValue InpV = Op.getOperand(0); + MVT ElemTy = ty(InpV).getVectorElementType(); + if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy)) + return extendHvxVectorPred(InpV, SDLoc(Op), ty(Op), false, DAG); + return Op; +} + +SDValue +HexagonTargetLowering::LowerHvxZeroExt(SDValue Op, SelectionDAG &DAG) const { + MVT ResTy = ty(Op); + SDValue InpV = Op.getOperand(0); + MVT ElemTy = ty(InpV).getVectorElementType(); + if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy)) + return extendHvxVectorPred(InpV, SDLoc(Op), ty(Op), true, DAG); + return Op; +} + +SDValue HexagonTargetLowering::LowerHvxMul(SDValue Op, SelectionDAG &DAG) const { MVT ResTy = ty(Op); assert(ResTy.isVector() && isHvxSingleTy(ResTy)); @@ -1085,6 +1281,8 @@ HexagonTargetLowering::LowerHvxExtend(SDValue Op, SelectionDAG &DAG) const { SDValue HexagonTargetLowering::LowerHvxShift(SDValue Op, SelectionDAG &DAG) const { + if (SDValue S = getVectorShiftByInt(Op, DAG)) + return S; return Op; } @@ -1152,19 +1350,19 @@ HexagonTargetLowering::LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const { 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::BUILD_VECTOR: return LowerHvxBuildVector(Op, DAG); + case ISD::CONCAT_VECTORS: return LowerHvxConcatVectors(Op, DAG); + case ISD::INSERT_SUBVECTOR: return LowerHvxInsertSubvector(Op, DAG); + case ISD::INSERT_VECTOR_ELT: return LowerHvxInsertElement(Op, DAG); + case ISD::EXTRACT_SUBVECTOR: return LowerHvxExtractSubvector(Op, DAG); + case ISD::EXTRACT_VECTOR_ELT: return LowerHvxExtractElement(Op, DAG); + + case ISD::ANY_EXTEND: return LowerHvxAnyExt(Op, DAG); + case ISD::SIGN_EXTEND: return LowerHvxSignExt(Op, DAG); + case ISD::ZERO_EXTEND: return LowerHvxZeroExt(Op, DAG); case ISD::SRA: case ISD::SHL: - case ISD::SRL: return LowerVECTOR_SHIFT(Op, DAG); + case ISD::SRL: return LowerHvxShift(Op, DAG); case ISD::MUL: return LowerHvxMul(Op, DAG); case ISD::MULHS: case ISD::MULHU: return LowerHvxMulh(Op, DAG); @@ -1182,7 +1380,7 @@ 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)) || + return Subtarget.isHVXVectorType(ty(Op), true) || llvm::any_of(Op.getNode()->ops(), [this] (SDValue V) { return Subtarget.isHVXVectorType(ty(V), true); |