summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
diff options
context:
space:
mode:
authorDaniel Sanders <daniel.sanders@imgtec.com>2013-09-23 12:02:46 +0000
committerDaniel Sanders <daniel.sanders@imgtec.com>2013-09-23 12:02:46 +0000
commit7a289d0e39c764635c2a8eb44dd0d7c900237baa (patch)
treee4cc985f9f79d136beb03676793f24ff85ed5676 /llvm/lib/Target/Mips/MipsSEISelLowering.cpp
parent7f92aa687a90ae8b7ed1f1767ffa401d24d17096 (diff)
downloadbcm5719-llvm-7a289d0e39c764635c2a8eb44dd0d7c900237baa.tar.gz
bcm5719-llvm-7a289d0e39c764635c2a8eb44dd0d7c900237baa.zip
[mips][msa] Implemented build_vector using ldi, fill, and custom SelectionDAG nodes (VSPLAT and VSPLATD)
Note: There's a later patch on my branch that re-implements this to select build_vector without the custom SelectionDAG nodes. The future patch avoids the constant-folding problems stemming from the custom node (i.e. it doesn't need to re-implement all the DAG combines related to BUILD_VECTOR). Changes to MIPS specific SelectionDAG nodes: * Added VSPLAT This is a special case of BUILD_VECTOR that covers the case the BUILD_VECTOR is a splat operation. * Added VSPLATD This is a special case of VSPLAT that handles the cases when v2i64 is legal llvm-svn: 191191
Diffstat (limited to 'llvm/lib/Target/Mips/MipsSEISelLowering.cpp')
-rw-r--r--llvm/lib/Target/Mips/MipsSEISelLowering.cpp109
1 files changed, 109 insertions, 0 deletions
diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
index 879df6d1299..3b446c5a13a 100644
--- a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
@@ -147,6 +147,7 @@ llvm::createMipsSETargetLowering(MipsTargetMachine &TM) {
return new MipsSETargetLowering(TM);
}
+// Enable MSA support for the given integer type and Register class.
void MipsSETargetLowering::
addMSAIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) {
addRegisterClass(Ty, RC);
@@ -158,6 +159,7 @@ addMSAIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) {
setOperationAction(ISD::BITCAST, Ty, Legal);
setOperationAction(ISD::LOAD, Ty, Legal);
setOperationAction(ISD::STORE, Ty, Legal);
+ setOperationAction(ISD::BUILD_VECTOR, Ty, Custom);
setOperationAction(ISD::ADD, Ty, Legal);
setOperationAction(ISD::CTLZ, Ty, Legal);
@@ -170,6 +172,7 @@ addMSAIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) {
setOperationAction(ISD::UDIV, Ty, Legal);
}
+// Enable MSA support for the given floating-point type and Register class.
void MipsSETargetLowering::
addMSAFloatType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) {
addRegisterClass(Ty, RC);
@@ -224,6 +227,7 @@ SDValue MipsSETargetLowering::LowerOperation(SDValue Op,
case ISD::INTRINSIC_WO_CHAIN: return lowerINTRINSIC_WO_CHAIN(Op, DAG);
case ISD::INTRINSIC_W_CHAIN: return lowerINTRINSIC_W_CHAIN(Op, DAG);
case ISD::INTRINSIC_VOID: return lowerINTRINSIC_VOID(Op, DAG);
+ case ISD::BUILD_VECTOR: return lowerBUILD_VECTOR(Op, DAG);
}
return MipsTargetLowering::LowerOperation(Op, DAG);
@@ -921,6 +925,10 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
case Intrinsic::mips_fdiv_w:
case Intrinsic::mips_fdiv_d:
return lowerMSABinaryIntr(Op, DAG, ISD::FDIV);
+ case Intrinsic::mips_fill_b:
+ case Intrinsic::mips_fill_h:
+ case Intrinsic::mips_fill_w:
+ return lowerMSAUnaryIntr(Op, DAG, MipsISD::VSPLAT);
case Intrinsic::mips_flog2_w:
case Intrinsic::mips_flog2_d:
return lowerMSAUnaryIntr(Op, DAG, ISD::FLOG2);
@@ -936,6 +944,11 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
case Intrinsic::mips_fsub_w:
case Intrinsic::mips_fsub_d:
return lowerMSABinaryIntr(Op, DAG, ISD::FSUB);
+ case Intrinsic::mips_ldi_b:
+ case Intrinsic::mips_ldi_h:
+ case Intrinsic::mips_ldi_w:
+ case Intrinsic::mips_ldi_d:
+ return lowerMSAUnaryIntr(Op, DAG, MipsISD::VSPLAT);
case Intrinsic::mips_mulv_b:
case Intrinsic::mips_mulv_h:
case Intrinsic::mips_mulv_w:
@@ -1073,6 +1086,102 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_VOID(SDValue Op,
}
}
+/// \brief Check if the given BuildVectorSDNode is a splat.
+/// This method currently relies on DAG nodes being reused when equivalent,
+/// so it's possible for this to return false even when isConstantSplat returns
+/// true.
+static bool isSplatVector(const BuildVectorSDNode *N) {
+ EVT VT = N->getValueType(0);
+ assert(VT.isVector() && "Expected a vector type");
+
+ unsigned int nOps = N->getNumOperands();
+ assert(nOps > 1 && "isSplat has 0 or 1 sized build vector");
+
+ SDValue Operand0 = N->getOperand(0);
+
+ for (unsigned int i = 1; i < nOps; ++i) {
+ if (N->getOperand(i) != Operand0)
+ return false;
+ }
+
+ return true;
+}
+
+// Lowers ISD::BUILD_VECTOR into appropriate SelectionDAG nodes for the
+// backend.
+//
+// Lowers according to the following rules:
+// - Vectors of 128-bits may be legal subject to the other rules. Other sizes
+// are not legal.
+// - Non-constant splats are legal and are lowered to MipsISD::VSPLAT.
+// - Constant splats with an element size of 32-bits or less are legal and are
+// lowered to MipsISD::VSPLAT.
+// - Constant splats with an element size of 64-bits but whose value would fit
+// within a 10 bit immediate are legal and are lowered to MipsISD::VSPLATD.
+// - All other ISD::BUILD_VECTORS are not legal
+SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op,
+ SelectionDAG &DAG) const {
+ BuildVectorSDNode *Node = cast<BuildVectorSDNode>(Op);
+ EVT ResTy = Op->getValueType(0);
+ SDLoc DL(Op);
+ APInt SplatValue, SplatUndef;
+ unsigned SplatBitSize;
+ bool HasAnyUndefs;
+
+ if (!Subtarget->hasMSA() || !ResTy.is128BitVector())
+ return SDValue();
+
+ if (Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
+ HasAnyUndefs, 8,
+ !Subtarget->isLittle())) {
+ SDValue Result;
+ EVT TmpVecTy;
+ EVT ConstTy = MVT::i32;
+ unsigned SplatOp = MipsISD::VSPLAT;
+
+ switch (SplatBitSize) {
+ default:
+ return SDValue();
+ case 64:
+ TmpVecTy = MVT::v2i64;
+
+ // i64 is an illegal type on Mips32, but if it the constant fits into a
+ // signed 10-bit value then we can still handle it using VSPLATD and an
+ // i32 constant
+ if (HasMips64)
+ ConstTy = MVT::i64;
+ else if (isInt<10>(SplatValue.getSExtValue())) {
+ SplatValue = SplatValue.trunc(32);
+ SplatOp = MipsISD::VSPLATD;
+ } else
+ return SDValue();
+ break;
+ case 32:
+ TmpVecTy = MVT::v4i32;
+ break;
+ case 16:
+ TmpVecTy = MVT::v8i16;
+ SplatValue = SplatValue.sext(32);
+ break;
+ case 8:
+ TmpVecTy = MVT::v16i8;
+ SplatValue = SplatValue.sext(32);
+ break;
+ }
+
+ Result = DAG.getNode(SplatOp, DL, TmpVecTy,
+ DAG.getConstant(SplatValue, ConstTy));
+ if (ResTy != Result.getValueType())
+ Result = DAG.getNode(ISD::BITCAST, DL, ResTy, Result);
+
+ return Result;
+ }
+ else if (isSplatVector(Node))
+ return DAG.getNode(MipsISD::VSPLAT, DL, ResTy, Op->getOperand(0));
+
+ return SDValue();
+}
+
MachineBasicBlock * MipsSETargetLowering::
emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{
// $bb:
OpenPOWER on IntegriCloud