Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2892,6 +2892,17 @@ if (SDValue Combined = visitADDCARRYLike(N1, N0, CarryIn, N)) return Combined; + // We want to avoid useless duplication. + // TODO: This is done automatically for binary operations. As ADDCARRY is + // not a binary operation, this is not really possible to leverage this + // existing mechanism for it. However, if more operations require the same + // deduplication logic, then it may be worth generalize. + SDValue Ops[] = {N1, N0, CarryIn}; + SDNode *CSENode = DAG.getNodeIfExists(ISD::ADDCARRY, N->getVTList(), Ops, + N->getFlags()); + if (CSENode) + return SDValue(CSENode, 0); + return SDValue(); } Index: test/CodeGen/X86/addcarry.ll =================================================================== --- test/CodeGen/X86/addcarry.ll +++ test/CodeGen/X86/addcarry.ll @@ -312,31 +312,15 @@ define %S @readd(%S* nocapture readonly %this, %S %arg.b) { ; CHECK-LABEL: readd: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: pushq %rbx -; CHECK-NEXT: .cfi_def_cfa_offset 16 -; CHECK-NEXT: .cfi_offset %rbx, -16 ; CHECK-NEXT: movq %rdi, %rax -; CHECK-NEXT: movq (%rsi), %r10 -; CHECK-NEXT: movq %rdx, %rdi -; CHECK-NEXT: addq %r10, %rdi -; CHECK-NEXT: movq 8(%rsi), %rdi -; CHECK-NEXT: movq 16(%rsi), %r11 -; CHECK-NEXT: movq %rcx, %rbx -; CHECK-NEXT: adcq %rdi, %rbx -; CHECK-NEXT: addq %r10, %rdx -; CHECK-NEXT: adcq %rdi, %rcx -; CHECK-NEXT: setb %cl -; CHECK-NEXT: movq %r8, %rdi -; CHECK-NEXT: adcq %r11, %rdi -; CHECK-NEXT: addb $255, %cl -; CHECK-NEXT: adcq %r11, %r8 +; CHECK-NEXT: addq (%rsi), %rdx +; CHECK-NEXT: adcq 8(%rsi), %rcx +; CHECK-NEXT: adcq 16(%rsi), %r8 ; CHECK-NEXT: adcq 24(%rsi), %r9 -; CHECK-NEXT: movq %rdx, (%rax) -; CHECK-NEXT: movq %rbx, 8(%rax) -; CHECK-NEXT: movq %rdi, 16(%rax) -; CHECK-NEXT: movq %r9, 24(%rax) -; CHECK-NEXT: popq %rbx -; CHECK-NEXT: .cfi_def_cfa_offset 8 +; 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: retq entry: %0 = extractvalue %S %arg.b, 0 @@ -398,16 +382,13 @@ define i128 @addcarry_to_subcarry(i64 %a, i64 %b) { ; CHECK-LABEL: addcarry_to_subcarry: ; CHECK: # %bb.0: -; CHECK-NEXT: notq %rsi -; CHECK-NEXT: movb $1, %al -; CHECK-NEXT: addb $-1, %al -; CHECK-NEXT: movq %rdi, %rax -; CHECK-NEXT: adcq %rsi, %rax -; CHECK-NEXT: setb %cl -; CHECK-NEXT: movq %rdi, %rax -; CHECK-NEXT: adcq %rsi, %rax -; CHECK-NEXT: addb $255, %cl -; CHECK-NEXT: adcq %rdi, %rsi +; CHECK-NEXT: movq %rsi, %rax +; CHECK-NEXT: notq %rax +; CHECK-NEXT: movb $1, %cl +; CHECK-NEXT: addb $-1, %cl +; CHECK-NEXT: movq %rdi, %rcx +; CHECK-NEXT: adcq %rax, %rcx +; CHECK-NEXT: adcq %rdi, %rax ; CHECK-NEXT: setb %cl ; CHECK-NEXT: movzbl %cl, %edx ; CHECK-NEXT: retq Index: test/CodeGen/X86/subcarry.ll =================================================================== --- test/CodeGen/X86/subcarry.ll +++ test/CodeGen/X86/subcarry.ll @@ -90,44 +90,24 @@ define %S @sub(%S* nocapture readonly %this, %S %arg.b) local_unnamed_addr { ; CHECK-LABEL: sub: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: pushq %r14 -; CHECK-NEXT: .cfi_def_cfa_offset 16 -; CHECK-NEXT: pushq %rbx -; CHECK-NEXT: .cfi_def_cfa_offset 24 -; CHECK-NEXT: .cfi_offset %rbx, -24 -; CHECK-NEXT: .cfi_offset %r14, -16 ; CHECK-NEXT: movq %rdi, %rax -; CHECK-NEXT: movq %rdx, %rdi -; CHECK-NEXT: notq %rdi -; CHECK-NEXT: movq (%rsi), %r10 -; CHECK-NEXT: movq 8(%rsi), %r11 -; CHECK-NEXT: movb $1, %bl -; CHECK-NEXT: addb $-1, %bl -; CHECK-NEXT: adcq %r10, %rdi +; CHECK-NEXT: movq (%rsi), %rdi +; CHECK-NEXT: movq %rdi, %r10 +; CHECK-NEXT: subq %rdx, %r10 +; CHECK-NEXT: notq %rdx +; CHECK-NEXT: movb $1, %r11b +; CHECK-NEXT: addb $-1, %r11b +; CHECK-NEXT: adcq %rdi, %rdx ; CHECK-NEXT: notq %rcx -; CHECK-NEXT: setb %bl -; CHECK-NEXT: movq %rcx, %rdi -; CHECK-NEXT: adcq %r11, %rdi -; CHECK-NEXT: movq 16(%rsi), %r14 -; CHECK-NEXT: addb $255, %bl -; CHECK-NEXT: adcq %r11, %rcx +; CHECK-NEXT: adcq 8(%rsi), %rcx ; CHECK-NEXT: notq %r8 -; CHECK-NEXT: setb %cl -; CHECK-NEXT: movq %r8, %rbx -; CHECK-NEXT: adcq %r14, %rbx -; CHECK-NEXT: addb $255, %cl -; CHECK-NEXT: adcq %r14, %r8 +; CHECK-NEXT: adcq 16(%rsi), %r8 ; CHECK-NEXT: notq %r9 ; CHECK-NEXT: adcq 24(%rsi), %r9 -; CHECK-NEXT: subq %rdx, %r10 ; CHECK-NEXT: movq %r10, (%rax) -; CHECK-NEXT: movq %rdi, 8(%rax) -; CHECK-NEXT: movq %rbx, 16(%rax) +; CHECK-NEXT: movq %rcx, 8(%rax) +; CHECK-NEXT: movq %r8, 16(%rax) ; CHECK-NEXT: movq %r9, 24(%rax) -; CHECK-NEXT: popq %rbx -; CHECK-NEXT: .cfi_def_cfa_offset 16 -; CHECK-NEXT: popq %r14 -; CHECK-NEXT: .cfi_def_cfa_offset 8 ; CHECK-NEXT: retq entry: %0 = extractvalue %S %arg.b, 0