unsigned short crc16_single(unsigned char msg, unsigned short crc) {
  unsigned short i, j;
  unsigned short lsb;
  crc ^= msg;
  for (j = 0; j < 8; j++) {
    lsb = crc & 0x1;
    crc = crc >> 1;
    if (lsb)
      crc ^= 0xA001;
  }
  return crc;
}


x86 assembly (clang, -O0):
<crc16_single>:
push   %rbp
mov    %rsp,%rbp
mov    %si,%ax
mov    %dil,%cl
mov    %cl,-0x1(%rbp)
mov    %ax,-0x4(%rbp)
movzbl -0x1(%rbp),%ecx
movzwl -0x4(%rbp),%eax
xor    %ecx,%eax
mov    %ax,-0x4(%rbp)
movw   $0x0,-0x8(%rbp)
movzwl -0x8(%rbp),%eax
cmp    $0x8,%eax
jge    1176 <crc16_single+0x76>
movzwl -0x4(%rbp),%eax
and    $0x1,%eax
mov    %ax,-0xa(%rbp)
movzwl -0x4(%rbp),%eax
sar    $0x1,%eax
mov    %ax,-0x4(%rbp)
cmpw   $0x0,-0xa(%rbp)
je     1160 <crc16_single+0x60>
movzwl -0x4(%rbp),%eax
xor    $0xa001,%eax
mov    %ax,-0x4(%rbp)
jmp    1165 <crc16_single+0x65>
mov    -0x8(%rbp),%ax
add    $0x1,%ax
mov    %ax,-0x8(%rbp)
jmp    1125 <crc16_single+0x25>
movzwl -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<crc16_single>:
xor    %esi,%edi
mov    %edi,%eax
shr    %eax
mov    %eax,%ecx
xor    $0xffffa001,%ecx
test   $0x1,%dil
cmove  %eax,%ecx
movzwl %cx,%eax
shr    %eax
mov    %eax,%edx
xor    $0xffffa001,%edx
test   $0x1,%cl
cmove  %eax,%edx
movzwl %dx,%eax
shr    %eax
mov    %eax,%ecx
xor    $0xffffa001,%ecx
test   $0x1,%dl
cmove  %eax,%ecx
movzwl %cx,%eax
shr    %eax
mov    %eax,%edx
xor    $0xffffa001,%edx
test   $0x1,%cl
cmove  %eax,%edx
movzwl %dx,%eax
shr    %eax
mov    %eax,%ecx
xor    $0xffffa001,%ecx
test   $0x1,%dl
cmove  %eax,%ecx
movzwl %cx,%eax
shr    %eax
mov    %eax,%edx
xor    $0xffffa001,%edx
test   $0x1,%cl
cmove  %eax,%edx
movzwl %dx,%eax
shr    %eax
mov    %eax,%ecx
xor    $0xffffa001,%ecx
test   $0x1,%dl
cmove  %eax,%ecx
movzwl %cx,%edx
shr    %edx
mov    %edx,%eax
xor    $0xffffa001,%eax
test   $0x1,%cl
cmove  %edx,%eax
ret

LLVM IR (-O0):
define zeroext i16 @crc16_single(i8 zeroext %0, i16 zeroext %1) {
%3 = alloca i8
%4 = alloca i16
%5 = alloca i16
%6 = alloca i16
%7 = alloca i16
store i8 %0, i8* %3
store i16 %1, i16* %4
%8 = load i8, i8* %3
%9 = zext i8 %8 to i32
%10 = load i16, i16* %4
%11 = zext i16 %10 to i32
%12 = xor i32 %11, %9
%13 = trunc i32 %12 to i16
store i16 %13, i16* %4
store i16 0, i16* %6
br label %14
14: ; preds = %35, %2
%15 = load i16, i16* %6
%16 = zext i16 %15 to i32
%17 = icmp slt i32 %16, 8
br i1 %17, label %18, label %38
18: ; preds = %14
%19 = load i16, i16* %4
%20 = zext i16 %19 to i32
%21 = and i32 %20, 1
%22 = trunc i32 %21 to i16
store i16 %22, i16* %7
%23 = load i16, i16* %4
%24 = zext i16 %23 to i32
%25 = ashr i32 %24, 1
%26 = trunc i32 %25 to i16
store i16 %26, i16* %4
%27 = load i16, i16* %7
%28 = icmp ne i16 %27, 0
br i1 %28, label %29, label %34
29: ; preds = %18
%30 = load i16, i16* %4
%31 = zext i16 %30 to i32
%32 = xor i32 %31, 40961
%33 = trunc i32 %32 to i16
store i16 %33, i16* %4
br label %34
34: ; preds = %29, %18
br label %35
35: ; preds = %34
%36 = load i16, i16* %6
%37 = add i16 %36, 1
store i16 %37, i16* %6
br label %14
38: ; preds = %14
%39 = load i16, i16* %4
ret i16 %39
}

LLVM IR (-O2):
define zeroext i16 @crc16_single(i8 zeroext %0, i16 zeroext %1) {
%3 = zext i8 %0 to i16
%4 = xor i16 %3, %1
%5 = and i16 %4, 1
%6 = lshr i16 %4, 1
%7 = icmp eq i16 %5, 0
%8 = xor i16 %6, -24575
%9 = select i1 %7, i16 %6, i16 %8
%10 = and i16 %9, 1
%11 = lshr i16 %9, 1
%12 = icmp eq i16 %10, 0
%13 = xor i16 %11, -24575
%14 = select i1 %12, i16 %11, i16 %13
%15 = and i16 %14, 1
%16 = lshr i16 %14, 1
%17 = icmp eq i16 %15, 0
%18 = xor i16 %16, -24575
%19 = select i1 %17, i16 %16, i16 %18
%20 = and i16 %19, 1
%21 = lshr i16 %19, 1
%22 = icmp eq i16 %20, 0
%23 = xor i16 %21, -24575
%24 = select i1 %22, i16 %21, i16 %23
%25 = and i16 %24, 1
%26 = lshr i16 %24, 1
%27 = icmp eq i16 %25, 0
%28 = xor i16 %26, -24575
%29 = select i1 %27, i16 %26, i16 %28
%30 = and i16 %29, 1
%31 = lshr i16 %29, 1
%32 = icmp eq i16 %30, 0
%33 = xor i16 %31, -24575
%34 = select i1 %32, i16 %31, i16 %33
%35 = and i16 %34, 1
%36 = lshr i16 %34, 1
%37 = icmp eq i16 %35, 0
%38 = xor i16 %36, -24575
%39 = select i1 %37, i16 %36, i16 %38
%40 = and i16 %39, 1
%41 = lshr i16 %39, 1
%42 = icmp eq i16 %40, 0
%43 = xor i16 %41, -24575
%44 = select i1 %42, i16 %41, i16 %43
ret i16 %44
}