diff options
Diffstat (limited to 'lib/Target/Mips/MipsSEISelLowering.cpp')
-rw-r--r-- | lib/Target/Mips/MipsSEISelLowering.cpp | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index 50a41d3afa..2dcc69c557 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -1288,6 +1288,39 @@ lowerMSASplatImm(SDValue Op, unsigned ImmOp, SelectionDAG &DAG) { Op->getOperand(ImmOp), DAG); } +static SDValue lowerMSABinaryBitImmIntr(SDValue Op, SelectionDAG &DAG, + unsigned Opc, SDValue Imm, + bool BigEndian) { + EVT VecTy = Op->getValueType(0); + SDValue Exp2Imm; + SDLoc DL(Op); + + // The DAG Combiner can't constant fold bitcasted vectors so we must do it + // here. + if (VecTy == MVT::v2i64) { + if (ConstantSDNode *CImm = dyn_cast<ConstantSDNode>(Imm)) { + APInt BitImm = APInt(64, 1) << CImm->getAPIntValue(); + + SDValue BitImmHiOp = DAG.getConstant(BitImm.lshr(32).trunc(32), MVT::i32); + SDValue BitImmOp = DAG.getConstant(BitImm.trunc(32), MVT::i32); + Exp2Imm = DAG.getNode(ISD::BITCAST, DL, MVT::v2i64, + DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v4i32, + BitImmHiOp, BitImmOp, + BitImmHiOp, BitImmOp)); + } + } + + if (Exp2Imm.getNode() == NULL) { + // We couldnt constant fold, do a vector shift instead + SDValue One = lowerMSASplatImm(DL, VecTy, DAG.getConstant(1, MVT::i32), + DAG); + Exp2Imm = lowerMSASplatImm(DL, VecTy, Imm, DAG); + Exp2Imm = DAG.getNode(ISD::SHL, DL, VecTy, One, Exp2Imm); + } + + return DAG.getNode(Opc, DL, VecTy, Op->getOperand(1), Exp2Imm); +} + SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); @@ -1383,6 +1416,24 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), lowerMSASplatImm(Op, 3, DAG), Op->getOperand(1), Op->getOperand(2)); + case Intrinsic::mips_bneg_b: + case Intrinsic::mips_bneg_h: + case Intrinsic::mips_bneg_w: + case Intrinsic::mips_bneg_d: { + EVT VecTy = Op->getValueType(0); + SDValue One = lowerMSASplatImm(DL, VecTy, DAG.getConstant(1, MVT::i32), + DAG); + + return DAG.getNode(ISD::XOR, DL, VecTy, Op->getOperand(1), + DAG.getNode(ISD::SHL, DL, VecTy, One, + Op->getOperand(2))); + } + case Intrinsic::mips_bnegi_b: + case Intrinsic::mips_bnegi_h: + case Intrinsic::mips_bnegi_w: + case Intrinsic::mips_bnegi_d: + return lowerMSABinaryBitImmIntr(Op, DAG, ISD::XOR, Op->getOperand(2), + !Subtarget->isLittle()); case Intrinsic::mips_bnz_b: case Intrinsic::mips_bnz_h: case Intrinsic::mips_bnz_w: @@ -1400,6 +1451,24 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), Op->getOperand(1), Op->getOperand(2), lowerMSASplatImm(Op, 3, DAG)); + case Intrinsic::mips_bset_b: + case Intrinsic::mips_bset_h: + case Intrinsic::mips_bset_w: + case Intrinsic::mips_bset_d: { + EVT VecTy = Op->getValueType(0); + SDValue One = lowerMSASplatImm(DL, VecTy, DAG.getConstant(1, MVT::i32), + DAG); + + return DAG.getNode(ISD::OR, DL, VecTy, Op->getOperand(1), + DAG.getNode(ISD::SHL, DL, VecTy, One, + Op->getOperand(2))); + } + case Intrinsic::mips_bseti_b: + case Intrinsic::mips_bseti_h: + case Intrinsic::mips_bseti_w: + case Intrinsic::mips_bseti_d: + return lowerMSABinaryBitImmIntr(Op, DAG, ISD::OR, Op->getOperand(2), + !Subtarget->isLittle()); case Intrinsic::mips_bz_b: case Intrinsic::mips_bz_h: case Intrinsic::mips_bz_w: |