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); @@ -2320,10 +2340,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: Index: llvm/test/CodeGen/X86/addcarry2.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/addcarry2.ll @@ -0,0 +1,313 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=i686-unknown-unknown --show-mc-encoding | FileCheck %s --check-prefix=X32 +; RUN: llc < %s -mtriple=x86_64-unknown --show-mc-encoding | FileCheck %s --check-prefix=X64 + +define void @adc_load_store_8_15(i64 inreg %ca, i64 inreg %cb, i8* inreg %x) nounwind { +; X32-LABEL: adc_load_store_8_15: +; X32: # %bb.0: +; X32-NEXT: pushl %esi # encoding: [0x56] +; X32-NEXT: movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c] +; X32-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8] +; X32-NEXT: adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08] +; X32-NEXT: adcb $15, (%esi) # encoding: [0x80,0x16,0x0f] +; X32-NEXT: popl %esi # encoding: [0x5e] +; X32-NEXT: retl # encoding: [0xc3] +; +; X64-LABEL: adc_load_store_8_15: +; X64: # %bb.0: +; X64-NEXT: addq %rsi, %rdi # encoding: [0x48,0x01,0xf7] +; X64-NEXT: adcb $15, (%rdx) # encoding: [0x80,0x12,0x0f] +; X64-NEXT: retq # encoding: [0xc3] + %zca = zext i64 %ca to i65 + %zcb = zext i64 %cb to i65 + %zc = add i65 %zca, %zcb + %ec = lshr i65 %zc, 64 + %c = trunc i65 %ec to i1 + %cc = zext i1 %c to i8 + %vx = load i8, i8* %x + %cc_off = add i8 15, %cc + %vsum = add i8 %vx, %cc_off + store i8 %vsum, i8* %x + ret void +} + + +define void @adc_load_store_16_15(i64 inreg %ca, i64 inreg %cb, i16* inreg %x) nounwind { +; X32-LABEL: adc_load_store_16_15: +; X32: # %bb.0: +; X32-NEXT: pushl %esi # encoding: [0x56] +; X32-NEXT: movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c] +; X32-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8] +; X32-NEXT: adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08] +; X32-NEXT: adcw $15, (%esi) # encoding: [0x66,0x83,0x16,0x0f] +; X32-NEXT: popl %esi # encoding: [0x5e] +; X32-NEXT: retl # encoding: [0xc3] +; +; X64-LABEL: adc_load_store_16_15: +; X64: # %bb.0: +; X64-NEXT: addq %rsi, %rdi # encoding: [0x48,0x01,0xf7] +; X64-NEXT: adcw $15, (%rdx) # encoding: [0x66,0x83,0x12,0x0f] +; X64-NEXT: retq # encoding: [0xc3] + %zca = zext i64 %ca to i65 + %zcb = zext i64 %cb to i65 + %zc = add i65 %zca, %zcb + %ec = lshr i65 %zc, 64 + %c = trunc i65 %ec to i1 + %cc = zext i1 %c to i16 + %vx = load i16, i16* %x + %cc_off = add i16 15, %cc + %vsum = add i16 %vx, %cc_off + store i16 %vsum, i16* %x + ret void +} + +define void @adc_load_store_16_256(i64 inreg %ca, i64 inreg %cb, i16* inreg %x) nounwind { +; X32-LABEL: adc_load_store_16_256: +; X32: # %bb.0: +; X32-NEXT: pushl %esi # encoding: [0x56] +; X32-NEXT: movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c] +; X32-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8] +; X32-NEXT: adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08] +; X32-NEXT: adcw $256, (%esi) # encoding: [0x66,0x81,0x16,0x00,0x01] +; X32-NEXT: # imm = 0x100 +; X32-NEXT: popl %esi # encoding: [0x5e] +; X32-NEXT: retl # encoding: [0xc3] +; +; X64-LABEL: adc_load_store_16_256: +; X64: # %bb.0: +; X64-NEXT: addq %rsi, %rdi # encoding: [0x48,0x01,0xf7] +; X64-NEXT: adcw $256, (%rdx) # encoding: [0x66,0x81,0x12,0x00,0x01] +; X64-NEXT: # imm = 0x100 +; X64-NEXT: retq # encoding: [0xc3] + %zca = zext i64 %ca to i65 + %zcb = zext i64 %cb to i65 + %zc = add i65 %zca, %zcb + %ec = lshr i65 %zc, 64 + %c = trunc i65 %ec to i1 + %cc = zext i1 %c to i16 + %vx = load i16, i16* %x + %cc_off = add i16 256, %cc + %vsum = add i16 %vx, %cc_off + store i16 %vsum, i16* %x + ret void +} + + + +define void @adc_load_store_32_127(i64 inreg %ca, i64 inreg %cb, i32* inreg %x) nounwind { +; X32-LABEL: adc_load_store_32_127: +; X32: # %bb.0: +; X32-NEXT: pushl %esi # encoding: [0x56] +; X32-NEXT: movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c] +; X32-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8] +; X32-NEXT: adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08] +; X32-NEXT: adcl $127, (%esi) # encoding: [0x83,0x16,0x7f] +; X32-NEXT: popl %esi # encoding: [0x5e] +; X32-NEXT: retl # encoding: [0xc3] +; +; X64-LABEL: adc_load_store_32_127: +; X64: # %bb.0: +; X64-NEXT: addq %rsi, %rdi # encoding: [0x48,0x01,0xf7] +; X64-NEXT: adcl $127, (%rdx) # encoding: [0x83,0x12,0x7f] +; X64-NEXT: retq # encoding: [0xc3] + %zca = zext i64 %ca to i65 + %zcb = zext i64 %cb to i65 + %zc = add i65 %zca, %zcb + %ec = lshr i65 %zc, 64 + %c = trunc i65 %ec to i1 + %cc = zext i1 %c to i32 + %vx = load i32, i32* %x + %cc_off = add i32 127, %cc + %vsum = add i32 %vx, %cc_off + store i32 %vsum, i32* %x + ret void +} + +define void @adc_load_store_32_128(i64 inreg %ca, i64 inreg %cb, i32* inreg %x) nounwind { +; X32-LABEL: adc_load_store_32_128: +; X32: # %bb.0: +; X32-NEXT: pushl %esi # encoding: [0x56] +; X32-NEXT: movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c] +; X32-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8] +; X32-NEXT: adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08] +; X32-NEXT: adcl $128, (%esi) # encoding: [0x81,0x16,0x80,0x00,0x00,0x00] +; X32-NEXT: popl %esi # encoding: [0x5e] +; X32-NEXT: retl # encoding: [0xc3] +; +; X64-LABEL: adc_load_store_32_128: +; X64: # %bb.0: +; X64-NEXT: addq %rsi, %rdi # encoding: [0x48,0x01,0xf7] +; X64-NEXT: adcl $128, (%rdx) # encoding: [0x81,0x12,0x80,0x00,0x00,0x00] +; X64-NEXT: retq # encoding: [0xc3] +; CHECK-LABEL: adc_load_store_32_128: +; CHECK: # %bb.0: + %zca = zext i64 %ca to i65 + %zcb = zext i64 %cb to i65 + %zc = add i65 %zca, %zcb + %ec = lshr i65 %zc, 64 + %c = trunc i65 %ec to i1 + %cc = zext i1 %c to i32 + %vx = load i32, i32* %x + %cc_off = add i32 128, %cc + %vsum = add i32 %vx, %cc_off + store i32 %vsum, i32* %x + ret void +} + +define void @adc_load_store_64_127(i64 inreg %ca, i64 inreg %cb, i64* inreg %x) nounwind { +; X32-LABEL: adc_load_store_64_127: +; X32: # %bb.0: +; X32-NEXT: pushl %esi # encoding: [0x56] +; X32-NEXT: movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c] +; X32-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8] +; X32-NEXT: adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08] +; X32-NEXT: movl (%esi), %eax # encoding: [0x8b,0x06] +; X32-NEXT: movl 4(%esi), %ecx # encoding: [0x8b,0x4e,0x04] +; X32-NEXT: adcl $0, %eax # encoding: [0x83,0xd0,0x00] +; X32-NEXT: adcl $0, %ecx # encoding: [0x83,0xd1,0x00] +; X32-NEXT: addl $127, %eax # encoding: [0x83,0xc0,0x7f] +; X32-NEXT: adcl $0, %ecx # encoding: [0x83,0xd1,0x00] +; X32-NEXT: movl %eax, (%esi) # encoding: [0x89,0x06] +; X32-NEXT: movl %ecx, 4(%esi) # encoding: [0x89,0x4e,0x04] +; X32-NEXT: popl %esi # encoding: [0x5e] +; X32-NEXT: retl # encoding: [0xc3] +; +; X64-LABEL: adc_load_store_64_127: +; X64: # %bb.0: +; X64-NEXT: addq %rsi, %rdi # encoding: [0x48,0x01,0xf7] +; X64-NEXT: adcq $127, (%rdx) # encoding: [0x48,0x83,0x12,0x7f] +; X64-NEXT: retq # encoding: [0xc3] +; CHECK-LABEL: adc_load_store_32_128: +; CHECK: # %bb.0: + %zca = zext i64 %ca to i65 + %zcb = zext i64 %cb to i65 + %zc = add i65 %zca, %zcb + %ec = lshr i65 %zc, 64 + %c = trunc i65 %ec to i1 + %cc = zext i1 %c to i64 + %vx = load i64, i64* %x + %cc_off = add i64 127, %cc + %vsum = add i64 %vx, %cc_off + store i64 %vsum, i64* %x + ret void +} + +define void @adc_load_store_64_128(i64 inreg %ca, i64 inreg %cb, i64* inreg %x) nounwind { +; X32-LABEL: adc_load_store_64_128: +; X32: # %bb.0: +; X32-NEXT: pushl %esi # encoding: [0x56] +; X32-NEXT: movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c] +; X32-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8] +; X32-NEXT: adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08] +; X32-NEXT: movl (%esi), %eax # encoding: [0x8b,0x06] +; X32-NEXT: movl 4(%esi), %ecx # encoding: [0x8b,0x4e,0x04] +; X32-NEXT: adcl $0, %eax # encoding: [0x83,0xd0,0x00] +; X32-NEXT: adcl $0, %ecx # encoding: [0x83,0xd1,0x00] +; X32-NEXT: addl $128, %eax # encoding: [0x05,0x80,0x00,0x00,0x00] +; X32-NEXT: adcl $0, %ecx # encoding: [0x83,0xd1,0x00] +; X32-NEXT: movl %eax, (%esi) # encoding: [0x89,0x06] +; X32-NEXT: movl %ecx, 4(%esi) # encoding: [0x89,0x4e,0x04] +; X32-NEXT: popl %esi # encoding: [0x5e] +; X32-NEXT: retl # encoding: [0xc3] +; +; X64-LABEL: adc_load_store_64_128: +; X64: # %bb.0: +; X64-NEXT: addq %rsi, %rdi # encoding: [0x48,0x01,0xf7] +; X64-NEXT: adcq $128, (%rdx) # encoding: [0x48,0x81,0x12,0x80,0x00,0x00,0x00] +; X64-NEXT: retq # encoding: [0xc3] +; CHECK-LABEL: adc_load_store_32_128: +; CHECK: # %bb.0: + %zca = zext i64 %ca to i65 + %zcb = zext i64 %cb to i65 + %zc = add i65 %zca, %zcb + %ec = lshr i65 %zc, 64 + %c = trunc i65 %ec to i1 + %cc = zext i1 %c to i64 + %vx = load i64, i64* %x + %cc_off = add i64 128, %cc + %vsum = add i64 %vx, %cc_off + store i64 %vsum, i64* %x + ret void +} + +define void @adc_load_store_64_4294967297(i64 inreg %ca, i64 inreg %cb, i64* inreg %x) nounwind { +; X32-LABEL: adc_load_store_64_4294967296: +; X32: # %bb.0: +; X32-NEXT: pushl %esi # encoding: [0x56] +; X32-NEXT: movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c] +; X32-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8] +; X32-NEXT: adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08] +; X32-NEXT: movl (%esi), %eax # encoding: [0x8b,0x06] +; X32-NEXT: movl 4(%esi), %ecx # encoding: [0x8b,0x4e,0x04] +; X32-NEXT: adcl $0, %eax # encoding: [0x83,0xd0,0x00] +; X32-NEXT: adcl $0, %ecx # encoding: [0x83,0xd1,0x00] +; X32-NEXT: addl $2147483647, %eax # encoding: [0x05,0xff,0xff,0xff,0x7f] +; X32-NEXT: # imm = 0x7FFFFFFF +; X32-NEXT: adcl $0, %ecx # encoding: [0x83,0xd1,0x00] +; X32-NEXT: movl %eax, (%esi) # encoding: [0x89,0x06] +; X32-NEXT: movl %ecx, 4(%esi) # encoding: [0x89,0x4e,0x04] +; X32-NEXT: popl %esi # encoding: [0x5e] +; X32-NEXT: retl # encoding: [0xc3] +; +; X64-LABEL: adc_load_store_64_4294967296: +; X64: # %bb.0: +; X64-NEXT: addq %rsi, %rdi # encoding: [0x48,0x01,0xf7] +; X64-NEXT: adcq $2147483647, (%rdx) # encoding: [0x48,0x81,0x12,0xff,0xff,0xff,0x7f] +; X64-NEXT: # imm = 0x7FFFFFFF +; X64-NEXT: retq # encoding: [0xc3] +; CHECK-LABEL: adc_load_store_32_128: +; CHECK: # %bb.0: + %zca = zext i64 %ca to i65 + %zcb = zext i64 %cb to i65 + %zc = add i65 %zca, %zcb + %ec = lshr i65 %zc, 64 + %c = trunc i65 %ec to i1 + %cc = zext i1 %c to i64 + %vx = load i64, i64* %x + %cc_off = add i64 2147483647, %cc + %vsum = add i64 %vx, %cc_off + store i64 %vsum, i64* %x + ret void +} + +define void @adc_load_store_64_2147483648(i64 inreg %ca, i64 inreg %cb, i64* inreg %x) nounwind { +; X32-LABEL: adc_load_store_64_2147483648: +; X32: # %bb.0: +; X32-NEXT: pushl %esi # encoding: [0x56] +; X32-NEXT: movl {{[0-9]+}}(%esp), %esi # encoding: [0x8b,0x74,0x24,0x0c] +; X32-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8] +; X32-NEXT: adcl {{[0-9]+}}(%esp), %edx # encoding: [0x13,0x54,0x24,0x08] +; X32-NEXT: movl (%esi), %eax # encoding: [0x8b,0x06] +; X32-NEXT: movl 4(%esi), %ecx # encoding: [0x8b,0x4e,0x04] +; X32-NEXT: adcl $0, %eax # encoding: [0x83,0xd0,0x00] +; X32-NEXT: adcl $0, %ecx # encoding: [0x83,0xd1,0x00] +; X32-NEXT: addl $-2147483648, %eax # encoding: [0x05,0x00,0x00,0x00,0x80] +; X32-NEXT: # imm = 0x80000000 +; X32-NEXT: adcl $0, %ecx # encoding: [0x83,0xd1,0x00] +; X32-NEXT: movl %eax, (%esi) # encoding: [0x89,0x06] +; X32-NEXT: movl %ecx, 4(%esi) # encoding: [0x89,0x4e,0x04] +; X32-NEXT: popl %esi # encoding: [0x5e] +; X32-NEXT: retl # encoding: [0xc3] +; +; X64-LABEL: adc_load_store_64_2147483648: +; X64: # %bb.0: +; X64-NEXT: addq %rsi, %rdi # encoding: [0x48,0x01,0xf7] +; X64-NEXT: movl $2147483648, %eax # encoding: [0xb8,0x00,0x00,0x00,0x80] +; X64-NEXT: # imm = 0x80000000 +; X64-NEXT: adcq %rax, (%rdx) # encoding: [0x48,0x11,0x02] +; X64-NEXT: retq # encoding: [0xc3] +; CHECK-LABEL: adc_load_store_32_128: +; CHECK: # %bb.0: + %zca = zext i64 %ca to i65 + %zcb = zext i64 %cb to i65 + %zc = add i65 %zca, %zcb + %ec = lshr i65 %zc, 64 + %c = trunc i65 %ec to i1 + %cc = zext i1 %c to i64 + %vx = load i64, i64* %x + %cc_off = add i64 2147483648, %cc + %vsum = add i64 %vx, %cc_off + store i64 %vsum, i64* %x + ret void +} +