setTargetDAGCombine(ISD::AND);
setTargetDAGCombine(ISD::SRA);
+ setTargetDAGCombine(ISD::VSELECT);
setTargetDAGCombine(ISD::XOR);
}
setOperationAction(ISD::SRL, Ty, Legal);
setOperationAction(ISD::SUB, Ty, Legal);
setOperationAction(ISD::UDIV, Ty, Legal);
+ setOperationAction(ISD::VSELECT, Ty, Legal);
setOperationAction(ISD::XOR, Ty, Legal);
setOperationAction(ISD::SETCC, Ty, Legal);
setOperationAction(ISD::FRINT, Ty, Legal);
setOperationAction(ISD::FSQRT, Ty, Legal);
setOperationAction(ISD::FSUB, Ty, Legal);
+ setOperationAction(ISD::VSELECT, Ty, Legal);
setOperationAction(ISD::SETCC, Ty, Legal);
setCondCodeAction(ISD::SETOGE, Ty, Expand);
static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) {
EVT Ty = N->getValueType(0);
- if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8))
- return SDValue();
+ if (Ty.is128BitVector() && Ty.isInteger()) {
+ // Try the following combines:
+ // (vselect (setcc $a, $b, SETLT), $b, $a)) -> (vsmax $a, $b)
+ // (vselect (setcc $a, $b, SETLE), $b, $a)) -> (vsmax $a, $b)
+ // (vselect (setcc $a, $b, SETLT), $a, $b)) -> (vsmin $a, $b)
+ // (vselect (setcc $a, $b, SETLE), $a, $b)) -> (vsmin $a, $b)
+ // (vselect (setcc $a, $b, SETULT), $b, $a)) -> (vumax $a, $b)
+ // (vselect (setcc $a, $b, SETULE), $b, $a)) -> (vumax $a, $b)
+ // (vselect (setcc $a, $b, SETULT), $a, $b)) -> (vumin $a, $b)
+ // (vselect (setcc $a, $b, SETULE), $a, $b)) -> (vumin $a, $b)
+ // SETGT/SETGE/SETUGT/SETUGE variants of these will show up initially but
+ // will be expanded to equivalent SETLT/SETLE/SETULT/SETULE versions by the
+ // legalizer.
+ SDValue Op0 = N->getOperand(0);
- SDValue SetCC = N->getOperand(0);
+ if (Op0->getOpcode() != ISD::SETCC)
+ return SDValue();
- if (SetCC.getOpcode() != MipsISD::SETCC_DSP)
- return SDValue();
+ ISD::CondCode CondCode = cast<CondCodeSDNode>(Op0->getOperand(2))->get();
+ bool Signed;
+
+ if (CondCode == ISD::SETLT || CondCode == ISD::SETLE)
+ Signed = true;
+ else if (CondCode == ISD::SETULT || CondCode == ISD::SETULE)
+ Signed = false;
+ else
+ return SDValue();
+
+ SDValue Op1 = N->getOperand(1);
+ SDValue Op2 = N->getOperand(2);
+ SDValue Op0Op0 = Op0->getOperand(0);
+ SDValue Op0Op1 = Op0->getOperand(1);
+
+ if (Op1 == Op0Op0 && Op2 == Op0Op1)
+ return DAG.getNode(Signed ? MipsISD::VSMIN : MipsISD::VUMIN, SDLoc(N),
+ Ty, Op1, Op2);
+ else if (Op1 == Op0Op1 && Op2 == Op0Op0)
+ return DAG.getNode(Signed ? MipsISD::VSMAX : MipsISD::VUMAX, SDLoc(N),
+ Ty, Op1, Op2);
+ } else if ((Ty == MVT::v2i16) || (Ty == MVT::v4i8)) {
+ SDValue SetCC = N->getOperand(0);
+
+ if (SetCC.getOpcode() != MipsISD::SETCC_DSP)
+ return SDValue();
- return DAG.getNode(MipsISD::SELECT_CC_DSP, SDLoc(N), Ty,
- SetCC.getOperand(0), SetCC.getOperand(1), N->getOperand(1),
- N->getOperand(2), SetCC.getOperand(2));
+ return DAG.getNode(MipsISD::SELECT_CC_DSP, SDLoc(N), Ty,
+ SetCC.getOperand(0), SetCC.getOperand(1),
+ N->getOperand(1), N->getOperand(2), SetCC.getOperand(2));
+ }
+
+ return SDValue();
}
static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG,
lowerMSASplatImm(Op, 2, DAG));
case Intrinsic::mips_and_v:
return lowerMSABinaryIntr(Op, DAG, ISD::AND);
+ case Intrinsic::mips_andi_b:
+ return lowerMSABinaryImmIntr(Op, DAG, ISD::AND,
+ lowerMSASplatImm(Op, 2, DAG));
case Intrinsic::mips_bnz_b:
case Intrinsic::mips_bnz_h:
case Intrinsic::mips_bnz_w:
return lowerMSABranchIntr(Op, DAG, MipsISD::VALL_NONZERO);
case Intrinsic::mips_bnz_v:
return lowerMSABranchIntr(Op, DAG, MipsISD::VANY_NONZERO);
+ case Intrinsic::mips_bsel_v:
+ return DAG.getNode(ISD::VSELECT, SDLoc(Op), Op->getValueType(0),
+ Op->getOperand(1), Op->getOperand(2),
+ Op->getOperand(3));
+ case Intrinsic::mips_bseli_b:
+ return DAG.getNode(ISD::VSELECT, SDLoc(Op), Op->getValueType(0),
+ Op->getOperand(1), Op->getOperand(2),
+ lowerMSASplatImm(Op, 3, DAG));
case Intrinsic::mips_bz_b:
case Intrinsic::mips_bz_h:
case Intrinsic::mips_bz_w:
case Intrinsic::mips_ldi_w:
case Intrinsic::mips_ldi_d:
return lowerMSAUnaryIntr(Op, DAG, MipsISD::VSPLAT);
+ case Intrinsic::mips_max_s_b:
+ case Intrinsic::mips_max_s_h:
+ case Intrinsic::mips_max_s_w:
+ case Intrinsic::mips_max_s_d:
+ return lowerMSABinaryIntr(Op, DAG, MipsISD::VSMAX);
+ case Intrinsic::mips_max_u_b:
+ case Intrinsic::mips_max_u_h:
+ case Intrinsic::mips_max_u_w:
+ case Intrinsic::mips_max_u_d:
+ return lowerMSABinaryIntr(Op, DAG, MipsISD::VUMAX);
+ case Intrinsic::mips_maxi_s_b:
+ case Intrinsic::mips_maxi_s_h:
+ case Intrinsic::mips_maxi_s_w:
+ case Intrinsic::mips_maxi_s_d:
+ return lowerMSABinaryImmIntr(Op, DAG, MipsISD::VSMAX,
+ lowerMSASplatImm(Op, 2, DAG));
+ case Intrinsic::mips_maxi_u_b:
+ case Intrinsic::mips_maxi_u_h:
+ case Intrinsic::mips_maxi_u_w:
+ case Intrinsic::mips_maxi_u_d:
+ return lowerMSABinaryImmIntr(Op, DAG, MipsISD::VUMAX,
+ lowerMSASplatImm(Op, 2, DAG));
+ case Intrinsic::mips_min_s_b:
+ case Intrinsic::mips_min_s_h:
+ case Intrinsic::mips_min_s_w:
+ case Intrinsic::mips_min_s_d:
+ return lowerMSABinaryIntr(Op, DAG, MipsISD::VSMIN);
+ case Intrinsic::mips_min_u_b:
+ case Intrinsic::mips_min_u_h:
+ case Intrinsic::mips_min_u_w:
+ case Intrinsic::mips_min_u_d:
+ return lowerMSABinaryIntr(Op, DAG, MipsISD::VUMIN);
+ case Intrinsic::mips_mini_s_b:
+ case Intrinsic::mips_mini_s_h:
+ case Intrinsic::mips_mini_s_w:
+ case Intrinsic::mips_mini_s_d:
+ return lowerMSABinaryImmIntr(Op, DAG, MipsISD::VSMIN,
+ lowerMSASplatImm(Op, 2, DAG));
+ case Intrinsic::mips_mini_u_b:
+ case Intrinsic::mips_mini_u_h:
+ case Intrinsic::mips_mini_u_w:
+ case Intrinsic::mips_mini_u_d:
+ return lowerMSABinaryImmIntr(Op, DAG, MipsISD::VUMIN,
+ lowerMSASplatImm(Op, 2, DAG));
case Intrinsic::mips_mulv_b:
case Intrinsic::mips_mulv_h:
case Intrinsic::mips_mulv_w:
SDValue Res = lowerMSABinaryIntr(Op, DAG, ISD::OR);
return DAG.getNOT(SDLoc(Op), Res, Res->getValueType(0));
}
+ case Intrinsic::mips_nori_b: {
+ SDValue Res = lowerMSABinaryImmIntr(Op, DAG, ISD::OR,
+ lowerMSASplatImm(Op, 2, DAG));
+ return DAG.getNOT(SDLoc(Op), Res, Res->getValueType(0));
+ }
case Intrinsic::mips_or_v:
return lowerMSABinaryIntr(Op, DAG, ISD::OR);
+ case Intrinsic::mips_ori_b:
+ return lowerMSABinaryImmIntr(Op, DAG, ISD::OR,
+ lowerMSASplatImm(Op, 2, DAG));
case Intrinsic::mips_pcnt_b:
case Intrinsic::mips_pcnt_h:
case Intrinsic::mips_pcnt_w:
lowerMSASplatImm(Op, 2, DAG));
case Intrinsic::mips_xor_v:
return lowerMSABinaryIntr(Op, DAG, ISD::XOR);
+ case Intrinsic::mips_xori_b:
+ return lowerMSABinaryImmIntr(Op, DAG, ISD::XOR,
+ lowerMSASplatImm(Op, 2, DAG));
}
}