#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
typedef size_t uint8_t;
typedef int /*<<< orphan*/ uint32_t;
typedef int /*<<< orphan*/ uint16_t;
struct iovec {
  size_t iov_len;
  int /*<<< orphan*/ *iov_base;
};

/* Variables and functions */
int /*<<< orphan*/ htonl(size_t);
int /*<<< orphan*/ in_cksum(struct iovec *, int);
uint16_t teredo_cksum(const void *src, const void *dst, uint8_t protocol,
                      const struct iovec *data, size_t n) {
  struct iovec iov[3 + n];
  size_t plen = 0;
  for (size_t i = 0; i < n; i++) {
    iov[3 + i].iov_base = data[i].iov_base;
    plen += (iov[3 + i].iov_len = data[i].iov_len);
  }
  uint32_t pseudo[4] = {htonl(plen), htonl(protocol)};
  iov[0].iov_base = (void *)src;
  iov[0].iov_len = 16;
  iov[1].iov_base = (void *)dst;
  iov[1].iov_len = 16;
  iov[2].iov_base = pseudo;
  iov[2].iov_len = 8;
  return in_cksum(iov, 3 + n);
}


x86 assembly (clang, -O0):
<teredo_cksum>:
push   %rbp
mov    %rsp,%rbp
sub    $0x90,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
mov    -0x28(%rbp),%rax
add    $0x3,%rax
mov    %rsp,%rcx
mov    %rcx,-0x30(%rbp)
mov    %rax,%rdx
shl    $0x4,%rdx
mov    %rsp,%rcx
sub    %rdx,%rcx
mov    %rcx,-0x68(%rbp)
mov    %rcx,%rsp
mov    %rax,-0x38(%rbp)
movq   $0x0,-0x40(%rbp)
movq   $0x0,-0x48(%rbp)
mov    -0x48(%rbp),%rax
cmp    -0x28(%rbp),%rax
jae    11ee <teredo_cksum+0xce>
mov    -0x68(%rbp),%rcx
mov    -0x20(%rbp),%rax
mov    -0x48(%rbp),%rdx
shl    $0x4,%rdx
add    %rdx,%rax
mov    0x8(%rax),%rdx
mov    -0x48(%rbp),%rsi
add    $0x3,%rsi
shl    $0x4,%rsi
mov    %rcx,%rax
add    %rsi,%rax
mov    %rdx,0x8(%rax)
mov    -0x20(%rbp),%rax
mov    -0x48(%rbp),%rdx
shl    $0x4,%rdx
add    %rdx,%rax
mov    (%rax),%rax
mov    -0x48(%rbp),%rdx
add    $0x3,%rdx
shl    $0x4,%rdx
add    %rdx,%rcx
mov    %rax,(%rcx)
add    -0x40(%rbp),%rax
mov    %rax,-0x40(%rbp)
mov    -0x48(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x48(%rbp)
jmp    1176 <teredo_cksum+0x56>
lea    -0x60(%rbp),%rax
mov    %rax,-0x88(%rbp)
mov    -0x40(%rbp),%rdi
call   1040 <htonl@plt>
mov    %eax,%ecx
mov    -0x88(%rbp),%rax
mov    %ecx,-0x60(%rbp)
add    $0x4,%rax
mov    %rax,-0x80(%rbp)
mov    -0x18(%rbp),%rdi
call   1040 <htonl@plt>
mov    -0x88(%rbp),%rcx
mov    %eax,%edx
mov    -0x80(%rbp),%rax
mov    %edx,-0x5c(%rbp)
add    $0x4,%rax
add    $0x10,%rcx
mov    %rcx,-0x78(%rbp)
mov    %rax,-0x70(%rbp)
mov    -0x70(%rbp),%rax
mov    -0x78(%rbp),%rcx
movl   $0x0,(%rax)
add    $0x4,%rax
mov    %rax,-0x90(%rbp)
cmp    %rcx,%rax
mov    %rax,-0x70(%rbp)
jne    123f <teredo_cksum+0x11f>
mov    -0x68(%rbp),%rdi
mov    -0x8(%rbp),%rax
mov    %rax,0x8(%rdi)
movq   $0x10,(%rdi)
mov    -0x10(%rbp),%rax
mov    %rax,0x18(%rdi)
movq   $0x10,0x10(%rdi)
lea    -0x60(%rbp),%rax
mov    %rax,0x28(%rdi)
movq   $0x8,0x20(%rdi)
mov    -0x28(%rbp),%rax
add    $0x3,%rax
mov    %eax,%esi
call   1030 <in_cksum@plt>
mov    -0x30(%rbp),%rcx
mov    %rcx,%rsp
mov    %rbp,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<teredo_cksum>:
push   %rbp
mov    %rsp,%rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x18,%rsp
mov    %rdx,%r13
mov    %rsi,%r15
mov    %rdi,%r12
lea    0x3(%r8),%r14
mov    %rsp,%rbx
mov    %r14,%rax
shl    $0x4,%rax
sub    %rax,%rbx
mov    %rbx,%rsp
test   %r8,%r8
je     115f <teredo_cksum+0x3f>
cmp    $0x1,%r8
jne    1163 <teredo_cksum+0x43>
xor    %eax,%eax
xor    %edi,%edi
jmp    11aa <teredo_cksum+0x8a>
xor    %edi,%edi
jmp    11ca <teredo_cksum+0xaa>
mov    %r8,%r9
and    $0xfffffffffffffffe,%r9
xor    %esi,%esi
xor    %eax,%eax
xor    %edi,%edi
mov    0x8(%rcx,%rsi,1),%rdx
mov    %rdx,0x38(%rbx,%rsi,1)
mov    (%rcx,%rsi,1),%rdx
mov    %rdx,0x30(%rbx,%rsi,1)
add    %rdx,%rdi
mov    0x18(%rcx,%rsi,1),%rdx
mov    %rdx,0x48(%rbx,%rsi,1)
mov    0x10(%rcx,%rsi,1),%rdx
mov    %rdx,0x40(%rbx,%rsi,1)
add    %rdx,%rdi
add    $0x2,%rax
add    $0x20,%rsi
cmp    %rax,%r9
jne    1170 <teredo_cksum+0x50>
test   $0x1,%r8b
je     11ca <teredo_cksum+0xaa>
shl    $0x4,%rax
mov    0x8(%rcx,%rax,1),%rdx
mov    %rdx,0x38(%rax,%rbx,1)
mov    (%rcx,%rax,1),%rcx
mov    %rcx,0x30(%rax,%rbx,1)
add    %rcx,%rdi
call   1040 <htonl@plt>
mov    %eax,-0x40(%rbp)
mov    %r13,%rdi
call   1040 <htonl@plt>
mov    %eax,-0x3c(%rbp)
movq   $0x0,-0x38(%rbp)
mov    %r12,0x8(%rbx)
movq   $0x10,(%rbx)
mov    %r15,0x18(%rbx)
movq   $0x10,0x10(%rbx)
lea    -0x40(%rbp),%rax
mov    %rax,0x28(%rbx)
movq   $0x8,0x20(%rbx)
mov    %rbx,%rdi
mov    %r14d,%esi
call   1030 <in_cksum@plt>
lea    -0x28(%rbp),%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
%struct.iovec = type { i64, i32* }
define i32 @teredo_cksum(i8* %0, i8* %1, i64 %2, %struct.iovec* %3, i64 %4) {
%6 = alloca i8*
%7 = alloca i8*
%8 = alloca i64
%9 = alloca %struct.iovec*
%10 = alloca i64
%11 = alloca i8*
%12 = alloca i64
%13 = alloca i64
%14 = alloca i64
%15 = alloca [4 x i32]
store i8* %0, i8** %6
store i8* %1, i8** %7
store i64 %2, i64* %8
store %struct.iovec* %3, %struct.iovec** %9
store i64 %4, i64* %10
%16 = load i64, i64* %10
%17 = add i64 3, %16
%18 = call i8* @llvm.stacksave()
store i8* %18, i8** %11
%19 = alloca %struct.iovec, i64 %17
store i64 %17, i64* %12
store i64 0, i64* %13
store i64 0, i64* %14
br label %20
20: ; preds = %45, %5
%21 = load i64, i64* %14
%22 = load i64, i64* %10
%23 = icmp ult i64 %21, %22
br i1 %23, label %24, label %48
24: ; preds = %20
%25 = load %struct.iovec*, %struct.iovec** %9
%26 = load i64, i64* %14
%27 = getelementptr inbounds %struct.iovec, %struct.iovec* %25, i64 %26
%28 = getelementptr inbounds %struct.iovec, %struct.iovec* %27, i32 0, i32 1
%29 = load i32*, i32** %28
%30 = load i64, i64* %14
%31 = add i64 3, %30
%32 = getelementptr inbounds %struct.iovec, %struct.iovec* %19, i64 %31
%33 = getelementptr inbounds %struct.iovec, %struct.iovec* %32, i32 0, i32 1
store i32* %29, i32** %33
%34 = load %struct.iovec*, %struct.iovec** %9
%35 = load i64, i64* %14
%36 = getelementptr inbounds %struct.iovec, %struct.iovec* %34, i64 %35
%37 = getelementptr inbounds %struct.iovec, %struct.iovec* %36, i32 0, i32 0
%38 = load i64, i64* %37
%39 = load i64, i64* %14
%40 = add i64 3, %39
%41 = getelementptr inbounds %struct.iovec, %struct.iovec* %19, i64 %40
%42 = getelementptr inbounds %struct.iovec, %struct.iovec* %41, i32 0, i32 0
store i64 %38, i64* %42
%43 = load i64, i64* %13
%44 = add i64 %43, %38
store i64 %44, i64* %13
br label %45
45: ; preds = %24
%46 = load i64, i64* %14
%47 = add i64 %46, 1
store i64 %47, i64* %14
br label %20
48: ; preds = %20
%49 = getelementptr inbounds [4 x i32], [4 x i32]* %15, i64 0, i64 0
%50 = load i64, i64* %13
%51 = call i32 @htonl(i64 %50)
store i32 %51, i32* %49
%52 = getelementptr inbounds i32, i32* %49, i64 1
%53 = load i64, i64* %8
%54 = call i32 @htonl(i64 %53)
store i32 %54, i32* %52
%55 = getelementptr inbounds i32, i32* %52, i64 1
%56 = getelementptr inbounds i32, i32* %49, i64 4
br label %57
57: ; preds = %57, %48
%58 = phi i32* [ %55, %48 ], [ %59, %57 ]
store i32 0, i32* %58
%59 = getelementptr inbounds i32, i32* %58, i64 1
%60 = icmp eq i32* %59, %56
br i1 %60, label %61, label %57
61: ; preds = %57
%62 = load i8*, i8** %6
%63 = bitcast i8* %62 to i32*
%64 = getelementptr inbounds %struct.iovec, %struct.iovec* %19, i64 0
%65 = getelementptr inbounds %struct.iovec, %struct.iovec* %64, i32 0, i32 1
store i32* %63, i32** %65
%66 = getelementptr inbounds %struct.iovec, %struct.iovec* %19, i64 0
%67 = getelementptr inbounds %struct.iovec, %struct.iovec* %66, i32 0, i32 0
store i64 16, i64* %67
%68 = load i8*, i8** %7
%69 = bitcast i8* %68 to i32*
%70 = getelementptr inbounds %struct.iovec, %struct.iovec* %19, i64 1
%71 = getelementptr inbounds %struct.iovec, %struct.iovec* %70, i32 0, i32 1
store i32* %69, i32** %71
%72 = getelementptr inbounds %struct.iovec, %struct.iovec* %19, i64 1
%73 = getelementptr inbounds %struct.iovec, %struct.iovec* %72, i32 0, i32 0
store i64 16, i64* %73
%74 = getelementptr inbounds [4 x i32], [4 x i32]* %15, i64 0, i64 0
%75 = getelementptr inbounds %struct.iovec, %struct.iovec* %19, i64 2
%76 = getelementptr inbounds %struct.iovec, %struct.iovec* %75, i32 0, i32 1
store i32* %74, i32** %76
%77 = getelementptr inbounds %struct.iovec, %struct.iovec* %19, i64 2
%78 = getelementptr inbounds %struct.iovec, %struct.iovec* %77, i32 0, i32 0
store i64 8, i64* %78
%79 = load i64, i64* %10
%80 = add i64 3, %79
%81 = trunc i64 %80 to i32
%82 = call i32 @in_cksum(%struct.iovec* %19, i32 %81)
%83 = load i8*, i8** %11
ret i32 %82
}

LLVM IR (-O2):
%struct.iovec = type { i64, i32* }
define i32 @teredo_cksum(i8* %0, i8* %1, i64 %2, %struct.iovec* nocapture %3, i64 %4) {
%6 = alloca [4 x i32]
%7 = add i64 %4, 3
%8 = alloca %struct.iovec, i64 %7
%9 = icmp eq i64 %4, 0
br i1 %9, label %29, label %10
10: ; preds = %5
%11 = and i64 %4, 1
%12 = icmp eq i64 %4, 1
br i1 %12, label %15, label %13
13: ; preds = %10
%14 = and i64 %4, -2
br label %48
15: ; preds = %48, %10
%16 = phi i64 [ undef, %10 ], [ %68, %48 ]
%17 = phi i64 [ 0, %10 ], [ %69, %48 ]
%18 = phi i64 [ 0, %10 ], [ %68, %48 ]
%19 = icmp eq i64 %11, 0
br i1 %19, label %29, label %20
20: ; preds = %15
%21 = getelementptr inbounds %struct.iovec, %struct.iovec* %3, i64 %17, i32 1
%22 = load i32*, i32** %21
%23 = add i64 %17, 3
%24 = getelementptr inbounds %struct.iovec, %struct.iovec* %8, i64 %23, i32 1
store i32* %22, i32** %24
%25 = getelementptr inbounds %struct.iovec, %struct.iovec* %3, i64 %17, i32 0
%26 = load i64, i64* %25
%27 = getelementptr inbounds %struct.iovec, %struct.iovec* %8, i64 %23, i32 0
store i64 %26, i64* %27
%28 = add i64 %26, %18
br label %29
29: ; preds = %20, %15, %5
%30 = phi i64 [ 0, %5 ], [ %16, %15 ], [ %28, %20 ]
%31 = bitcast [4 x i32]* %6 to i8*
%32 = getelementptr inbounds [4 x i32], [4 x i32]* %6, i64 0, i64 0
%33 = tail call i32 @htonl(i64 %30)
store i32 %33, i32* %32
%34 = getelementptr inbounds [4 x i32], [4 x i32]* %6, i64 0, i64 1
%35 = tail call i32 @htonl(i64 %2)
store i32 %35, i32* %34
%36 = getelementptr inbounds [4 x i32], [4 x i32]* %6, i64 0, i64 2
%37 = bitcast i32* %36 to i64*
store i64 0, i64* %37
%38 = getelementptr inbounds %struct.iovec, %struct.iovec* %8, i64 0, i32 1
%39 = bitcast i32** %38 to i8**
store i8* %0, i8** %39
%40 = getelementptr inbounds %struct.iovec, %struct.iovec* %8, i64 0, i32 0
store i64 16, i64* %40
%41 = getelementptr inbounds %struct.iovec, %struct.iovec* %8, i64 1, i32 1
%42 = bitcast i32** %41 to i8**
store i8* %1, i8** %42
%43 = getelementptr inbounds %struct.iovec, %struct.iovec* %8, i64 1, i32 0
store i64 16, i64* %43
%44 = getelementptr inbounds %struct.iovec, %struct.iovec* %8, i64 2, i32 1
store i32* %32, i32** %44
%45 = getelementptr inbounds %struct.iovec, %struct.iovec* %8, i64 2, i32 0
store i64 8, i64* %45
%46 = trunc i64 %7 to i32
%47 = call i32 @in_cksum(%struct.iovec* %8, i32 %46)
ret i32 %47
48: ; preds = %48, %13
%49 = phi i64 [ 0, %13 ], [ %69, %48 ]
%50 = phi i64 [ 0, %13 ], [ %68, %48 ]
%51 = phi i64 [ 0, %13 ], [ %70, %48 ]
%52 = getelementptr inbounds %struct.iovec, %struct.iovec* %3, i64 %49, i32 1
%53 = load i32*, i32** %52
%54 = add i64 %49, 3
%55 = getelementptr inbounds %struct.iovec, %struct.iovec* %8, i64 %54, i32 1
store i32* %53, i32** %55
%56 = getelementptr inbounds %struct.iovec, %struct.iovec* %3, i64 %49, i32 0
%57 = load i64, i64* %56
%58 = getelementptr inbounds %struct.iovec, %struct.iovec* %8, i64 %54, i32 0
store i64 %57, i64* %58
%59 = add i64 %57, %50
%60 = or i64 %49, 1
%61 = getelementptr inbounds %struct.iovec, %struct.iovec* %3, i64 %60, i32 1
%62 = load i32*, i32** %61
%63 = add i64 %49, 4
%64 = getelementptr inbounds %struct.iovec, %struct.iovec* %8, i64 %63, i32 1
store i32* %62, i32** %64
%65 = getelementptr inbounds %struct.iovec, %struct.iovec* %3, i64 %60, i32 0
%66 = load i64, i64* %65
%67 = getelementptr inbounds %struct.iovec, %struct.iovec* %8, i64 %63, i32 0
store i64 %66, i64* %67
%68 = add i64 %66, %59
%69 = add nuw i64 %49, 2
%70 = add i64 %51, 2
%71 = icmp eq i64 %70, %14
br i1 %71, label %15, label %48
}