aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2008-11-25 08:12:19 +0000
committerBill Wendling <isanbard@gmail.com>2008-11-25 08:12:19 +0000
commitc0062fb7557c9f4eb66b7d8fa7b6b0c765e579b8 (patch)
treea3bad4a3ba9bd560ab22dd3cb74cbca2773ec693
parent3b48501adc540c834fe33bf2695377c7e1189d3c (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.cpp52
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 };