diff options
author | Bill Wendling <isanbard@gmail.com> | 2008-11-25 08:12:19 +0000 |
---|---|---|
committer | Bill Wendling <isanbard@gmail.com> | 2008-11-25 08:12:19 +0000 |
commit | c0062fb7557c9f4eb66b7d8fa7b6b0c765e579b8 (patch) | |
tree | a3bad4a3ba9bd560ab22dd3cb74cbca2773ec693 | |
parent | 3b48501adc540c834fe33bf2695377c7e1189d3c (diff) |
Hacker's Delight says, "Signed integer overflow of addition occurs if and only
if the operands have the same sign and the sum has sign opposite to that of the
operands."
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60014 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 52 |
1 files changed, 48 insertions, 4 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 972e4ae8c2..5a6332c1ce 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -4170,7 +4170,53 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; } - case ISD::SADDO: + case ISD::SADDO: { + MVT VT = Node->getValueType(0); + switch (TLI.getOperationAction(Node->getOpcode(), VT)) { + default: assert(0 && "This action not supported for this op yet!"); + case TargetLowering::Custom: + Result = TLI.LowerOperation(Op, DAG); + if (Result.getNode()) break; + // FALLTHROUGH + case TargetLowering::Legal: { + SDValue LHS = LegalizeOp(Node->getOperand(0)); + SDValue RHS = LegalizeOp(Node->getOperand(1)); + + SDValue Sum = DAG.getNode(ISD::ADD, LHS.getValueType(), LHS, RHS); + MVT SType = Node->getValueType(0); + MVT OType = Node->getValueType(1); + + SDValue Zero = DAG.getConstant(0, OType); + + SDValue LHSPos = DAG.getSetCC(OType, LHS, Zero, ISD::SETGE); + SDValue RHSPos = DAG.getSetCC(OType, RHS, Zero, ISD::SETGE); + SDValue And1 = DAG.getNode(ISD::AND, OType, LHSPos, RHSPos); + + And1 = DAG.getNode(ISD::AND, OType, And1, + DAG.getSetCC(OType, Sum, Zero, ISD::SETLT)); + + SDValue LHSNeg = DAG.getSetCC(OType, LHS, Zero, ISD::SETLT); + SDValue RHSNeg = DAG.getSetCC(OType, RHS, Zero, ISD::SETLT); + SDValue And2 = DAG.getNode(ISD::AND, OType, LHSNeg, RHSNeg); + + And2 = DAG.getNode(ISD::AND, OType, And2, + DAG.getSetCC(OType, Sum, Zero, ISD::SETGE)); + + SDValue Cmp = DAG.getNode(ISD::OR, OType, And1, And2); + + MVT ValueVTs[] = { LHS.getValueType(), OType }; + SDValue Ops[] = { Sum, Cmp }; + + Result = DAG.getMergeValues(DAG.getVTList(&ValueVTs[0], 2), &Ops[0], 2); + SDNode *RNode = Result.getNode(); + DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 0), SDValue(RNode, 0)); + DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 1), SDValue(RNode, 1)); + break; + } + } + + break; + } case ISD::UADDO: { MVT VT = Node->getValueType(0); switch (TLI.getOperationAction(Node->getOpcode(), VT)) { @@ -4185,9 +4231,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { SDValue Sum = DAG.getNode(ISD::ADD, LHS.getValueType(), LHS, RHS); MVT OType = Node->getValueType(1); - SDValue Cmp = DAG.getSetCC(OType, Sum, LHS, - (Node->getOpcode() == ISD::SADDO) ? - ISD::SETLT : ISD::SETULT); + SDValue Cmp = DAG.getSetCC(OType, Sum, LHS, ISD::SETULT); MVT ValueVTs[] = { LHS.getValueType(), OType }; SDValue Ops[] = { Sum, Cmp }; |