Hacker's Delight says, "Signed integer overflow of addition occurs if and only
authorBill Wendling <isanbard@gmail.com>
Tue, 25 Nov 2008 08:12:19 +0000 (08:12 +0000)
committerBill Wendling <isanbard@gmail.com>
Tue, 25 Nov 2008 08:12:19 +0000 (08:12 +0000)
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

lib/CodeGen/SelectionDAG/LegalizeDAG.cpp

index 972e4ae8c28f70ba28a69dda825e9bbae7d59047..5a6332c1cef99135e2f75ec797969b401679cd55 100644 (file)
@@ -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 };