unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl) {
  unsigned int sum;
  __asm__ __volatile__("	    movl (%1), %0\n"
                       "	    subl $4, %2\n"
                       "	    jbe 2f\n"
                       "	    addl 4(%1), %0\n"
                       "	    adcl 8(%1), %0\n"
                       "	    adcl 12(%1), %0\n"
                       "1:	    adcl 16(%1), %0\n"
                       "	    lea 4(%1), %1\n"
                       "	    decl %2\n"
                       "	    jne	1b\n"
                       "	    adcl $0, %0\n"
                       "	    movl %0, %2\n"
                       "	    shrl $16, %0\n"
                       "	    addw %w2, %w0\n"
                       "	    adcl $0, %0\n"
                       "	    notl %0\n"
                       "2:"
                       : "=r"(sum), "=r"(iph), "=r"(ihl)
                       : "1"(iph), "2"(ihl)
                       : "memory");
  return (sum);
}


x86 assembly (clang, -O0):
<ip_fast_csum>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    -0x8(%rbp),%rcx
mov    -0xc(%rbp),%eax
mov    (%rcx),%edx
sub    $0x4,%eax
jbe    1145 <ip_fast_csum+0x45>
add    0x4(%rcx),%edx
adc    0x8(%rcx),%edx
adc    0xc(%rcx),%edx
adc    0x10(%rcx),%edx
lea    0x4(%rcx),%rcx
dec    %eax
jne    1126 <ip_fast_csum+0x26>
adc    $0x0,%edx
mov    %edx,%eax
shr    $0x10,%edx
add    %ax,%dx
adc    $0x0,%edx
not    %edx
mov    %edx,-0x10(%rbp)
mov    %rcx,-0x8(%rbp)
mov    %eax,-0xc(%rbp)
mov    -0x10(%rbp),%eax
movzwl %ax,%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<ip_fast_csum>:
mov    (%rdi),%eax
sub    $0x4,%esi
jbe    112b <ip_fast_csum+0x2b>
add    0x4(%rdi),%eax
adc    0x8(%rdi),%eax
adc    0xc(%rdi),%eax
adc    0x10(%rdi),%eax
lea    0x4(%rdi),%rdi
dec    %esi
jne    1110 <ip_fast_csum+0x10>
adc    $0x0,%eax
mov    %eax,%esi
shr    $0x10,%eax
add    %si,%ax
adc    $0x0,%eax
not    %eax
ret

LLVM IR (-O0):
define zeroext i16 @ip_fast_csum(i8* %0, i32 %1) {
%3 = alloca i8*
%4 = alloca i32
%5 = alloca i32
store i8* %0, i8** %3
store i32 %1, i32* %4
%6 = load i8*, i8** %3
%7 = load i32, i32* %4
%8 = call { i32, i8*, i32 } asm sideeffect "\09 movl ($1), $0\0A\09 subl $$4, $2\0A\09 jbe 2f\0A\09 addl 4($1), $0\0A\09 adcl 8($1), $0\0A\09 adcl 12($1), $0\0A1:\09 adcl 16($1), $0\0A\09 lea 4($1), $1\0A\09 decl $2\0A\09 jne\091b\0A\09 adcl $$0, $0\0A\09 movl $0, $2\0A\09 shrl $$16, $0\0A\09 addw ${2:w}, ${0:w}\0A\09 adcl $$0, $0\0A\09 notl $0\0A2:", "=r,=r,=r,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i8* %6, i32 %7)
%9 = extractvalue { i32, i8*, i32 } %8, 0
%10 = extractvalue { i32, i8*, i32 } %8, 1
%11 = extractvalue { i32, i8*, i32 } %8, 2
store i32 %9, i32* %5
store i8* %10, i8** %3
store i32 %11, i32* %4
%12 = load i32, i32* %5
%13 = trunc i32 %12 to i16
ret i16 %13
}

LLVM IR (-O2):
define zeroext i16 @ip_fast_csum(i8* %0, i32 %1) {
%3 = tail call { i32, i8*, i32 } asm sideeffect "\09 movl ($1), $0\0A\09 subl $$4, $2\0A\09 jbe 2f\0A\09 addl 4($1), $0\0A\09 adcl 8($1), $0\0A\09 adcl 12($1), $0\0A1:\09 adcl 16($1), $0\0A\09 lea 4($1), $1\0A\09 decl $2\0A\09 jne\091b\0A\09 adcl $$0, $0\0A\09 movl $0, $2\0A\09 shrl $$16, $0\0A\09 addw ${2:w}, ${0:w}\0A\09 adcl $$0, $0\0A\09 notl $0\0A2:", "=r,=r,=r,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i8* %0, i32 %1)
%4 = extractvalue { i32, i8*, i32 } %3, 0
%5 = trunc i32 %4 to i16
ret i16 %5
}