#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 int uint8_t;
typedef scalar_t__ uint16_t;

/* Variables and functions */
uint16_t gen_crc16(const uint8_t *data, uint16_t size) {
  uint16_t out = 0;
  int bits_read = 0, bit_flag;
  if (data == NULL)
    return 0;
  while (size > 0) {
    bit_flag = out >> 15;
    out <<= 1;
    out |= (*data >> bits_read) & 1;
    bits_read++;
    if (bits_read > 7) {
      bits_read = 0;
      data++;
      size--;
    }
    if (bit_flag)
      out ^= 0x8005;
  }
  int i;
  for (i = 0; i < 16; ++i) {
    bit_flag = out >> 15;
    out <<= 1;
    if (bit_flag)
      out ^= 0x8005;
  }
  uint16_t crc = 0;
  i = 0x8000;
  int j = 0x0001;
  for (; i != 0; i >>= 1, j <<= 1) {
    if (i & out)
      crc |= j;
  }
  return crc;
}


x86 assembly (clang, -O0):
<gen_crc16>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
movq   $0x0,-0x20(%rbp)
movl   $0x0,-0x24(%rbp)
cmpq   $0x0,-0x10(%rbp)
jne    1133 <gen_crc16+0x33>
movq   $0x0,-0x8(%rbp)
jmp    1276 <gen_crc16+0x176>
jmp    1138 <gen_crc16+0x38>
cmpq   $0x0,-0x18(%rbp)
jle    11c1 <gen_crc16+0xc1>
mov    -0x20(%rbp),%rax
sar    $0xf,%rax
mov    %eax,-0x28(%rbp)
mov    -0x20(%rbp),%rax
shl    $0x1,%rax
mov    %rax,-0x20(%rbp)
mov    -0x10(%rbp),%rax
mov    (%rax),%eax
mov    -0x24(%rbp),%ecx
sar    %cl,%eax
and    $0x1,%eax
cltq
or     -0x20(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
cmpl   $0x7,-0x24(%rbp)
jle    11a4 <gen_crc16+0xa4>
movl   $0x0,-0x24(%rbp)
mov    -0x10(%rbp),%rax
add    $0x4,%rax
mov    %rax,-0x10(%rbp)
mov    -0x18(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x18(%rbp)
cmpl   $0x0,-0x28(%rbp)
je     11bc <gen_crc16+0xbc>
mov    -0x20(%rbp),%rax
xor    $0x8005,%rax
mov    %rax,-0x20(%rbp)
jmp    1138 <gen_crc16+0x38>
movl   $0x0,-0x2c(%rbp)
cmpl   $0x10,-0x2c(%rbp)
jge    1214 <gen_crc16+0x114>
mov    -0x20(%rbp),%rax
sar    $0xf,%rax
mov    %eax,-0x28(%rbp)
mov    -0x20(%rbp),%rax
shl    $0x1,%rax
mov    %rax,-0x20(%rbp)
cmpl   $0x0,-0x28(%rbp)
je     1201 <gen_crc16+0x101>
mov    -0x20(%rbp),%rax
xor    $0x8005,%rax
mov    %rax,-0x20(%rbp)
jmp    1206 <gen_crc16+0x106>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    11c8 <gen_crc16+0xc8>
movq   $0x0,-0x38(%rbp)
movl   $0x8000,-0x2c(%rbp)
movl   $0x1,-0x3c(%rbp)
cmpl   $0x0,-0x2c(%rbp)
je     126e <gen_crc16+0x16e>
movslq -0x2c(%rbp),%rax
and    -0x20(%rbp),%rax
cmp    $0x0,%rax
je     1252 <gen_crc16+0x152>
movslq -0x3c(%rbp),%rax
or     -0x38(%rbp),%rax
mov    %rax,-0x38(%rbp)
jmp    1257 <gen_crc16+0x157>
mov    -0x2c(%rbp),%eax
sar    $0x1,%eax
mov    %eax,-0x2c(%rbp)
mov    -0x3c(%rbp),%eax
shl    $0x1,%eax
mov    %eax,-0x3c(%rbp)
jmp    122a <gen_crc16+0x12a>
mov    -0x38(%rbp),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<gen_crc16>:
test   %rdi,%rdi
je     1228 <gen_crc16+0x128>
movabs $0x7fffffff8000,%r8
test   %rsi,%rsi
jle    122b <gen_crc16+0x12b>
add    $0x1,%rsi
xor    %edx,%edx
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
mov    (%rdi),%eax
mov    %eax,%ecx
and    $0x1,%ecx
lea    (%rcx,%rdx,2),%r9
mov    %r9,%rcx
xor    $0x8005,%rcx
test   %r8,%rdx
cmove  %r9,%rcx
mov    %eax,%edx
shr    %edx
and    $0x1,%edx
lea    (%rdx,%rcx,2),%r9
mov    %r9,%rdx
xor    $0x8005,%rdx
test   %r8,%rcx
cmove  %r9,%rdx
mov    %eax,%ecx
shr    $0x2,%ecx
and    $0x1,%ecx
lea    (%rcx,%rdx,2),%r9
mov    %r9,%rcx
xor    $0x8005,%rcx
test   %r8,%rdx
cmove  %r9,%rcx
mov    %eax,%edx
shr    $0x3,%edx
and    $0x1,%edx
lea    (%rdx,%rcx,2),%r9
mov    %r9,%rdx
xor    $0x8005,%rdx
test   %r8,%rcx
cmove  %r9,%rdx
mov    %eax,%ecx
shr    $0x4,%ecx
and    $0x1,%ecx
lea    (%rcx,%rdx,2),%r9
mov    %r9,%rcx
xor    $0x8005,%rcx
test   %r8,%rdx
cmove  %r9,%rcx
mov    %eax,%edx
shr    $0x5,%edx
and    $0x1,%edx
lea    (%rdx,%rcx,2),%r9
mov    %r9,%rdx
xor    $0x8005,%rdx
test   %r8,%rcx
cmove  %r9,%rdx
mov    %eax,%ecx
shr    $0x6,%ecx
and    $0x1,%ecx
lea    (%rcx,%rdx,2),%r9
mov    %r9,%rcx
xor    $0x8005,%rcx
test   %r8,%rdx
cmove  %r9,%rcx
shr    $0x7,%eax
and    $0x1,%eax
lea    (%rax,%rcx,2),%rax
mov    %rax,%rdx
xor    $0x8005,%rdx
test   %r8,%rcx
cmove  %rax,%rdx
add    $0x4,%rdi
add    $0xffffffffffffffff,%rsi
cmp    $0x1,%rsi
jg     1130 <gen_crc16+0x30>
jmp    122d <gen_crc16+0x12d>
xor    %eax,%eax
ret
xor    %edx,%edx
lea    (%rdx,%rdx,1),%rcx
mov    %rcx,%rsi
xor    $0x8005,%rsi
test   %r8,%rdx
cmove  %rcx,%rsi
lea    (%rsi,%rsi,1),%rcx
mov    %rcx,%rdx
xor    $0x8005,%rdx
test   %r8,%rsi
cmove  %rcx,%rdx
lea    (%rdx,%rdx,1),%rcx
mov    %rcx,%rsi
xor    $0x8005,%rsi
test   %r8,%rdx
cmove  %rcx,%rsi
lea    (%rsi,%rsi,1),%rcx
mov    %rcx,%rdx
xor    $0x8005,%rdx
test   %r8,%rsi
cmove  %rcx,%rdx
lea    (%rdx,%rdx,1),%rcx
mov    %rcx,%rsi
xor    $0x8005,%rsi
test   %r8,%rdx
cmove  %rcx,%rsi
lea    (%rsi,%rsi,1),%rcx
mov    %rcx,%rdx
xor    $0x8005,%rdx
test   %r8,%rsi
cmove  %rcx,%rdx
lea    (%rdx,%rdx,1),%rcx
mov    %rcx,%rsi
xor    $0x8005,%rsi
test   %r8,%rdx
cmove  %rcx,%rsi
lea    (%rsi,%rsi,1),%rcx
mov    %rcx,%rdx
xor    $0x8005,%rdx
test   %r8,%rsi
cmove  %rcx,%rdx
lea    (%rdx,%rdx,1),%rcx
mov    %rcx,%rsi
xor    $0x8005,%rsi
test   %r8,%rdx
cmove  %rcx,%rsi
lea    (%rsi,%rsi,1),%rcx
mov    %rcx,%rdx
xor    $0x8005,%rdx
test   %r8,%rsi
cmove  %rcx,%rdx
lea    (%rdx,%rdx,1),%rcx
mov    %rcx,%rsi
xor    $0x8005,%rsi
test   %r8,%rdx
cmove  %rcx,%rsi
lea    (%rsi,%rsi,1),%rcx
mov    %rcx,%rdx
xor    $0x8005,%rdx
test   %r8,%rsi
cmove  %rcx,%rdx
lea    (%rdx,%rdx,1),%rcx
mov    %rcx,%rsi
xor    $0x8005,%rsi
test   %r8,%rdx
cmove  %rcx,%rsi
lea    (%rsi,%rsi,1),%rcx
mov    %rcx,%rdx
xor    $0x8005,%rdx
test   %r8,%rsi
cmove  %rcx,%rdx
lea    (%rdx,%rdx,1),%rcx
mov    %rcx,%rsi
xor    $0x8005,%rsi
test   %r8,%rdx
cmove  %rcx,%rsi
lea    (%rsi,%rsi,1),%ecx
mov    %ecx,%edx
xor    $0xffff8005,%edx
test   %r8,%rsi
cmove  %ecx,%edx
rol    $0x8,%dx
mov    %edx,%eax
and    $0xf0f,%eax
shl    $0x4,%eax
shr    $0x4,%edx
and    $0xf0f,%edx
or     %eax,%edx
mov    %edx,%eax
and    $0x3333,%eax
shr    $0x2,%edx
and    $0x3333,%edx
lea    (%rdx,%rax,4),%eax
mov    %eax,%ecx
and    $0x5555,%ecx
shr    %eax
and    $0x5555,%eax
lea    (%rax,%rcx,2),%eax
ret

LLVM IR (-O0):
define i64 @gen_crc16(i32* %0, i64 %1) {
%3 = alloca i64
%4 = alloca i32*
%5 = alloca i64
%6 = alloca i64
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32
%10 = alloca i64
%11 = alloca i32
store i32* %0, i32** %4
store i64 %1, i64* %5
store i64 0, i64* %6
store i32 0, i32* %7
%12 = load i32*, i32** %4
%13 = icmp eq i32* %12, null
br i1 %13, label %14, label %15
14: ; preds = %2
store i64 0, i64* %3
br label %91
15: ; preds = %2
br label %16
16: ; preds = %48, %15
%17 = load i64, i64* %5
%18 = icmp sgt i64 %17, 0
br i1 %18, label %19, label %49
19: ; preds = %16
%20 = load i64, i64* %6
%21 = ashr i64 %20, 15
%22 = trunc i64 %21 to i32
store i32 %22, i32* %8
%23 = load i64, i64* %6
%24 = shl i64 %23, 1
store i64 %24, i64* %6
%25 = load i32*, i32** %4
%26 = load i32, i32* %25
%27 = load i32, i32* %7
%28 = ashr i32 %26, %27
%29 = and i32 %28, 1
%30 = sext i32 %29 to i64
%31 = load i64, i64* %6
%32 = or i64 %31, %30
store i64 %32, i64* %6
%33 = load i32, i32* %7
%34 = add nsw i32 %33, 1
store i32 %34, i32* %7
%35 = load i32, i32* %7
%36 = icmp sgt i32 %35, 7
br i1 %36, label %37, label %42
37: ; preds = %19
store i32 0, i32* %7
%38 = load i32*, i32** %4
%39 = getelementptr inbounds i32, i32* %38, i32 1
store i32* %39, i32** %4
%40 = load i64, i64* %5
%41 = add nsw i64 %40, -1
store i64 %41, i64* %5
br label %42
42: ; preds = %37, %19
%43 = load i32, i32* %8
%44 = icmp ne i32 %43, 0
br i1 %44, label %45, label %48
45: ; preds = %42
%46 = load i64, i64* %6
%47 = xor i64 %46, 32773
store i64 %47, i64* %6
br label %48
48: ; preds = %45, %42
br label %16
49: ; preds = %16
store i32 0, i32* %9
br label %50
50: ; preds = %65, %49
%51 = load i32, i32* %9
%52 = icmp slt i32 %51, 16
br i1 %52, label %53, label %68
53: ; preds = %50
%54 = load i64, i64* %6
%55 = ashr i64 %54, 15
%56 = trunc i64 %55 to i32
store i32 %56, i32* %8
%57 = load i64, i64* %6
%58 = shl i64 %57, 1
store i64 %58, i64* %6
%59 = load i32, i32* %8
%60 = icmp ne i32 %59, 0
br i1 %60, label %61, label %64
61: ; preds = %53
%62 = load i64, i64* %6
%63 = xor i64 %62, 32773
store i64 %63, i64* %6
br label %64
64: ; preds = %61, %53
br label %65
65: ; preds = %64
%66 = load i32, i32* %9
%67 = add nsw i32 %66, 1
store i32 %67, i32* %9
br label %50
68: ; preds = %50
store i64 0, i64* %10
store i32 32768, i32* %9
store i32 1, i32* %11
br label %69
69: ; preds = %84, %68
%70 = load i32, i32* %9
%71 = icmp ne i32 %70, 0
br i1 %71, label %72, label %89
72: ; preds = %69
%73 = load i32, i32* %9
%74 = sext i32 %73 to i64
%75 = load i64, i64* %6
%76 = and i64 %74, %75
%77 = icmp ne i64 %76, 0
br i1 %77, label %78, label %83
78: ; preds = %72
%79 = load i32, i32* %11
%80 = sext i32 %79 to i64
%81 = load i64, i64* %10
%82 = or i64 %81, %80
store i64 %82, i64* %10
br label %83
83: ; preds = %78, %72
br label %84
84: ; preds = %83
%85 = load i32, i32* %9
%86 = ashr i32 %85, 1
store i32 %86, i32* %9
%87 = load i32, i32* %11
%88 = shl i32 %87, 1
store i32 %88, i32* %11
br label %69
89: ; preds = %69
%90 = load i64, i64* %10
store i64 %90, i64* %3
br label %91
91: ; preds = %89, %14
%92 = load i64, i64* %3
ret i64 %92
}

LLVM IR (-O2):
define i64 @gen_crc16(i32* %0, i64 %1) {
%3 = icmp eq i32* %0, null
br i1 %3, label %170, label %4
4: ; preds = %2
%5 = icmp sgt i64 %1, 0
br i1 %5, label %91, label %6
6: ; preds = %91, %4
%7 = phi i64 [ 0, %4 ], [ %166, %91 ]
%8 = shl i64 %7, 1
%9 = and i64 %7, 140737488322560
%10 = icmp eq i64 %9, 0
%11 = xor i64 %8, 32773
%12 = select i1 %10, i64 %8, i64 %11
%13 = shl i64 %12, 1
%14 = and i64 %12, 140737488322560
%15 = icmp eq i64 %14, 0
%16 = xor i64 %13, 32773
%17 = select i1 %15, i64 %13, i64 %16
%18 = shl i64 %17, 1
%19 = and i64 %17, 140737488322560
%20 = icmp eq i64 %19, 0
%21 = xor i64 %18, 32773
%22 = select i1 %20, i64 %18, i64 %21
%23 = shl i64 %22, 1
%24 = and i64 %22, 140737488322560
%25 = icmp eq i64 %24, 0
%26 = xor i64 %23, 32773
%27 = select i1 %25, i64 %23, i64 %26
%28 = shl i64 %27, 1
%29 = and i64 %27, 140737488322560
%30 = icmp eq i64 %29, 0
%31 = xor i64 %28, 32773
%32 = select i1 %30, i64 %28, i64 %31
%33 = shl i64 %32, 1
%34 = and i64 %32, 140737488322560
%35 = icmp eq i64 %34, 0
%36 = xor i64 %33, 32773
%37 = select i1 %35, i64 %33, i64 %36
%38 = shl i64 %37, 1
%39 = and i64 %37, 140737488322560
%40 = icmp eq i64 %39, 0
%41 = xor i64 %38, 32773
%42 = select i1 %40, i64 %38, i64 %41
%43 = shl i64 %42, 1
%44 = and i64 %42, 140737488322560
%45 = icmp eq i64 %44, 0
%46 = xor i64 %43, 32773
%47 = select i1 %45, i64 %43, i64 %46
%48 = shl i64 %47, 1
%49 = and i64 %47, 140737488322560
%50 = icmp eq i64 %49, 0
%51 = xor i64 %48, 32773
%52 = select i1 %50, i64 %48, i64 %51
%53 = shl i64 %52, 1
%54 = and i64 %52, 140737488322560
%55 = icmp eq i64 %54, 0
%56 = xor i64 %53, 32773
%57 = select i1 %55, i64 %53, i64 %56
%58 = shl i64 %57, 1
%59 = and i64 %57, 140737488322560
%60 = icmp eq i64 %59, 0
%61 = xor i64 %58, 32773
%62 = select i1 %60, i64 %58, i64 %61
%63 = shl i64 %62, 1
%64 = and i64 %62, 140737488322560
%65 = icmp eq i64 %64, 0
%66 = xor i64 %63, 32773
%67 = select i1 %65, i64 %63, i64 %66
%68 = shl i64 %67, 1
%69 = and i64 %67, 140737488322560
%70 = icmp eq i64 %69, 0
%71 = xor i64 %68, 32773
%72 = select i1 %70, i64 %68, i64 %71
%73 = shl i64 %72, 1
%74 = and i64 %72, 140737488322560
%75 = icmp eq i64 %74, 0
%76 = xor i64 %73, 32773
%77 = select i1 %75, i64 %73, i64 %76
%78 = shl i64 %77, 1
%79 = and i64 %77, 140737488322560
%80 = icmp eq i64 %79, 0
%81 = xor i64 %78, 32773
%82 = select i1 %80, i64 %78, i64 %81
%83 = shl i64 %82, 1
%84 = and i64 %82, 140737488322560
%85 = icmp eq i64 %84, 0
%86 = xor i64 %83, 32773
%87 = select i1 %85, i64 %83, i64 %86
%88 = trunc i64 %87 to i16
%89 = call i16 @llvm.bitreverse.i16(i16 %88)
%90 = zext i16 %89 to i64
br label %170
91: ; preds = %4, %91
%92 = phi i64 [ %166, %91 ], [ 0, %4 ]
%93 = phi i64 [ %167, %91 ], [ %1, %4 ]
%94 = phi i32* [ %168, %91 ], [ %0, %4 ]
%95 = shl i64 %92, 1
%96 = load i32, i32* %94
%97 = and i32 %96, 1
%98 = zext i32 %97 to i64
%99 = or i64 %95, %98
%100 = and i64 %92, 140737488322560
%101 = icmp eq i64 %100, 0
%102 = xor i64 %99, 32773
%103 = select i1 %101, i64 %99, i64 %102
%104 = shl i64 %103, 1
%105 = lshr i32 %96, 1
%106 = and i32 %105, 1
%107 = zext i32 %106 to i64
%108 = or i64 %104, %107
%109 = and i64 %103, 140737488322560
%110 = icmp eq i64 %109, 0
%111 = xor i64 %108, 32773
%112 = select i1 %110, i64 %108, i64 %111
%113 = shl i64 %112, 1
%114 = lshr i32 %96, 2
%115 = and i32 %114, 1
%116 = zext i32 %115 to i64
%117 = or i64 %113, %116
%118 = and i64 %112, 140737488322560
%119 = icmp eq i64 %118, 0
%120 = xor i64 %117, 32773
%121 = select i1 %119, i64 %117, i64 %120
%122 = shl i64 %121, 1
%123 = lshr i32 %96, 3
%124 = and i32 %123, 1
%125 = zext i32 %124 to i64
%126 = or i64 %122, %125
%127 = and i64 %121, 140737488322560
%128 = icmp eq i64 %127, 0
%129 = xor i64 %126, 32773
%130 = select i1 %128, i64 %126, i64 %129
%131 = shl i64 %130, 1
%132 = lshr i32 %96, 4
%133 = and i32 %132, 1
%134 = zext i32 %133 to i64
%135 = or i64 %131, %134
%136 = and i64 %130, 140737488322560
%137 = icmp eq i64 %136, 0
%138 = xor i64 %135, 32773
%139 = select i1 %137, i64 %135, i64 %138
%140 = shl i64 %139, 1
%141 = lshr i32 %96, 5
%142 = and i32 %141, 1
%143 = zext i32 %142 to i64
%144 = or i64 %140, %143
%145 = and i64 %139, 140737488322560
%146 = icmp eq i64 %145, 0
%147 = xor i64 %144, 32773
%148 = select i1 %146, i64 %144, i64 %147
%149 = shl i64 %148, 1
%150 = lshr i32 %96, 6
%151 = and i32 %150, 1
%152 = zext i32 %151 to i64
%153 = or i64 %149, %152
%154 = and i64 %148, 140737488322560
%155 = icmp eq i64 %154, 0
%156 = xor i64 %153, 32773
%157 = select i1 %155, i64 %153, i64 %156
%158 = shl i64 %157, 1
%159 = lshr i32 %96, 7
%160 = and i32 %159, 1
%161 = zext i32 %160 to i64
%162 = or i64 %158, %161
%163 = and i64 %157, 140737488322560
%164 = icmp eq i64 %163, 0
%165 = xor i64 %162, 32773
%166 = select i1 %164, i64 %162, i64 %165
%167 = add nsw i64 %93, -1
%168 = getelementptr inbounds i32, i32* %94, i64 1
%169 = icmp sgt i64 %93, 1
br i1 %169, label %91, label %6
170: ; preds = %6, %2
%171 = phi i64 [ 0, %2 ], [ %90, %6 ]
ret i64 %171
}