static
SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp,
- SelectionDAG &DAG) {
+ SelectionDAG &DAG, const TargetLowering &TLI,
+ bool AfterLegalize) {
MVT VT = N->getValueType(0);
unsigned Opc = N->getOpcode();
bool isSlctCC = Slct.getOpcode() == ISD::SELECT_CC;
SDValue LHS = isSlctCC ? Slct.getOperand(2) : Slct.getOperand(1);
SDValue RHS = isSlctCC ? Slct.getOperand(3) : Slct.getOperand(2);
ISD::CondCode CC = ISD::SETCC_INVALID;
- if (isSlctCC)
+
+ if (isSlctCC) {
CC = cast<CondCodeSDNode>(Slct.getOperand(4))->get();
- else {
+ } else {
SDValue CCOp = Slct.getOperand(0);
if (CCOp.getOpcode() == ISD::SETCC)
CC = cast<CondCodeSDNode>(CCOp.getOperand(2))->get();
bool InvCC = false;
assert ((Opc == ISD::ADD || (Opc == ISD::SUB && Slct == N->getOperand(1))) &&
"Bad input!");
+
if (LHS.getOpcode() == ISD::Constant &&
- cast<ConstantSDNode>(LHS)->isNullValue())
+ cast<ConstantSDNode>(LHS)->isNullValue()) {
DoXform = true;
- else if (CC != ISD::SETCC_INVALID &&
- RHS.getOpcode() == ISD::Constant &&
- cast<ConstantSDNode>(RHS)->isNullValue()) {
+ } else if (CC != ISD::SETCC_INVALID &&
+ RHS.getOpcode() == ISD::Constant &&
+ cast<ConstantSDNode>(RHS)->isNullValue()) {
std::swap(LHS, RHS);
SDValue Op0 = Slct.getOperand(0);
- bool isInt = (isSlctCC ? Op0.getValueType() :
- Op0.getOperand(0).getValueType()).isInteger();
+ MVT OpVT = isSlctCC ? Op0.getValueType() :
+ Op0.getOperand(0).getValueType();
+ bool isInt = OpVT.isInteger();
CC = ISD::getSetCCInverse(CC, isInt);
+
+ if (AfterLegalize && !TLI.isCondCodeLegal(CC, OpVT))
+ return SDValue(); // Inverse operator isn't legal.
+
DoXform = true;
InvCC = true;
}
// fold (add (select cc, 0, c), x) -> (select cc, x, (add, x, c))
if (N0.getOpcode() == ISD::SELECT && N0.getNode()->hasOneUse()) {
- SDValue Result = combineSelectAndUse(N, N0, N1, DAG);
+ SDValue Result = combineSelectAndUse(N, N0, N1, DAG, TLI, AfterLegalize);
if (Result.getNode()) return Result;
}
if (N1.getOpcode() == ISD::SELECT && N1.getNode()->hasOneUse()) {
- SDValue Result = combineSelectAndUse(N, N1, N0, DAG);
+ SDValue Result = combineSelectAndUse(N, N1, N0, DAG, TLI, AfterLegalize);
if (Result.getNode()) return Result;
}
return N0.getOperand(0);
// fold (sub x, (select cc, 0, c)) -> (select cc, x, (sub, x, c))
if (N1.getOpcode() == ISD::SELECT && N1.getNode()->hasOneUse()) {
- SDValue Result = combineSelectAndUse(N, N1, N0, DAG);
+ SDValue Result = combineSelectAndUse(N, N1, N0, DAG, TLI, AfterLegalize);
if (Result.getNode()) return Result;
}
// If either operand of a sub is undef, the result is undef
if (LL == RL && LR == RR) {
bool isInteger = LL.getValueType().isInteger();
ISD::CondCode Result = ISD::getSetCCAndOperation(Op0, Op1, isInteger);
- if (Result != ISD::SETCC_INVALID)
+ if (Result != ISD::SETCC_INVALID &&
+ (!AfterLegalize || TLI.isCondCodeLegal(Result, LL.getValueType())))
return DAG.getSetCC(N0.getValueType(), LL, LR, Result);
}
}
if (LL == RL && LR == RR) {
bool isInteger = LL.getValueType().isInteger();
ISD::CondCode Result = ISD::getSetCCOrOperation(Op0, Op1, isInteger);
- if (Result != ISD::SETCC_INVALID)
+ if (Result != ISD::SETCC_INVALID &&
+ (!AfterLegalize || TLI.isCondCodeLegal(Result, LL.getValueType())))
return DAG.getSetCC(N0.getValueType(), LL, LR, Result);
}
}
SDValue RXOR = ReassociateOps(ISD::XOR, N0, N1);
if (RXOR.getNode() != 0)
return RXOR;
+
// fold !(x cc y) -> (x !cc y)
if (N1C && N1C->getAPIntValue() == 1 && isSetCCEquivalent(N0, LHS, RHS, CC)) {
bool isInt = LHS.getValueType().isInteger();
ISD::CondCode NotCC = ISD::getSetCCInverse(cast<CondCodeSDNode>(CC)->get(),
isInt);
- if (N0.getOpcode() == ISD::SETCC)
- return DAG.getSetCC(VT, LHS, RHS, NotCC);
- if (N0.getOpcode() == ISD::SELECT_CC)
- return DAG.getSelectCC(LHS, RHS, N0.getOperand(2),N0.getOperand(3),NotCC);
- assert(0 && "Unhandled SetCC Equivalent!");
- abort();
+
+ if (!AfterLegalize || TLI.isCondCodeLegal(NotCC, LHS.getValueType())) {
+ switch (N0.getOpcode()) {
+ default:
+ assert(0 && "Unhandled SetCC Equivalent!");
+ abort();
+ case ISD::SETCC:
+ return DAG.getSetCC(VT, LHS, RHS, NotCC);
+ case ISD::SELECT_CC:
+ return DAG.getSelectCC(LHS, RHS, N0.getOperand(2),
+ N0.getOperand(3), NotCC);
+ }
+ }
}
+
// fold (not (zext (setcc x, y))) -> (zext (not (setcc x, y)))
if (N1C && N1C->getAPIntValue() == 1 && N0.getOpcode() == ISD::ZERO_EXTEND &&
N0.getNode()->hasOneUse() &&
SDValue ShufMask = N->getOperand(2);
unsigned NumElts = ShufMask.getNumOperands();
+ SDValue N0 = N->getOperand(0);
+ SDValue N1 = N->getOperand(1);
+
+ assert(N0.getValueType().getVectorNumElements() == NumElts &&
+ "Vector shuffle must be normalized in DAG");
+
// If the shuffle mask is an identity operation on the LHS, return the LHS.
bool isIdentity = true;
for (unsigned i = 0; i != NumElts; ++i) {
}
}
- SDValue N0 = N->getOperand(0);
- SDValue N1 = N->getOperand(1);
// Normalize unary shuffle so the RHS is undef.
if (isUnary && VecNum == 1)
std::swap(N0, N1);
// Return the new VECTOR_SHUFFLE node.
MVT EVT = RHS.getValueType().getVectorElementType();
MVT VT = MVT::getVectorVT(EVT, NumElts);
+ MVT MaskVT = MVT::getVectorVT(TLI.getPointerTy(), NumElts);
std::vector<SDValue> Ops;
LHS = DAG.getNode(ISD::BIT_CONVERT, VT, LHS);
Ops.push_back(LHS);
std::vector<SDValue> ZeroOps(NumElts, DAG.getConstant(0, EVT));
Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, VT,
&ZeroOps[0], ZeroOps.size()));
- Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, VT,
+ Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
&IdxOps[0], IdxOps.size()));
SDValue Result = DAG.getNode(ISD::VECTOR_SHUFFLE, VT,
&Ops[0], Ops.size());