summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp151
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);
+ });
+}
OpenPOWER on IntegriCloud