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:				;\n"
                       : "=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 "movl ($1), $0\09;\0Asubl $$4, $2\09;\0Ajbe 2f\09\09;\0Aaddl 4($1), $0\09;\0Aadcl 8($1), $0\09;\0Aadcl 12($1), $0\09;\0A1:\09 adcl 16($1), $0\09;\0Alea 4($1), $1\09;\0Adecl $2\09\09;\0Ajne 1b\09\09;\0Aadcl $$0, $0\09;\0Amovl $0, $2\09;\0Ashrl $$16, $0\09;\0Aaddw ${2:w}, ${0:w}\09;\0Aadcl $$0, $0\09;\0Anotl $0\09\09;\0A2:\09\09\09\09;\0A", "=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 "movl ($1), $0\09;\0Asubl $$4, $2\09;\0Ajbe 2f\09\09;\0Aaddl 4($1), $0\09;\0Aadcl 8($1), $0\09;\0Aadcl 12($1), $0\09;\0A1:\09 adcl 16($1), $0\09;\0Alea 4($1), $1\09;\0Adecl $2\09\09;\0Ajne 1b\09\09;\0Aadcl $$0, $0\09;\0Amovl $0, $2\09;\0Ashrl $$16, $0\09;\0Aaddw ${2:w}, ${0:w}\09;\0Aadcl $$0, $0\09;\0Anotl $0\09\09;\0A2:\09\09\09\09;\0A", "=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
}