unsigned short crc_ccitt(unsigned short *data, short num) {
  short byte_idx, bit_idx;
  unsigned short _crc, _dat;
  const unsigned short poly = 0x8D;
  unsigned short crc = 0xFF;
  for (byte_idx = 0; byte_idx < num; byte_idx++) {
    _dat = data[byte_idx];
    for (bit_idx = 0; bit_idx < 8; bit_idx++) {
      _crc = crc;
      crc <<= 1;
      if (_dat & 0x80)
        crc++;
      _dat <<= 1;
      if (_crc & 0x80)
        crc ^= poly;
    }
  }
  for (bit_idx = 0; bit_idx < 8; bit_idx++) {
    _crc = crc;
    crc = crc << 1;
    if (_crc & 0x80)
      crc ^= poly;
  }
  return crc;
}


x86 assembly (clang, -O0):
<crc_ccitt>:
push   %rbp
mov    %rsp,%rbp
mov    %si,%ax
mov    %rdi,-0x8(%rbp)
mov    %ax,-0xa(%rbp)
movw   $0x8d,-0x14(%rbp)
movw   $0xff,-0x16(%rbp)
movw   $0x0,-0xc(%rbp)
movswl -0xc(%rbp),%eax
movswl -0xa(%rbp),%ecx
cmp    %ecx,%eax
jge    11dc <crc_ccitt+0xdc>
mov    -0x8(%rbp),%rax
movswq -0xc(%rbp),%rcx
mov    (%rax,%rcx,2),%ax
mov    %ax,-0x12(%rbp)
movw   $0x0,-0xe(%rbp)
movswl -0xe(%rbp),%eax
cmp    $0x8,%eax
jge    11c6 <crc_ccitt+0xc6>
mov    -0x16(%rbp),%ax
mov    %ax,-0x10(%rbp)
movzwl -0x16(%rbp),%eax
shl    $0x1,%eax
mov    %ax,-0x16(%rbp)
movzwl -0x12(%rbp),%eax
and    $0x80,%eax
cmp    $0x0,%eax
je     1186 <crc_ccitt+0x86>
mov    -0x16(%rbp),%ax
add    $0x1,%ax
mov    %ax,-0x16(%rbp)
movzwl -0x12(%rbp),%eax
shl    $0x1,%eax
mov    %ax,-0x12(%rbp)
movzwl -0x10(%rbp),%eax
and    $0x80,%eax
cmp    $0x0,%eax
je     11b0 <crc_ccitt+0xb0>
movzwl -0x16(%rbp),%eax
xor    $0x8d,%eax
mov    %ax,-0x16(%rbp)
jmp    11b5 <crc_ccitt+0xb5>
mov    -0xe(%rbp),%ax
add    $0x1,%ax
mov    %ax,-0xe(%rbp)
jmp    1148 <crc_ccitt+0x48>
jmp    11cb <crc_ccitt+0xcb>
mov    -0xc(%rbp),%ax
add    $0x1,%ax
mov    %ax,-0xc(%rbp)
jmp    1121 <crc_ccitt+0x21>
movw   $0x0,-0xe(%rbp)
movswl -0xe(%rbp),%eax
cmp    $0x8,%eax
jge    1237 <crc_ccitt+0x137>
mov    -0x16(%rbp),%ax
mov    %ax,-0x10(%rbp)
movzwl -0x16(%rbp),%eax
shl    $0x1,%eax
mov    %ax,-0x16(%rbp)
movzwl -0x10(%rbp),%eax
and    $0x80,%eax
cmp    $0x0,%eax
je     1221 <crc_ccitt+0x121>
movzwl -0x16(%rbp),%eax
xor    $0x8d,%eax
mov    %ax,-0x16(%rbp)
jmp    1226 <crc_ccitt+0x126>
mov    -0xe(%rbp),%ax
add    $0x1,%ax
mov    %ax,-0xe(%rbp)
jmp    11e2 <crc_ccitt+0xe2>
movzwl -0x16(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<crc_ccitt>:
test   %si,%si
jle    11fa <crc_ccitt+0xfa>
movzwl %si,%r8d
mov    $0xff,%si
xor    %r9d,%r9d
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movzwl (%rdi,%r9,2),%eax
mov    %eax,%edx
shr    $0x7,%edx
and    $0x1,%edx
lea    (%rdx,%rsi,2),%edx
mov    %edx,%ecx
xor    $0x8d,%ecx
test   $0x80,%sil
cmove  %edx,%ecx
mov    %eax,%edx
shr    $0x6,%edx
and    $0x1,%edx
lea    (%rdx,%rcx,2),%edx
mov    %edx,%esi
xor    $0x8d,%esi
test   $0x80,%cl
cmove  %edx,%esi
mov    %eax,%ecx
shr    $0x5,%ecx
and    $0x1,%ecx
lea    (%rcx,%rsi,2),%ecx
mov    %ecx,%edx
xor    $0x8d,%edx
test   $0x80,%sil
cmove  %ecx,%edx
mov    %eax,%ecx
shr    $0x4,%ecx
and    $0x1,%ecx
lea    (%rcx,%rdx,2),%ecx
mov    %ecx,%esi
xor    $0x8d,%esi
test   $0x80,%dl
cmove  %ecx,%esi
mov    %eax,%ecx
shr    $0x3,%ecx
and    $0x1,%ecx
lea    (%rcx,%rsi,2),%ecx
mov    %ecx,%edx
xor    $0x8d,%edx
test   $0x80,%sil
cmove  %ecx,%edx
mov    %eax,%ecx
shr    $0x2,%ecx
and    $0x1,%ecx
lea    (%rcx,%rdx,2),%ecx
mov    %ecx,%esi
xor    $0x8d,%esi
test   $0x80,%dl
cmove  %ecx,%esi
mov    %eax,%ecx
shr    %ecx
and    $0x1,%ecx
lea    (%rcx,%rsi,2),%ecx
mov    %ecx,%edx
xor    $0x8d,%edx
test   $0x80,%sil
cmove  %ecx,%edx
and    $0x1,%eax
lea    (%rax,%rdx,2),%eax
mov    %eax,%esi
xor    $0x8d,%esi
test   $0x80,%dl
cmove  %eax,%esi
add    $0x1,%r9
cmp    %r9,%r8
jne    1120 <crc_ccitt+0x20>
jmp    11fe <crc_ccitt+0xfe>
mov    $0xff,%si
lea    (%rsi,%rsi,1),%eax
mov    %eax,%ecx
xor    $0x8d,%ecx
test   $0x80,%sil
cmove  %eax,%ecx
lea    (%rcx,%rcx,1),%eax
mov    %eax,%edx
xor    $0x8d,%edx
test   $0x80,%cl
cmove  %eax,%edx
lea    (%rdx,%rdx,1),%eax
mov    %eax,%ecx
xor    $0x8d,%ecx
test   $0x80,%dl
cmove  %eax,%ecx
lea    (%rcx,%rcx,1),%eax
mov    %eax,%edx
xor    $0x8d,%edx
test   $0x80,%cl
cmove  %eax,%edx
lea    (%rdx,%rdx,1),%eax
mov    %eax,%ecx
xor    $0x8d,%ecx
test   $0x80,%dl
cmove  %eax,%ecx
lea    (%rcx,%rcx,1),%eax
mov    %eax,%edx
xor    $0x8d,%edx
test   $0x80,%cl
cmove  %eax,%edx
lea    (%rdx,%rdx,1),%eax
mov    %eax,%ecx
xor    $0x8d,%ecx
test   $0x80,%dl
cmove  %eax,%ecx
lea    (%rcx,%rcx,1),%edx
mov    %edx,%eax
xor    $0x8d,%eax
test   $0x80,%cl
cmove  %edx,%eax
ret

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

LLVM IR (-O2):
define zeroext i16 @crc_ccitt(i16* nocapture %0, i16 signext %1) {
%3 = icmp sgt i16 %1, 0
br i1 %3, label %4, label %6
4: ; preds = %2
%5 = zext i16 %1 to i64
br label %48
6: ; preds = %48, %2
%7 = phi i16 [ 255, %2 ], [ %115, %48 ]
%8 = shl i16 %7, 1
%9 = and i16 %7, 128
%10 = icmp eq i16 %9, 0
%11 = xor i16 %8, 141
%12 = select i1 %10, i16 %8, i16 %11
%13 = shl i16 %12, 1
%14 = and i16 %12, 128
%15 = icmp eq i16 %14, 0
%16 = xor i16 %13, 141
%17 = select i1 %15, i16 %13, i16 %16
%18 = shl i16 %17, 1
%19 = and i16 %17, 128
%20 = icmp eq i16 %19, 0
%21 = xor i16 %18, 141
%22 = select i1 %20, i16 %18, i16 %21
%23 = shl i16 %22, 1
%24 = and i16 %22, 128
%25 = icmp eq i16 %24, 0
%26 = xor i16 %23, 141
%27 = select i1 %25, i16 %23, i16 %26
%28 = shl i16 %27, 1
%29 = and i16 %27, 128
%30 = icmp eq i16 %29, 0
%31 = xor i16 %28, 141
%32 = select i1 %30, i16 %28, i16 %31
%33 = shl i16 %32, 1
%34 = and i16 %32, 128
%35 = icmp eq i16 %34, 0
%36 = xor i16 %33, 141
%37 = select i1 %35, i16 %33, i16 %36
%38 = shl i16 %37, 1
%39 = and i16 %37, 128
%40 = icmp eq i16 %39, 0
%41 = xor i16 %38, 141
%42 = select i1 %40, i16 %38, i16 %41
%43 = shl i16 %42, 1
%44 = and i16 %42, 128
%45 = icmp eq i16 %44, 0
%46 = xor i16 %43, 141
%47 = select i1 %45, i16 %43, i16 %46
ret i16 %47
48: ; preds = %4, %48
%49 = phi i64 [ 0, %4 ], [ %116, %48 ]
%50 = phi i16 [ 255, %4 ], [ %115, %48 ]
%51 = getelementptr inbounds i16, i16* %0, i64 %49
%52 = load i16, i16* %51
%53 = shl i16 %50, 1
%54 = lshr i16 %52, 7
%55 = and i16 %54, 1
%56 = or i16 %55, %53
%57 = and i16 %50, 128
%58 = icmp eq i16 %57, 0
%59 = xor i16 %56, 141
%60 = select i1 %58, i16 %56, i16 %59
%61 = shl i16 %60, 1
%62 = lshr i16 %52, 6
%63 = and i16 %62, 1
%64 = or i16 %63, %61
%65 = and i16 %60, 128
%66 = icmp eq i16 %65, 0
%67 = xor i16 %64, 141
%68 = select i1 %66, i16 %64, i16 %67
%69 = shl i16 %68, 1
%70 = lshr i16 %52, 5
%71 = and i16 %70, 1
%72 = or i16 %71, %69
%73 = and i16 %68, 128
%74 = icmp eq i16 %73, 0
%75 = xor i16 %72, 141
%76 = select i1 %74, i16 %72, i16 %75
%77 = shl i16 %76, 1
%78 = lshr i16 %52, 4
%79 = and i16 %78, 1
%80 = or i16 %79, %77
%81 = and i16 %76, 128
%82 = icmp eq i16 %81, 0
%83 = xor i16 %80, 141
%84 = select i1 %82, i16 %80, i16 %83
%85 = shl i16 %84, 1
%86 = lshr i16 %52, 3
%87 = and i16 %86, 1
%88 = or i16 %87, %85
%89 = and i16 %84, 128
%90 = icmp eq i16 %89, 0
%91 = xor i16 %88, 141
%92 = select i1 %90, i16 %88, i16 %91
%93 = shl i16 %92, 1
%94 = lshr i16 %52, 2
%95 = and i16 %94, 1
%96 = or i16 %95, %93
%97 = and i16 %92, 128
%98 = icmp eq i16 %97, 0
%99 = xor i16 %96, 141
%100 = select i1 %98, i16 %96, i16 %99
%101 = shl i16 %100, 1
%102 = lshr i16 %52, 1
%103 = and i16 %102, 1
%104 = or i16 %103, %101
%105 = and i16 %100, 128
%106 = icmp eq i16 %105, 0
%107 = xor i16 %104, 141
%108 = select i1 %106, i16 %104, i16 %107
%109 = shl i16 %108, 1
%110 = and i16 %52, 1
%111 = or i16 %110, %109
%112 = and i16 %108, 128
%113 = icmp eq i16 %112, 0
%114 = xor i16 %111, 141
%115 = select i1 %113, i16 %111, i16 %114
%116 = add nuw nsw i64 %49, 1
%117 = icmp eq i64 %116, %5
br i1 %117, label %6, label %48
}