Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1870,6 +1870,17 @@ return CombineTo(N, DAG.getNode(ISD::ADD, DL, VT, N0, N1), DAG.getNode(ISD::CARRY_FALSE, DL, MVT::Glue)); + // (addc X, (adde Y, 0, Carry)) -> (adde X, Y, Carry) + // if Y + 1 cannot overflow. + if (N1.getOpcode() == ISD::ADDE && N1->hasOneUse() && + isNullConstant(N1.getOperand(1))) { + auto Y = N1.getOperand(0); + auto One = DAG.getConstant(1, DL, Y.getValueType()); + if (DAG.computeOverflowKind(Y, One) == SelectionDAG::OFK_Never) + return DAG.getNode(ISD::ADDE, DL, N->getVTList(), N0, Y, + N1.getOperand(2)); + } + return SDValue(); } Index: test/CodeGen/X86/adde-carry.ll =================================================================== --- test/CodeGen/X86/adde-carry.ll +++ test/CodeGen/X86/adde-carry.ll @@ -89,24 +89,21 @@ define %scalar @pr31719(%scalar* nocapture readonly %this, %scalar %arg.b) { ; CHECK-LABEL: pr31719: ; CHECK: # BB#0: # %entry -; CHECK-NEXT: addq (%rsi), %rdx +; CHECK-NEXT: addq 8(%rsi), %rcx ; CHECK-NEXT: sbbq %r10, %r10 ; CHECK-NEXT: andl $1, %r10d -; CHECK-NEXT: addq 8(%rsi), %rcx +; CHECK-NEXT: addq 16(%rsi), %r8 ; CHECK-NEXT: sbbq %rax, %rax ; CHECK-NEXT: andl $1, %eax -; CHECK-NEXT: addq %r10, %rcx -; CHECK-NEXT: adcq $0, %rax -; CHECK-NEXT: addq 16(%rsi), %r8 -; CHECK-NEXT: sbbq %r10, %r10 -; CHECK-NEXT: andl $1, %r10d ; CHECK-NEXT: addq 24(%rsi), %r9 -; CHECK-NEXT: addq %rax, %r8 -; CHECK-NEXT: adcq %r10, %r9 +; CHECK-NEXT: addq (%rsi), %rdx +; CHECK-NEXT: adcq $0, %rcx +; CHECK-NEXT: adcq %r8, %r10 +; CHECK-NEXT: adcq %r9, %rax ; CHECK-NEXT: movq %rdx, (%rdi) ; CHECK-NEXT: movq %rcx, 8(%rdi) -; CHECK-NEXT: movq %r8, 16(%rdi) -; CHECK-NEXT: movq %r9, 24(%rdi) +; CHECK-NEXT: movq %r10, 16(%rdi) +; CHECK-NEXT: movq %rax, 24(%rdi) ; CHECK-NEXT: movq %rdi, %rax ; CHECK-NEXT: retq entry: