Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1970,6 +1970,28 @@ return SDValue(); } +static SDValue getAsCarry(SDValue V) { + // First, peel away truncation and and due to legalization. + while (V.getOpcode() == ISD::TRUNCATE || + V.getOpcode() == ISD::ZERO_EXTEND || + V.getOpcode() == ISD::SIGN_EXTEND || + V.getOpcode() == ISD::ANY_EXTEND || + (V.getOpcode() == ISD::AND && isOneConstant(V.getOperand(1)))) + V = V.getOperand(0); + + // If this is a carry, return. + if (V.getResNo() != 1) + return SDValue(); + + if (V.getOpcode() == ISD::ADDCARRY || + V.getOpcode() == ISD::SUBCARRY || + V.getOpcode() == ISD::UADDO || + V.getOpcode() == ISD::USUBO) + return V; + + return SDValue(); +} + SDValue DAGCombiner::visitADDLike(SDValue N0, SDValue N1, SDNode *LocReference) { EVT VT = N0.getValueType(); SDLoc DL(LocReference); @@ -2017,6 +2039,12 @@ return DAG.getNode(ISD::ADDCARRY, DL, N1->getVTList(), N0, N1.getOperand(0), N1.getOperand(2)); + // (add X, Carry) -> (addcarry X, 0, Carry) + if (auto Carry = getAsCarry(N1)) + return DAG.getNode(ISD::ADDCARRY, DL, + DAG.getVTList(VT, Carry.getValueType()), N0, + DAG.getConstant(0, DL, VT), Carry); + return SDValue(); } @@ -2100,6 +2128,11 @@ N1.getOperand(2)); } + // (uaddo X, Carry) -> (addcarry X, 0, Carry) + if (auto Carry = getAsCarry(N1)) + return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(), N0, + DAG.getConstant(0, SDLoc(N), N0.getValueType()), Carry); + return SDValue(); } Index: test/CodeGen/X86/add-of-carry.ll =================================================================== --- test/CodeGen/X86/add-of-carry.ll +++ test/CodeGen/X86/add-of-carry.ll @@ -9,9 +9,11 @@ define i32 @test1(i32 %sum, i32 %x) nounwind readnone ssp { ; CHECK-LABEL: test1: ; CHECK: # BB#0: +; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx ; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax -; CHECK-NEXT: addl {{[0-9]+}}(%esp), %eax -; CHECK-NEXT: adcl $0, %eax +; CHECK-NEXT: movl %eax, %edx +; CHECK-NEXT: addl %ecx, %edx +; CHECK-NEXT: adcl %ecx, %eax ; CHECK-NEXT: retl %add4 = add i32 %x, %sum %cmp = icmp ult i32 %add4, %x Index: test/CodeGen/X86/addcarry.ll =================================================================== --- test/CodeGen/X86/addcarry.ll +++ test/CodeGen/X86/addcarry.ll @@ -190,9 +190,9 @@ define i64 @shiftadd(i64 %a, i64 %b, i64 %c, i64 %d) { ; CHECK-LABEL: shiftadd: ; CHECK: # BB#0: # %entry -; CHECK-NEXT: leaq (%rdx,%rcx), %rax ; CHECK-NEXT: addq %rsi, %rdi -; CHECK-NEXT: adcq $0, %rax +; CHECK-NEXT: adcq %rcx, %rdx +; CHECK-NEXT: movq %rdx, %rax ; CHECK-NEXT: retq entry: %0 = zext i64 %a to i128