Index: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -2177,7 +2177,9 @@ case X86ISD::INC: case X86ISD::DEC: case X86ISD::ADD: + case X86ISD::ADC: case X86ISD::SUB: + case X86ISD::SBB: case X86ISD::AND: case X86ISD::OR: case X86ISD::XOR: @@ -2225,7 +2227,9 @@ break; } case X86ISD::ADD: + case X86ISD::ADC: case X86ISD::SUB: + case X86ISD::SBB: case X86ISD::AND: case X86ISD::OR: case X86ISD::XOR: { @@ -2234,9 +2238,15 @@ case X86ISD::ADD: return SelectOpcode(X86::ADD64mr, X86::ADD32mr, X86::ADD16mr, X86::ADD8mr); + case X86ISD::ADC: + return SelectOpcode(X86::ADC64mr, X86::ADC32mr, X86::ADC16mr, + X86::ADC8mr); case X86ISD::SUB: return SelectOpcode(X86::SUB64mr, X86::SUB32mr, X86::SUB16mr, X86::SUB8mr); + case X86ISD::SBB: + return SelectOpcode(X86::SBB64mr, X86::SBB32mr, X86::SBB16mr, + X86::SBB8mr); case X86ISD::AND: return SelectOpcode(X86::AND64mr, X86::AND32mr, X86::AND16mr, X86::AND8mr); @@ -2253,8 +2263,12 @@ switch (Opc) { case X86ISD::ADD: return SelectOpcode(X86::ADD64mi8, X86::ADD32mi8, X86::ADD16mi8, 0); + case X86ISD::ADC: + return SelectOpcode(X86::ADC64mi8, X86::ADC32mi8, X86::ADC16mi8, 0); case X86ISD::SUB: return SelectOpcode(X86::SUB64mi8, X86::SUB32mi8, X86::SUB16mi8, 0); + case X86ISD::SBB: + return SelectOpcode(X86::SBB64mi8, X86::SBB32mi8, X86::SBB16mi8, 0); case X86ISD::AND: return SelectOpcode(X86::AND64mi8, X86::AND32mi8, X86::AND16mi8, 0); case X86ISD::OR: @@ -2270,9 +2284,15 @@ case X86ISD::ADD: return SelectOpcode(X86::ADD64mi32, X86::ADD32mi, X86::ADD16mi, X86::ADD8mi); + case X86ISD::ADC: + return SelectOpcode(X86::ADC64mi32, X86::ADC32mi, X86::ADC16mi, + X86::ADC8mi); case X86ISD::SUB: return SelectOpcode(X86::SUB64mi32, X86::SUB32mi, X86::SUB16mi, X86::SUB8mi); + case X86ISD::SBB: + return SelectOpcode(X86::SBB64mi32, X86::SBB32mi, X86::SBB16mi, + X86::SBB8mi); case X86ISD::AND: return SelectOpcode(X86::AND64mi32, X86::AND32mi, X86::AND16mi, X86::AND8mi); @@ -2298,14 +2318,28 @@ // Check if we can shrink the operand enough to fit in an immediate (or // fit into a smaller immediate) by negating it and switching the // operation. - if ((Opc == X86ISD::ADD || Opc == X86ISD::SUB) && + if ((Opc == X86ISD::ADD || Opc == X86ISD::SUB || Opc == X86ISD::ADC || + Opc == X86ISD::SBB) && ((MemVT != MVT::i8 && OperandV.getMinSignedBits() > 8 && (-OperandV).getMinSignedBits() <= 8) || (MemVT == MVT::i64 && OperandV.getMinSignedBits() > 32 && (-OperandV).getMinSignedBits() <= 32)) && hasNoCarryFlagUses(StoredVal.getNode())) { OperandV = -OperandV; - Opc = Opc == X86ISD::ADD ? X86ISD::SUB : X86ISD::ADD; + switch (Opc) { + case X86ISD::ADD: + Opc = X86ISD::SUB; + break; + case X86ISD::SUB: + Opc = X86ISD::ADD; + break; + case X86ISD::ADC: + Opc = X86ISD::SUB; + break; + case X86ISD::SBB: + Opc = X86ISD::ADC; + break; + } } // First try to fit this into an Imm8 operand. If it doesn't fit, then try @@ -2320,10 +2354,21 @@ } } - const SDValue Ops[] = {Base, Scale, Index, Disp, - Segment, Operand, InputChain}; - Result = - CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other, Ops); + if (Opc == X86ISD::ADC || Opc == X86ISD::SBB) { + SDValue CopyTo = + CurDAG->getCopyToReg(InputChain, SDLoc(Node), X86::EFLAGS, + StoredVal.getOperand(2), SDValue()); + + const SDValue Ops[] = {Base, Scale, Index, Disp, + Segment, Operand, CopyTo, CopyTo.getValue(1)}; + Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other, + Ops); + } else { + const SDValue Ops[] = {Base, Scale, Index, Disp, + Segment, Operand, InputChain}; + Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other, + Ops); + } break; } default: Index: llvm/test/CodeGen/X86/addcarry.ll =================================================================== --- llvm/test/CodeGen/X86/addcarry.ll +++ llvm/test/CodeGen/X86/addcarry.ll @@ -172,8 +172,7 @@ ; CHECK-NEXT: movq %rdx, %rax ; CHECK-NEXT: mulq %rsi ; CHECK-NEXT: addq %rax, (%rdi) -; CHECK-NEXT: adcq 8(%rdi), %rdx -; CHECK-NEXT: movq %rdx, 8(%rdi) +; CHECK-NEXT: adcq %rdx, 8(%rdi) ; CHECK-NEXT: adcl $0, 16(%rdi) ; CHECK-NEXT: retq entry: