unsigned short _hz_update_crc16_sick(unsigned short crc16, unsigned char c,
                                     char prev_byte) {
  unsigned short crc = crc16;
  unsigned short short_c, short_p;
  short_c = 0x00FF & (unsigned short)c;
  short_p = (0x00FF & (unsigned short)prev_byte) << 8;
  if (crc & 0x8000)
    crc = (crc << 1) ^ 0x8005;
  else
    crc = crc << 1;
  crc &= 0xFFFF;
  crc ^= (short_c | short_p);
  return crc;
}


x86 assembly (clang, -O0):
<_hz_update_crc16_sick>:
push   %rbp
mov    %rsp,%rbp
mov    %dl,%al
mov    %sil,%cl
mov    %di,%dx
mov    %dx,-0x2(%rbp)
mov    %cl,-0x3(%rbp)
mov    %al,-0x4(%rbp)
mov    -0x2(%rbp),%ax
mov    %ax,-0x6(%rbp)
movzbl -0x3(%rbp),%eax
movzwl %ax,%eax
and    $0xff,%eax
mov    %ax,-0x8(%rbp)
movsbl -0x4(%rbp),%eax
movzwl %ax,%eax
and    $0xff,%eax
shl    $0x8,%eax
mov    %ax,-0xa(%rbp)
movzwl -0x6(%rbp),%eax
and    $0x8000,%eax
cmp    $0x0,%eax
je     1168 <_hz_update_crc16_sick+0x68>
movzwl -0x6(%rbp),%eax
shl    $0x1,%eax
xor    $0x8005,%eax
mov    %ax,-0x6(%rbp)
jmp    1173 <_hz_update_crc16_sick+0x73>
movzwl -0x6(%rbp),%eax
shl    $0x1,%eax
mov    %ax,-0x6(%rbp)
movzwl -0x6(%rbp),%eax
and    $0xffff,%eax
mov    %ax,-0x6(%rbp)
movzwl -0x8(%rbp),%ecx
movzwl -0xa(%rbp),%eax
or     %eax,%ecx
movzwl -0x6(%rbp),%eax
xor    %ecx,%eax
mov    %ax,-0x6(%rbp)
movzwl -0x6(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<_hz_update_crc16_sick>:
lea    (%rdi,%rdi,1),%eax
mov    %eax,%ecx
xor    $0xffff8005,%ecx
test   %di,%di
cmovns %eax,%ecx
shl    $0x8,%edx
lea    (%rdx,%rsi,1),%eax
xor    %ecx,%eax
ret

LLVM IR (-O0):
define zeroext i16 @_hz_update_crc16_sick(i16 zeroext %0, i8 zeroext %1, i8 signext %2) {
%4 = alloca i16
%5 = alloca i8
%6 = alloca i8
%7 = alloca i16
%8 = alloca i16
%9 = alloca i16
store i16 %0, i16* %4
store i8 %1, i8* %5
store i8 %2, i8* %6
%10 = load i16, i16* %4
store i16 %10, i16* %7
%11 = load i8, i8* %5
%12 = zext i8 %11 to i16
%13 = zext i16 %12 to i32
%14 = and i32 255, %13
%15 = trunc i32 %14 to i16
store i16 %15, i16* %8
%16 = load i8, i8* %6
%17 = sext i8 %16 to i16
%18 = zext i16 %17 to i32
%19 = and i32 255, %18
%20 = shl i32 %19, 8
%21 = trunc i32 %20 to i16
store i16 %21, i16* %9
%22 = load i16, i16* %7
%23 = zext i16 %22 to i32
%24 = and i32 %23, 32768
%25 = icmp ne i32 %24, 0
br i1 %25, label %26, label %32
26: ; preds = %3
%27 = load i16, i16* %7
%28 = zext i16 %27 to i32
%29 = shl i32 %28, 1
%30 = xor i32 %29, 32773
%31 = trunc i32 %30 to i16
store i16 %31, i16* %7
br label %37
32: ; preds = %3
%33 = load i16, i16* %7
%34 = zext i16 %33 to i32
%35 = shl i32 %34, 1
%36 = trunc i32 %35 to i16
store i16 %36, i16* %7
br label %37
37: ; preds = %32, %26
%38 = load i16, i16* %7
%39 = zext i16 %38 to i32
%40 = and i32 %39, 65535
%41 = trunc i32 %40 to i16
store i16 %41, i16* %7
%42 = load i16, i16* %8
%43 = zext i16 %42 to i32
%44 = load i16, i16* %9
%45 = zext i16 %44 to i32
%46 = or i32 %43, %45
%47 = load i16, i16* %7
%48 = zext i16 %47 to i32
%49 = xor i32 %48, %46
%50 = trunc i32 %49 to i16
store i16 %50, i16* %7
%51 = load i16, i16* %7
ret i16 %51
}

LLVM IR (-O2):
define zeroext i16 @_hz_update_crc16_sick(i16 zeroext %0, i8 zeroext %1, i8 signext %2) {
%4 = icmp sgt i16 %0, -1
%5 = shl i16 %0, 1
%6 = xor i16 %5, -32763
%7 = select i1 %4, i16 %5, i16 %6
%8 = zext i8 %2 to i16
%9 = shl nuw i16 %8, 8
%10 = zext i8 %1 to i16
%11 = or i16 %9, %10
%12 = xor i16 %11, %7
ret i16 %12
}