canonicalize constants to the RHS of addc/adde. If nothing uses the carry out of
authorChris Lattner <sabre@nondot.org>
Sun, 4 Mar 2007 20:03:15 +0000 (20:03 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 4 Mar 2007 20:03:15 +0000 (20:03 +0000)
addc, turn it into add.

This allows us to compile:

long long test(long long A, unsigned B) {
  return (A + ((long long)B << 32)) & 123;
}

into:

_test:
        movl $123, %eax
        andl 4(%esp), %eax
        xorl %edx, %edx
        ret

instead of:
_test:
        xorl %edx, %edx
        movl %edx, %eax
        addl 4(%esp), %eax   ;; add of zero
        andl $123, %eax
        ret

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34909 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/DAGCombiner.cpp

index 79d9e79d2b303ad62960622cef2012adf69e8a3f..d48f4190340b9ff094239c12bcbde35d0b729ff7 100644 (file)
@@ -205,6 +205,8 @@ namespace {
     SDOperand visitTokenFactor(SDNode *N);
     SDOperand visitADD(SDNode *N);
     SDOperand visitSUB(SDNode *N);
+    SDOperand visitADDC(SDNode *N);
+    SDOperand visitADDE(SDNode *N);
     SDOperand visitMUL(SDNode *N);
     SDOperand visitSDIV(SDNode *N);
     SDOperand visitUDIV(SDNode *N);
@@ -502,6 +504,8 @@ SDOperand DAGCombiner::visit(SDNode *N) {
   case ISD::TokenFactor:        return visitTokenFactor(N);
   case ISD::ADD:                return visitADD(N);
   case ISD::SUB:                return visitSUB(N);
+  case ISD::ADDC:               return visitADDC(N);
+  case ISD::ADDE:               return visitADDE(N);
   case ISD::MUL:                return visitMUL(N);
   case ISD::SDIV:               return visitSDIV(N);
   case ISD::UDIV:               return visitUDIV(N);
@@ -740,6 +744,49 @@ SDOperand DAGCombiner::visitADD(SDNode *N) {
   return SDOperand();
 }
 
+SDOperand DAGCombiner::visitADDC(SDNode *N) {
+  SDOperand N0 = N->getOperand(0);
+  SDOperand N1 = N->getOperand(1);
+  ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
+  ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
+  MVT::ValueType VT = N0.getValueType();
+  
+  // If the flag result is dead, turn this into an ADD.
+  if (N->hasNUsesOfValue(0, 1))
+    return CombineTo(N, DAG.getNode(ISD::ADD, VT, N1, N0),
+                     SDOperand(N, 1));
+  
+  // canonicalize constant to RHS.
+  if (N0C && !N1C)
+    return DAG.getNode(ISD::ADDC, VT, N1, N0);
+  
+  // fold (add x, 0) -> x + no carry out
+  //if (N1C && N1C->isNullValue())
+  //  return N0;
+  
+  return SDOperand();
+}
+
+SDOperand DAGCombiner::visitADDE(SDNode *N) {
+  SDOperand N0 = N->getOperand(0);
+  SDOperand N1 = N->getOperand(1);
+  ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
+  ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
+  MVT::ValueType VT = N0.getValueType();
+  
+  // canonicalize constant to RHS
+  if (N0C && !N1C)
+    return DAG.getNode(ISD::ADDE, VT, N1, N0, N->getOperand(2));
+  
+  // fold (add x, 0) -> x
+  //if (N1C && N1C->isNullValue())
+  //  return N0;
+  
+  return SDOperand();
+}
+
+
+
 SDOperand DAGCombiner::visitSUB(SDNode *N) {
   SDOperand N0 = N->getOperand(0);
   SDOperand N1 = N->getOperand(1);