if (Cond.getOpcode() == ISD::SETCC)
Cond = LowerSETCC(Cond, DAG);
+ else if (Cond.getOpcode() == ISD::SADDO || Cond.getOpcode() == ISD::UADDO)
+ Cond = LowerXADDO(Cond, DAG);
// If condition flag is set by a X86ISD::CMP, then use it as the condition
// setting operand in place of the X86ISD::SETCC.
Opc == X86ISD::UCOMI) {
Cond = Cmp;
addTest = false;
+ } else {
+ if (ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(CC.getNode())) {
+ switch (CSDN->getZExtValue()) {
+ default: break;
+ case X86::COND_O:
+ case X86::COND_C:
+ Cond = Cond.getNode()->getOperand(1);
+ addTest = false;
+ break;
+ }
+ }
}
// Also, recognize the pattern generated by an FCMP_UNE. We can emit
// two branches instead of an explicit OR instruction with a
return Op;
}
-SDValue X86TargetLowering::LowerXADDO(SDValue Op, SelectionDAG &DAG,
- ISD::NodeType NTy) {
-#if 0
- // FIXME: Lowering XADDO should use BRCOND as well.
+SDValue X86TargetLowering::LowerXADDO(SDValue Op, SelectionDAG &DAG) {
+ // Lower the "add with overflow" instruction into a regular "add" plus a
+ // "setcc" instruction that checks the overflow flag. The "brcond" lowering
+ // looks for this combo and may remove the "setcc" instruction if the "setcc"
+ // has only one use.
SDNode *N = Op.getNode();
+ SDValue LHS = N->getOperand(0);
+ SDValue RHS = N->getOperand(1);
- for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
- SDNode *UseNode = *I;
-
- if (UseNode->getOpcode() == ISD::BRCOND) {
- // Lower a branch on the overflow/carry flag into a "JO"/"JC"
- // instruction. Convert the addition into an actual addition, not just a
- // pseudo node.
- SDValue LHS = N->getOperand(0);
- SDValue RHS = N->getOperand(1);
- SDValue Sum = DAG.getNode(ISD::ADD, LHS.getValueType(), LHS, RHS);
-
- SDValue Ops[] = { UseNode->getOperand(2), UseNode->getOperand(0) };
- DAG.SelectNodeTo(UseNode, (NTy == ISD::SADDO) ? X86::JO : X86::JC,
- MVT::Other, Ops, 2);
- return Sum;
- }
- }
-#endif
- return SDValue();
+ // Also sets EFLAGS.
+ SDVTList VTs = DAG.getVTList(N->getValueType(0), MVT::i32);
+ SDValue Sum = DAG.getNode(ISD::ADD, VTs, LHS, RHS);
+
+ SDValue SetCC =
+ DAG.getNode(X86ISD::SETCC, N->getValueType(1),
+ DAG.getConstant((Op.getOpcode() == ISD::SADDO) ?
+ X86::COND_O : X86::COND_C,
+ MVT::i32), SDValue(Sum.getNode(), 1));
+
+ DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), SetCC);
+ return Sum;
}
SDValue X86TargetLowering::LowerCMP_SWAP(SDValue Op, SelectionDAG &DAG) {
assert(Subtarget->is64Bit() && "Node not type legal!");
Reg = X86::RAX; size = 8;
break;
- };
+ }
SDValue cpIn = DAG.getCopyToReg(Op.getOperand(0), Reg,
Op.getOperand(2), SDValue());
SDValue Ops[] = { cpIn.getValue(0),
case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG);
case ISD::CTLZ: return LowerCTLZ(Op, DAG);
case ISD::CTTZ: return LowerCTTZ(Op, DAG);
- case ISD::SADDO: return LowerXADDO(Op, DAG, ISD::SADDO);
- case ISD::UADDO: return LowerXADDO(Op, DAG, ISD::UADDO);
+ case ISD::SADDO: return LowerXADDO(Op, DAG);
+ case ISD::UADDO: return LowerXADDO(Op, DAG);
case ISD::READCYCLECOUNTER: return LowerREADCYCLECOUNTER(Op, DAG);
}
}