unsigned short compute_tcpudp_checksum(unsigned int sourceip,
                                       unsigned int destip,
                                       unsigned char protocol,
                                       unsigned short datalen,
                                       unsigned char *data) {
  unsigned int pseudohdr[3];
  unsigned int csum;
  pseudohdr[0] = htonl(sourceip);
  pseudohdr[1] = htonl(destip);
  ((unsigned char *)&pseudohdr[2])[0] = 0;
  ((unsigned char *)&pseudohdr[2])[1] = protocol;
  ((unsigned short *)&pseudohdr[2])[1] = htons(datalen);
  csum = (~compute_checksum((unsigned char *)pseudohdr, 12) & 0xFFFF) +
         (~compute_checksum(data, datalen) & 0xFFFF);
  if (csum & 0xFFFF0000)
    csum = (csum + 1) & 0xFFFF;
  return (unsigned short)~csum;
}


x86 assembly (clang, -O0):
<compute_tcpudp_checksum>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %cx,%ax
mov    %dl,%cl
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    %cl,-0x9(%rbp)
mov    %ax,-0xc(%rbp)
mov    %r8,-0x18(%rbp)
mov    -0x4(%rbp),%edi
mov    $0x0,%al
call   1050 <htonl@plt>
mov    %eax,-0x24(%rbp)
mov    -0x8(%rbp),%edi
mov    $0x0,%al
call   1050 <htonl@plt>
mov    %eax,-0x20(%rbp)
movb   $0x0,-0x1c(%rbp)
mov    -0x9(%rbp),%al
mov    %al,-0x1b(%rbp)
movzwl -0xc(%rbp),%edi
mov    $0x0,%al
call   1040 <htons@plt>
mov    %ax,-0x1a(%rbp)
lea    -0x24(%rbp),%rdi
mov    $0xc,%esi
mov    $0x0,%al
call   1030 <compute_checksum@plt>
xor    $0xffffffff,%eax
and    $0xffff,%eax
mov    %eax,-0x2c(%rbp)
mov    -0x18(%rbp),%rdi
movzwl -0xc(%rbp),%esi
mov    $0x0,%al
call   1030 <compute_checksum@plt>
mov    %eax,%ecx
mov    -0x2c(%rbp),%eax
xor    $0xffffffff,%ecx
and    $0xffff,%ecx
add    %ecx,%eax
mov    %eax,-0x28(%rbp)
mov    -0x28(%rbp),%eax
and    $0xffff0000,%eax
cmp    $0x0,%eax
je     11dd <compute_tcpudp_checksum+0xad>
mov    -0x28(%rbp),%eax
add    $0x1,%eax
and    $0xffff,%eax
mov    %eax,-0x28(%rbp)
mov    -0x28(%rbp),%eax
xor    $0xffffffff,%eax
movzwl %ax,%eax
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<compute_tcpudp_checksum>:
push   %rbp
push   %r15
push   %r14
push   %rbx
sub    $0x18,%rsp
mov    %r8,%r14
mov    %ecx,%r15d
mov    %edx,%ebp
mov    %esi,%ebx
xor    %eax,%eax
call   1050 <htonl@plt>
mov    %eax,0xc(%rsp)
mov    %ebx,%edi
xor    %eax,%eax
call   1050 <htonl@plt>
mov    %eax,0x10(%rsp)
movb   $0x0,0x14(%rsp)
mov    %bpl,0x15(%rsp)
mov    %r15d,%edi
xor    %eax,%eax
call   1040 <htons@plt>
mov    %ax,0x16(%rsp)
lea    0xc(%rsp),%rdi
mov    $0xc,%esi
xor    %eax,%eax
call   1030 <compute_checksum@plt>
not    %eax
movzwl %ax,%ebx
mov    %r14,%rdi
mov    %r15d,%esi
xor    %eax,%eax
call   1030 <compute_checksum@plt>
not    %eax
movzwl %ax,%ecx
add    %ebx,%ecx
mov    %ecx,%eax
shr    $0x10,%eax
add    %ecx,%eax
not    %eax
add    $0x18,%rsp
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define zeroext i16 @compute_tcpudp_checksum(i32 %0, i32 %1, i8 zeroext %2, i16 zeroext %3, i8* %4) {
%6 = alloca i32
%7 = alloca i32
%8 = alloca i8
%9 = alloca i16
%10 = alloca i8*
%11 = alloca [3 x i32]
%12 = alloca i32
store i32 %0, i32* %6
store i32 %1, i32* %7
store i8 %2, i8* %8
store i16 %3, i16* %9
store i8* %4, i8** %10
%13 = load i32, i32* %6
%14 = call i32 (i32, ...) bitcast (i32 (...)* @htonl to i32 (i32, ...)*)(i32 %13)
%15 = getelementptr inbounds [3 x i32], [3 x i32]* %11, i64 0, i64 0
store i32 %14, i32* %15
%16 = load i32, i32* %7
%17 = call i32 (i32, ...) bitcast (i32 (...)* @htonl to i32 (i32, ...)*)(i32 %16)
%18 = getelementptr inbounds [3 x i32], [3 x i32]* %11, i64 0, i64 1
store i32 %17, i32* %18
%19 = getelementptr inbounds [3 x i32], [3 x i32]* %11, i64 0, i64 2
%20 = bitcast i32* %19 to i8*
%21 = getelementptr inbounds i8, i8* %20, i64 0
store i8 0, i8* %21
%22 = load i8, i8* %8
%23 = getelementptr inbounds [3 x i32], [3 x i32]* %11, i64 0, i64 2
%24 = bitcast i32* %23 to i8*
%25 = getelementptr inbounds i8, i8* %24, i64 1
store i8 %22, i8* %25
%26 = load i16, i16* %9
%27 = zext i16 %26 to i32
%28 = call i32 (i32, ...) bitcast (i32 (...)* @htons to i32 (i32, ...)*)(i32 %27)
%29 = trunc i32 %28 to i16
%30 = getelementptr inbounds [3 x i32], [3 x i32]* %11, i64 0, i64 2
%31 = bitcast i32* %30 to i16*
%32 = getelementptr inbounds i16, i16* %31, i64 1
store i16 %29, i16* %32
%33 = getelementptr inbounds [3 x i32], [3 x i32]* %11, i64 0, i64 0
%34 = bitcast i32* %33 to i8*
%35 = call i32 (i8*, i32, ...) bitcast (i32 (...)* @compute_checksum to i32 (i8*, i32, ...)*)(i8* %34, i32 12)
%36 = xor i32 %35, -1
%37 = and i32 %36, 65535
%38 = load i8*, i8** %10
%39 = load i16, i16* %9
%40 = zext i16 %39 to i32
%41 = call i32 (i8*, i32, ...) bitcast (i32 (...)* @compute_checksum to i32 (i8*, i32, ...)*)(i8* %38, i32 %40)
%42 = xor i32 %41, -1
%43 = and i32 %42, 65535
%44 = add nsw i32 %37, %43
store i32 %44, i32* %12
%45 = load i32, i32* %12
%46 = and i32 %45, -65536
%47 = icmp ne i32 %46, 0
br i1 %47, label %48, label %52
48: ; preds = %5
%49 = load i32, i32* %12
%50 = add i32 %49, 1
%51 = and i32 %50, 65535
store i32 %51, i32* %12
br label %52
52: ; preds = %48, %5
%53 = load i32, i32* %12
%54 = xor i32 %53, -1
%55 = trunc i32 %54 to i16
ret i16 %55
}

LLVM IR (-O2):
define zeroext i16 @compute_tcpudp_checksum(i32 %0, i32 %1, i8 zeroext %2, i16 zeroext %3, i8* %4) {
%6 = alloca [3 x i32]
%7 = bitcast [3 x i32]* %6 to i8*
%8 = tail call i32 (i32, ...) bitcast (i32 (...)* @htonl to i32 (i32, ...)*)(i32 %0)
%9 = getelementptr inbounds [3 x i32], [3 x i32]* %6, i64 0, i64 0
store i32 %8, i32* %9
%10 = tail call i32 (i32, ...) bitcast (i32 (...)* @htonl to i32 (i32, ...)*)(i32 %1)
%11 = getelementptr inbounds [3 x i32], [3 x i32]* %6, i64 0, i64 1
store i32 %10, i32* %11
%12 = getelementptr inbounds [3 x i32], [3 x i32]* %6, i64 0, i64 2
%13 = bitcast i32* %12 to i8*
store i8 0, i8* %13
%14 = getelementptr inbounds i8, i8* %13, i64 1
store i8 %2, i8* %14
%15 = zext i16 %3 to i32
%16 = tail call i32 (i32, ...) bitcast (i32 (...)* @htons to i32 (i32, ...)*)(i32 %15)
%17 = trunc i32 %16 to i16
%18 = bitcast i32* %12 to i16*
%19 = getelementptr inbounds i16, i16* %18, i64 1
store i16 %17, i16* %19
%20 = call i32 (i8*, i32, ...) bitcast (i32 (...)* @compute_checksum to i32 (i8*, i32, ...)*)(i8* %7, i32 12)
%21 = and i32 %20, 65535
%22 = xor i32 %21, 65535
%23 = call i32 (i8*, i32, ...) bitcast (i32 (...)* @compute_checksum to i32 (i8*, i32, ...)*)(i8* %4, i32 %15)
%24 = and i32 %23, 65535
%25 = xor i32 %24, 65535
%26 = add nuw nsw i32 %25, %22
%27 = lshr i32 %26, 16
%28 = add nuw nsw i32 %27, %26
%29 = trunc i32 %28 to i16
%30 = xor i16 %29, -1
ret i16 %30
}