Index: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -232,6 +232,7 @@ SDValue visitTokenFactor(SDNode *N); SDValue visitMERGE_VALUES(SDNode *N); SDValue visitADD(SDNode *N); + SDValue visitADDLike(SDValue N0, SDValue N1, SDNode *LocReference); SDValue visitSUB(SDNode *N); SDValue visitADDC(SDNode *N); SDValue visitSUBC(SDNode *N); @@ -1782,6 +1783,19 @@ VT.isInteger() && DAG.haveNoCommonBitsSet(N0, N1)) return DAG.getNode(ISD::OR, DL, VT, N0, N1); + if (SDValue Combined = visitADDLike(N0, N1, N)) + return Combined; + + if (SDValue Combined = visitADDLike(N1, N0, N)) + return Combined; + + return SDValue(); +} + +SDValue DAGCombiner::visitADDLike(SDValue N0, SDValue N1, SDNode *LocReference) { + EVT VT = N0.getValueType(); + SDLoc DL(LocReference); + // fold (add x, shl(0 - y, n)) -> sub(x, shl(y, n)) if (N1.getOpcode() == ISD::SHL && N1.getOperand(0).getOpcode() == ISD::SUB && isNullConstantOrNullSplatConstant(N1.getOperand(0).getOperand(0))) @@ -1789,12 +1803,6 @@ DAG.getNode(ISD::SHL, DL, VT, N1.getOperand(0).getOperand(1), N1.getOperand(1))); - if (N0.getOpcode() == ISD::SHL && N0.getOperand(0).getOpcode() == ISD::SUB && - isNullConstantOrNullSplatConstant(N0.getOperand(0).getOperand(0))) - return DAG.getNode(ISD::SUB, DL, VT, N1, - DAG.getNode(ISD::SHL, DL, VT, - N0.getOperand(0).getOperand(1), - N0.getOperand(1))); if (N1.getOpcode() == ISD::AND) { SDValue AndOp0 = N1.getOperand(0); Index: llvm/trunk/test/CodeGen/X86/adde-carry.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/adde-carry.ll +++ llvm/trunk/test/CodeGen/X86/adde-carry.ll @@ -29,9 +29,8 @@ ; CHECK: # BB#0: # %entry ; CHECK-NEXT: addq %rdx, %rsi ; CHECK-NEXT: sbbq %rax, %rax -; CHECK-NEXT: andl $1, %eax -; CHECK-NEXT: addl %ecx, %eax -; CHECK-NEXT: movl %eax, (%rdi) +; CHECK-NEXT: subl %eax, %ecx +; CHECK-NEXT: movl %ecx, (%rdi) ; CHECK-NEXT: retq entry: %0 = zext i64 %a to i128 @@ -50,9 +49,8 @@ ; CHECK: # BB#0: # %entry ; CHECK-NEXT: addq %rdx, %rsi ; CHECK-NEXT: sbbq %rax, %rax -; CHECK-NEXT: andl $1, %eax -; CHECK-NEXT: addl %ecx, %eax -; CHECK-NEXT: movw %ax, (%rdi) +; CHECK-NEXT: subl %eax, %ecx +; CHECK-NEXT: movw %cx, (%rdi) ; CHECK-NEXT: retq entry: %0 = zext i64 %a to i128 @@ -71,9 +69,8 @@ ; CHECK: # BB#0: # %entry ; CHECK-NEXT: addq %rdx, %rsi ; CHECK-NEXT: sbbq %rax, %rax -; CHECK-NEXT: andl $1, %eax -; CHECK-NEXT: addl %ecx, %eax -; CHECK-NEXT: movb %al, (%rdi) +; CHECK-NEXT: subl %eax, %ecx +; CHECK-NEXT: movb %cl, (%rdi) ; CHECK-NEXT: retq entry: %0 = zext i64 %a to i128 @@ -169,9 +166,8 @@ ; CHECK-NEXT: movq %rax, (%rdi) ; CHECK-NEXT: addq 8(%rdi), %rdx ; CHECK-NEXT: sbbq %rax, %rax -; CHECK-NEXT: andl $1, %eax ; CHECK-NEXT: movq %rdx, 8(%rdi) -; CHECK-NEXT: addl %eax, 16(%rdi) +; CHECK-NEXT: subl %eax, 16(%rdi) ; CHECK-NEXT: retq entry: %0 = zext i64 %arg.a to i128