void CalculateChecksum(unsigned short *data, unsigned short len,
                       unsigned long *result) {
  unsigned long temp;
  unsigned long sum1 = 0xffff;
  unsigned long sum2 = 0xffff;
  *result = 0xffffffff;
  while (len--) {
    temp = *data;
    sum1 += temp;
    sum2 += sum1;
    sum1 = (sum1 & 0xffff) + (sum1 >> 16);
    sum2 = (sum2 & 0xffff) + (sum2 >> 16);
    data++;
  }
  *result = sum2 << 16 | sum1;
  return;
}


x86 assembly (clang, -O0):
<CalculateChecksum>:
push   %rbp
mov    %rsp,%rbp
mov    %si,%ax
mov    %rdi,-0x8(%rbp)
mov    %ax,-0xa(%rbp)
mov    %rdx,-0x18(%rbp)
movq   $0xffff,-0x28(%rbp)
movq   $0xffff,-0x30(%rbp)
mov    -0x18(%rbp),%rax
mov    $0xffffffff,%ecx
mov    %rcx,(%rax)
mov    -0xa(%rbp),%ax
mov    %ax,%cx
add    $0xffff,%cx
mov    %cx,-0xa(%rbp)
cmp    $0x0,%ax
je     11ae <CalculateChecksum+0xae>
mov    -0x8(%rbp),%rax
movzwl (%rax),%eax
mov    %rax,-0x20(%rbp)
mov    -0x20(%rbp),%rax
add    -0x28(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x28(%rbp),%rax
add    -0x30(%rbp),%rax
mov    %rax,-0x30(%rbp)
mov    -0x28(%rbp),%rax
and    $0xffff,%rax
mov    -0x28(%rbp),%rcx
shr    $0x10,%rcx
add    %rcx,%rax
mov    %rax,-0x28(%rbp)
mov    -0x30(%rbp),%rax
and    $0xffff,%rax
mov    -0x30(%rbp),%rcx
shr    $0x10,%rcx
add    %rcx,%rax
mov    %rax,-0x30(%rbp)
mov    -0x8(%rbp),%rax
add    $0x2,%rax
mov    %rax,-0x8(%rbp)
jmp    112f <CalculateChecksum+0x2f>
mov    -0x30(%rbp),%rcx
shl    $0x10,%rcx
or     -0x28(%rbp),%rcx
mov    -0x18(%rbp),%rax
mov    %rcx,(%rax)
pop    %rbp
ret

x86 assembly (clang, -O2):
<CalculateChecksum>:
test   %esi,%esi
je     1116 <CalculateChecksum+0x16>
cmp    $0x1,%si
jne    111f <CalculateChecksum+0x1f>
mov    $0xffff,%eax
mov    $0xffff,%ecx
jmp    118a <CalculateChecksum+0x8a>
mov    $0xffffffff,%eax
mov    %rax,(%rdx)
ret
mov    %esi,%r8d
and    $0xfffe,%r8d
mov    $0xffff,%eax
mov    $0xffff,%ecx
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movzwl (%rdi),%r9d
add    %rcx,%r9
add    %r9,%rax
movzwl %r9w,%ecx
shr    $0x10,%r9
add    %rcx,%r9
movzwl %ax,%ecx
shr    $0x10,%rax
add    %rcx,%rax
movzwl 0x2(%rdi),%ecx
add    %r9,%rcx
add    %rcx,%rax
movzwl %cx,%r9d
shr    $0x10,%rcx
add    %r9,%rcx
movzwl %ax,%r9d
shr    $0x10,%rax
add    %r9,%rax
add    $0x4,%rdi
add    $0xfffe,%r8w
jne    1140 <CalculateChecksum+0x40>
test   $0x1,%sil
je     11ad <CalculateChecksum+0xad>
movzwl (%rdi),%esi
add    %rsi,%rcx
add    %rcx,%rax
movzwl %cx,%esi
shr    $0x10,%rcx
add    %rsi,%rcx
movzwl %ax,%esi
shr    $0x10,%rax
add    %rsi,%rax
shl    $0x10,%rax
or     %rcx,%rax
mov    %rax,(%rdx)
ret

LLVM IR (-O0):
define void @CalculateChecksum(i16* %0, i16 zeroext %1, i64* %2) {
%4 = alloca i16*
%5 = alloca i16
%6 = alloca i64*
%7 = alloca i64
%8 = alloca i64
%9 = alloca i64
store i16* %0, i16** %4
store i16 %1, i16* %5
store i64* %2, i64** %6
store i64 65535, i64* %8
store i64 65535, i64* %9
%10 = load i64*, i64** %6
store i64 4294967295, i64* %10
br label %11
11: ; preds = %15, %3
%12 = load i16, i16* %5
%13 = add i16 %12, -1
store i16 %13, i16* %5
%14 = icmp ne i16 %12, 0
br i1 %14, label %15, label %37
15: ; preds = %11
%16 = load i16*, i16** %4
%17 = load i16, i16* %16
%18 = zext i16 %17 to i64
store i64 %18, i64* %7
%19 = load i64, i64* %7
%20 = load i64, i64* %8
%21 = add i64 %20, %19
store i64 %21, i64* %8
%22 = load i64, i64* %8
%23 = load i64, i64* %9
%24 = add i64 %23, %22
store i64 %24, i64* %9
%25 = load i64, i64* %8
%26 = and i64 %25, 65535
%27 = load i64, i64* %8
%28 = lshr i64 %27, 16
%29 = add i64 %26, %28
store i64 %29, i64* %8
%30 = load i64, i64* %9
%31 = and i64 %30, 65535
%32 = load i64, i64* %9
%33 = lshr i64 %32, 16
%34 = add i64 %31, %33
store i64 %34, i64* %9
%35 = load i16*, i16** %4
%36 = getelementptr inbounds i16, i16* %35, i32 1
store i16* %36, i16** %4
br label %11
37: ; preds = %11
%38 = load i64, i64* %9
%39 = shl i64 %38, 16
%40 = load i64, i64* %8
%41 = or i64 %39, %40
%42 = load i64*, i64** %6
store i64 %41, i64* %42
ret void
}

LLVM IR (-O2):
define void @CalculateChecksum(i16* nocapture %0, i16 zeroext %1, i64* nocapture writeonly %2) {
%4 = icmp eq i16 %1, 0
br i1 %4, label %62, label %5
5: ; preds = %3
%6 = and i16 %1, 1
%7 = icmp eq i16 %1, 1
br i1 %7, label %39, label %8
8: ; preds = %5
%9 = and i16 %1, -2
br label %10
10: ; preds = %10, %8
%11 = phi i64 [ 65535, %8 ], [ %35, %10 ]
%12 = phi i64 [ 65535, %8 ], [ %32, %10 ]
%13 = phi i16* [ %0, %8 ], [ %36, %10 ]
%14 = phi i16 [ 0, %8 ], [ %37, %10 ]
%15 = load i16, i16* %13
%16 = zext i16 %15 to i64
%17 = add nsw i64 %12, %16
%18 = add nsw i64 %17, %11
%19 = and i64 %17, 65535
%20 = lshr i64 %17, 16
%21 = add nuw nsw i64 %19, %20
%22 = and i64 %18, 65535
%23 = lshr i64 %18, 16
%24 = add nuw nsw i64 %22, %23
%25 = getelementptr inbounds i16, i16* %13, i64 1
%26 = load i16, i16* %25
%27 = zext i16 %26 to i64
%28 = add nuw nsw i64 %21, %27
%29 = add nuw nsw i64 %28, %24
%30 = and i64 %28, 65535
%31 = lshr i64 %28, 16
%32 = add nuw nsw i64 %30, %31
%33 = and i64 %29, 65535
%34 = lshr i64 %29, 16
%35 = add nuw nsw i64 %33, %34
%36 = getelementptr inbounds i16, i16* %13, i64 2
%37 = add i16 %14, 2
%38 = icmp eq i16 %37, %9
br i1 %38, label %39, label %10
39: ; preds = %10, %5
%40 = phi i64 [ undef, %5 ], [ %32, %10 ]
%41 = phi i64 [ undef, %5 ], [ %35, %10 ]
%42 = phi i64 [ 65535, %5 ], [ %35, %10 ]
%43 = phi i64 [ 65535, %5 ], [ %32, %10 ]
%44 = phi i16* [ %0, %5 ], [ %36, %10 ]
%45 = icmp eq i16 %6, 0
br i1 %45, label %57, label %46
46: ; preds = %39
%47 = load i16, i16* %44
%48 = zext i16 %47 to i64
%49 = add nsw i64 %43, %48
%50 = add nsw i64 %49, %42
%51 = and i64 %49, 65535
%52 = lshr i64 %49, 16
%53 = add nuw nsw i64 %51, %52
%54 = and i64 %50, 65535
%55 = lshr i64 %50, 16
%56 = add nuw nsw i64 %54, %55
br label %57
57: ; preds = %39, %46
%58 = phi i64 [ %40, %39 ], [ %53, %46 ]
%59 = phi i64 [ %41, %39 ], [ %56, %46 ]
%60 = shl i64 %59, 16
%61 = or i64 %60, %58
br label %62
62: ; preds = %57, %3
%63 = phi i64 [ %61, %57 ], [ 4294967295, %3 ]
store i64 %63, i64* %2
ret void
}