Index: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3384,6 +3384,18 @@ } } + if (TLI.isOperationLegalOrCustom(ISD::ADDCARRY, VT)) { + // (sub Carry, X) -> (addcarry (sub 0, X), 0, Carry) + if (SDValue Carry = getAsCarry(TLI, N0)) { + SDValue X = N1; + SDValue Zero = DAG.getConstant(0, DL, VT); + SDValue NegX = DAG.getNode(ISD::SUB, DL, VT, Zero, X); + return DAG.getNode(ISD::ADDCARRY, DL, + DAG.getVTList(VT, Carry.getValueType()), NegX, Zero, + Carry); + } + } + return SDValue(); } Index: llvm/trunk/test/CodeGen/ARM/addsubcarry-promotion.ll =================================================================== --- llvm/trunk/test/CodeGen/ARM/addsubcarry-promotion.ll +++ llvm/trunk/test/CodeGen/ARM/addsubcarry-promotion.ll @@ -10,11 +10,11 @@ define void @fn1(i32 %a, i32 %b, i32 %c) local_unnamed_addr #0 { ; ARM-LABEL: fn1: ; ARM: @ %bb.0: @ %entry +; ARM-NEXT: rsb r2, r2, #0 ; ARM-NEXT: adds r0, r1, r0 -; ARM-NEXT: mov r3, #0 -; ARM-NEXT: adc r0, r3, #0 ; ARM-NEXT: movw r1, #65535 -; ARM-NEXT: sub r0, r0, r2 +; ARM-NEXT: sxth r2, r2 +; ARM-NEXT: adc r0, r2, #0 ; ARM-NEXT: uxth r0, r0 ; ARM-NEXT: cmp r0, r1 ; ARM-NEXT: bxeq lr @@ -24,11 +24,12 @@ ; ; THUMBV6M-LABEL: fn1: ; THUMBV6M: @ %bb.0: @ %entry +; THUMBV6M-NEXT: rsbs r2, r2, #0 +; THUMBV6M-NEXT: sxth r2, r2 ; THUMBV6M-NEXT: movs r3, #0 ; THUMBV6M-NEXT: adds r0, r1, r0 -; THUMBV6M-NEXT: adcs r3, r3 -; THUMBV6M-NEXT: subs r0, r3, r2 -; THUMBV6M-NEXT: uxth r0, r0 +; THUMBV6M-NEXT: adcs r3, r2 +; THUMBV6M-NEXT: uxth r0, r3 ; THUMBV6M-NEXT: ldr r1, .LCPI0_0 ; THUMBV6M-NEXT: cmp r0, r1 ; THUMBV6M-NEXT: beq .LBB0_2 @@ -44,11 +45,12 @@ ; ; THUMBV8M-BASE-LABEL: fn1: ; THUMBV8M-BASE: @ %bb.0: @ %entry +; THUMBV8M-BASE-NEXT: rsbs r2, r2, #0 +; THUMBV8M-BASE-NEXT: sxth r2, r2 ; THUMBV8M-BASE-NEXT: movs r3, #0 ; THUMBV8M-BASE-NEXT: adds r0, r1, r0 -; THUMBV8M-BASE-NEXT: adcs r3, r3 -; THUMBV8M-BASE-NEXT: subs r0, r3, r2 -; THUMBV8M-BASE-NEXT: uxth r0, r0 +; THUMBV8M-BASE-NEXT: adcs r3, r2 +; THUMBV8M-BASE-NEXT: uxth r0, r3 ; THUMBV8M-BASE-NEXT: movw r1, #65535 ; THUMBV8M-BASE-NEXT: cmp r0, r1 ; THUMBV8M-BASE-NEXT: beq .LBB0_2 @@ -60,11 +62,11 @@ ; ; THUMB-LABEL: fn1: ; THUMB: @ %bb.0: @ %entry +; THUMB-NEXT: rsbs r2, r2, #0 ; THUMB-NEXT: adds r0, r0, r1 -; THUMB-NEXT: mov.w r3, #0 -; THUMB-NEXT: adc r0, r3, #0 ; THUMB-NEXT: movw r1, #65535 -; THUMB-NEXT: subs r0, r0, r2 +; THUMB-NEXT: sxth r2, r2 +; THUMB-NEXT: adc r0, r2, #0 ; THUMB-NEXT: uxth r0, r0 ; THUMB-NEXT: cmp r0, r1 ; THUMB-NEXT: it eq Index: llvm/trunk/test/CodeGen/X86/subcarry.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/subcarry.ll +++ llvm/trunk/test/CodeGen/X86/subcarry.ll @@ -169,11 +169,11 @@ define i64 @sub_from_carry(i64 %x, i64 %y, i64* %valout, i64 %z) { ; CHECK-LABEL: sub_from_carry: ; CHECK: # %bb.0: -; CHECK-NEXT: xorl %eax, %eax +; CHECK-NEXT: movq %rcx, %rax +; CHECK-NEXT: negq %rax ; CHECK-NEXT: addq %rsi, %rdi -; CHECK-NEXT: setb %al ; CHECK-NEXT: movq %rdi, (%rdx) -; CHECK-NEXT: subq %rcx, %rax +; CHECK-NEXT: adcq $0, %rax ; CHECK-NEXT: retq %agg = call {i64, i1} @llvm.uadd.with.overflow(i64 %x, i64 %y) %val = extractvalue {i64, i1} %agg, 0