diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 109609b4369..a74d328e203 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -5186,6 +5186,8 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) { 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. @@ -5199,6 +5201,17 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) { Opc == X86ISD::UCOMI) { Cond = Cmp; addTest = false; + } else { + if (ConstantSDNode *CSDN = dyn_cast(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 @@ -6102,31 +6115,27 @@ SDValue X86TargetLowering::LowerCTTZ(SDValue Op, SelectionDAG &DAG) { 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; + // Also sets EFLAGS. + SDVTList VTs = DAG.getVTList(N->getValueType(0), MVT::i32); + SDValue Sum = DAG.getNode(ISD::ADD, VTs, LHS, RHS); - 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 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)); - 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(); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), SetCC); + return Sum; } SDValue X86TargetLowering::LowerCMP_SWAP(SDValue Op, SelectionDAG &DAG) { @@ -6143,7 +6152,7 @@ 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), @@ -6247,8 +6256,8 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { 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); } } diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 062ab2e6e07..4a854443284 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -593,7 +593,7 @@ namespace llvm { SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG); SDValue LowerCTLZ(SDValue Op, SelectionDAG &DAG); SDValue LowerCTTZ(SDValue Op, SelectionDAG &DAG); - SDValue LowerXADDO(SDValue Op, SelectionDAG &DAG, ISD::NodeType NTy); + SDValue LowerXADDO(SDValue Op, SelectionDAG &DAG); SDValue LowerCMP_SWAP(SDValue Op, SelectionDAG &DAG); SDValue LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG); diff --git a/test/CodeGen/X86/add-with-overflow.ll b/test/CodeGen/X86/add-with-overflow.ll index 84cc157a58e..8fab46cd629 100644 --- a/test/CodeGen/X86/add-with-overflow.ll +++ b/test/CodeGen/X86/add-with-overflow.ll @@ -1,6 +1,5 @@ ; RUN: llvm-as < %s | llc -march=x86 | grep {jo} | count 1 ; RUN: llvm-as < %s | llc -march=x86 | grep {jc} | count 1 -; XFAIL: * @ok = internal constant [4 x i8] c"%d\0A\00" @no = internal constant [4 x i8] c"no\0A\00"