canonicalize constants to the RHS of addc/adde. If nothing uses the carry out of

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

llvm-svn: 34909
This commit is contained in:
Chris Lattner 2007-03-04 20:03:15 +00:00
parent 362621c7ae
commit e2e13caeb2
1 changed files with 47 additions and 0 deletions

View File

@ -205,6 +205,8 @@ namespace {
SDOperand visitTokenFactor(SDNode *N); SDOperand visitTokenFactor(SDNode *N);
SDOperand visitADD(SDNode *N); SDOperand visitADD(SDNode *N);
SDOperand visitSUB(SDNode *N); SDOperand visitSUB(SDNode *N);
SDOperand visitADDC(SDNode *N);
SDOperand visitADDE(SDNode *N);
SDOperand visitMUL(SDNode *N); SDOperand visitMUL(SDNode *N);
SDOperand visitSDIV(SDNode *N); SDOperand visitSDIV(SDNode *N);
SDOperand visitUDIV(SDNode *N); SDOperand visitUDIV(SDNode *N);
@ -502,6 +504,8 @@ SDOperand DAGCombiner::visit(SDNode *N) {
case ISD::TokenFactor: return visitTokenFactor(N); case ISD::TokenFactor: return visitTokenFactor(N);
case ISD::ADD: return visitADD(N); case ISD::ADD: return visitADD(N);
case ISD::SUB: return visitSUB(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::MUL: return visitMUL(N);
case ISD::SDIV: return visitSDIV(N); case ISD::SDIV: return visitSDIV(N);
case ISD::UDIV: return visitUDIV(N); case ISD::UDIV: return visitUDIV(N);
@ -740,6 +744,49 @@ SDOperand DAGCombiner::visitADD(SDNode *N) {
return SDOperand(); 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 DAGCombiner::visitSUB(SDNode *N) {
SDOperand N0 = N->getOperand(0); SDOperand N0 = N->getOperand(0);
SDOperand N1 = N->getOperand(1); SDOperand N1 = N->getOperand(1);