#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 int uint32_t;
typedef size_t crc;

/* Variables and functions */
uint32_t crc32_body(uint32_t crc, unsigned char const *buf, size_t len,
                    const uint32_t (*tab)[256]) {
  const uint32_t *b;
  size_t rem_len;
  if ((long)buf & 3 && len) {
    do {
      crc = tab[0][(crc ^ (*buf++)) & 255] ^ (crc >> 8);
    } while ((--len) && ((long)buf) & 3);
  }
  rem_len = len & 3;
  len = len >> 2;
  b = (const uint32_t *)buf;
  for (--b; len; --len) {
    crc ^= *++b;
    crc = tab[3][(crc)&255] ^ tab[2][(crc >> 8) & 255] ^
          tab[1][(crc >> 16) & 255] ^ tab[0][(crc >> 24) & 255];
  }
  len = rem_len;
  if (len) {
    uint8_t *p = (uint8_t *)(b + 1) - 1;
    do {
      crc = tab[0][(crc ^ (*++p)) & 255] ^ (crc >> 8);
    } while (--len);
  }
  return crc;
}


x86 assembly (clang, -O0):
<crc32_body>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    -0x10(%rbp),%rax
and    $0x3,%rax
cmp    $0x0,%rax
je     11a4 <crc32_body+0xa4>
cmpq   $0x0,-0x18(%rbp)
je     11a4 <crc32_body+0xa4>
jmp    1135 <crc32_body+0x35>
mov    -0x20(%rbp),%rax
mov    -0x4(%rbp),%ecx
mov    -0x10(%rbp),%rdx
mov    %rdx,%rsi
add    $0x1,%rsi
mov    %rsi,-0x10(%rbp)
movzbl (%rdx),%edx
xor    %edx,%ecx
and    $0xff,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,4),%eax
mov    -0x4(%rbp),%ecx
sar    $0x8,%ecx
xor    %ecx,%eax
mov    %eax,-0x4(%rbp)
mov    -0x18(%rbp),%rcx
add    $0xffffffffffffffff,%rcx
mov    %rcx,-0x18(%rbp)
xor    %eax,%eax
cmp    $0x0,%rcx
mov    %al,-0x39(%rbp)
je     1194 <crc32_body+0x94>
mov    -0x10(%rbp),%rax
and    $0x3,%rax
cmp    $0x0,%rax
setne  %al
mov    %al,-0x39(%rbp)
mov    -0x39(%rbp),%al
test   $0x1,%al
jne    1135 <crc32_body+0x35>
jmp    11a4 <crc32_body+0xa4>
mov    -0x18(%rbp),%rax
and    $0x3,%rax
mov    %rax,-0x30(%rbp)
mov    -0x18(%rbp),%rax
shr    $0x2,%rax
mov    %rax,-0x18(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x28(%rbp),%rax
add    $0xfffffffffffffffc,%rax
mov    %rax,-0x28(%rbp)
cmpq   $0x0,-0x18(%rbp)
je     1268 <crc32_body+0x168>
mov    -0x28(%rbp),%rax
mov    %rax,%rcx
add    $0x4,%rcx
mov    %rcx,-0x28(%rbp)
mov    0x4(%rax),%eax
xor    -0x4(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x20(%rbp),%rax
mov    -0x4(%rbp),%ecx
and    $0xff,%ecx
movslq %ecx,%rcx
mov    0xc00(%rax,%rcx,4),%eax
mov    -0x20(%rbp),%rcx
mov    -0x4(%rbp),%edx
sar    $0x8,%edx
and    $0xff,%edx
movslq %edx,%rdx
xor    0x800(%rcx,%rdx,4),%eax
mov    -0x20(%rbp),%rcx
mov    -0x4(%rbp),%edx
sar    $0x10,%edx
and    $0xff,%edx
movslq %edx,%rdx
xor    0x400(%rcx,%rdx,4),%eax
mov    -0x20(%rbp),%rcx
mov    -0x4(%rbp),%edx
sar    $0x18,%edx
and    $0xff,%edx
movslq %edx,%rdx
xor    (%rcx,%rdx,4),%eax
mov    %eax,-0x4(%rbp)
mov    -0x18(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x18(%rbp)
jmp    11d0 <crc32_body+0xd0>
mov    -0x30(%rbp),%rax
mov    %rax,-0x18(%rbp)
cmpq   $0x0,-0x18(%rbp)
je     12d6 <crc32_body+0x1d6>
mov    -0x28(%rbp),%rax
add    $0x4,%rax
add    $0xfffffffffffffffc,%rax
mov    %rax,-0x38(%rbp)
mov    -0x20(%rbp),%rax
mov    -0x4(%rbp),%ecx
mov    -0x38(%rbp),%rdx
mov    %rdx,%rsi
add    $0x4,%rsi
mov    %rsi,-0x38(%rbp)
xor    0x4(%rdx),%ecx
and    $0xff,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,4),%eax
mov    -0x4(%rbp),%ecx
sar    $0x8,%ecx
xor    %ecx,%eax
mov    %eax,-0x4(%rbp)
mov    -0x18(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x18(%rbp)
cmp    $0x0,%rax
jne    128b <crc32_body+0x18b>
jmp    12d6 <crc32_body+0x1d6>
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<crc32_body>:
push   %rbp
push   %rbx
mov    %edi,%eax
test   %rdx,%rdx
je     11b6 <crc32_body+0xb6>
mov    %esi,%edi
and    $0x3,%edi
test   %rdi,%rdi
je     11b6 <crc32_body+0xb6>
lea    0x1(%rsi),%r8
movzbl (%rsi),%r9d
movzbl %al,%edi
xor    %r9d,%edi
sar    $0x8,%eax
xor    (%rcx,%rdi,4),%eax
mov    %rdx,%r9
add    $0xffffffffffffffff,%r9
je     11b0 <crc32_body+0xb0>
mov    %r8d,%edi
and    $0x3,%edi
test   %rdi,%rdi
je     11b0 <crc32_body+0xb0>
lea    0x2(%rsi),%r8
movzbl 0x1(%rsi),%r9d
movzbl %al,%edi
xor    %r9d,%edi
sar    $0x8,%eax
xor    (%rcx,%rdi,4),%eax
mov    %rdx,%r9
add    $0xfffffffffffffffe,%r9
je     11b0 <crc32_body+0xb0>
mov    %r8d,%edi
and    $0x3,%edi
test   %rdi,%rdi
je     11b0 <crc32_body+0xb0>
lea    0x3(%rsi),%r8
movzbl 0x2(%rsi),%r9d
movzbl %al,%edi
xor    %r9d,%edi
sar    $0x8,%eax
xor    (%rcx,%rdi,4),%eax
mov    %rdx,%r9
add    $0xfffffffffffffffd,%r9
je     11b0 <crc32_body+0xb0>
mov    %r8d,%edi
and    $0x3,%edi
test   %rdi,%rdi
je     11b0 <crc32_body+0xb0>
movzbl 0x3(%rsi),%r8d
add    $0x4,%rsi
movzbl %al,%edi
xor    %r8d,%edi
sar    $0x8,%eax
xor    (%rcx,%rdi,4),%eax
add    $0xfffffffffffffffc,%rdx
jmp    11b6 <crc32_body+0xb6>
mov    %r9,%rdx
mov    %r8,%rsi
mov    %edx,%r8d
and    $0x3,%r8d
cmp    $0x4,%rdx
jae    11d1 <crc32_body+0xd1>
add    $0xfffffffffffffffc,%rsi
test   %r8,%r8
jne    1231 <crc32_body+0x131>
jmp    1267 <crc32_body+0x167>
mov    %rdx,%r9
shr    $0x2,%r9
add    $0xfffffffffffffffc,%rdx
and    $0xfffffffffffffffc,%rdx
add    %rsi,%rdx
xor    %edi,%edi
cs nopw 0x0(%rax,%rax,1)
nop
xor    (%rsi,%rdi,4),%eax
movzbl %al,%r10d
movzbl %ah,%ebp
mov    %eax,%ebx
mov    0x800(%rcx,%rbp,4),%ebp
xor    0xc00(%rcx,%r10,4),%ebp
shr    $0x10,%eax
movzbl %al,%eax
xor    0x400(%rcx,%rax,4),%ebp
shr    $0x18,%ebx
mov    %ebp,%eax
xor    (%rcx,%rbx,4),%eax
add    $0x1,%rdi
cmp    %rdi,%r9
jne    11f0 <crc32_body+0xf0>
mov    %rdx,%rsi
test   %r8,%r8
je     1267 <crc32_body+0x167>
mov    0x4(%rsi),%edx
xor    %eax,%edx
movzbl %dl,%edx
sar    $0x8,%eax
xor    (%rcx,%rdx,4),%eax
cmp    $0x1,%r8d
je     1267 <crc32_body+0x167>
mov    0x8(%rsi),%edx
xor    %eax,%edx
movzbl %dl,%edx
sar    $0x8,%eax
xor    (%rcx,%rdx,4),%eax
cmp    $0x2,%r8d
je     1267 <crc32_body+0x167>
mov    0xc(%rsi),%edx
xor    %eax,%edx
movzbl %dl,%edx
sar    $0x8,%eax
xor    (%rcx,%rdx,4),%eax
pop    %rbx
pop    %rbp
ret

LLVM IR (-O0):
define i32 @crc32_body(i32 %0, i8* %1, i64 %2, [256 x i32]* %3) {
%5 = alloca i32
%6 = alloca i8*
%7 = alloca i64
%8 = alloca [256 x i32]*
%9 = alloca i32*
%10 = alloca i64
%11 = alloca i32*
store i32 %0, i32* %5
store i8* %1, i8** %6
store i64 %2, i64* %7
store [256 x i32]* %3, [256 x i32]** %8
%12 = load i8*, i8** %6
%13 = ptrtoint i8* %12 to i64
%14 = and i64 %13, 3
%15 = icmp ne i64 %14, 0
br i1 %15, label %16, label %48
16: ; preds = %4
%17 = load i64, i64* %7
%18 = icmp ne i64 %17, 0
br i1 %18, label %19, label %48
19: ; preds = %16
br label %20
20: ; preds = %45, %19
%21 = load [256 x i32]*, [256 x i32]** %8
%22 = getelementptr inbounds [256 x i32], [256 x i32]* %21, i64 0
%23 = load i32, i32* %5
%24 = load i8*, i8** %6
%25 = getelementptr inbounds i8, i8* %24, i32 1
store i8* %25, i8** %6
%26 = load i8, i8* %24
%27 = zext i8 %26 to i32
%28 = xor i32 %23, %27
%29 = and i32 %28, 255
%30 = sext i32 %29 to i64
%31 = getelementptr inbounds [256 x i32], [256 x i32]* %22, i64 0, i64 %30
%32 = load i32, i32* %31
%33 = load i32, i32* %5
%34 = ashr i32 %33, 8
%35 = xor i32 %32, %34
store i32 %35, i32* %5
br label %36
36: ; preds = %20
%37 = load i64, i64* %7
%38 = add i64 %37, -1
store i64 %38, i64* %7
%39 = icmp ne i64 %38, 0
br i1 %39, label %40, label %45
40: ; preds = %36
%41 = load i8*, i8** %6
%42 = ptrtoint i8* %41 to i64
%43 = and i64 %42, 3
%44 = icmp ne i64 %43, 0
br label %45
45: ; preds = %40, %36
%46 = phi i1 [ false, %36 ], [ %44, %40 ]
br i1 %46, label %20, label %47
47: ; preds = %45
br label %48
48: ; preds = %47, %16, %4
%49 = load i64, i64* %7
%50 = and i64 %49, 3
store i64 %50, i64* %10
%51 = load i64, i64* %7
%52 = lshr i64 %51, 2
store i64 %52, i64* %7
%53 = load i8*, i8** %6
%54 = bitcast i8* %53 to i32*
store i32* %54, i32** %9
%55 = load i32*, i32** %9
%56 = getelementptr inbounds i32, i32* %55, i32 -1
store i32* %56, i32** %9
br label %57
57: ; preds = %100, %48
%58 = load i64, i64* %7
%59 = icmp ne i64 %58, 0
br i1 %59, label %60, label %103
60: ; preds = %57
%61 = load i32*, i32** %9
%62 = getelementptr inbounds i32, i32* %61, i32 1
store i32* %62, i32** %9
%63 = load i32, i32* %62
%64 = load i32, i32* %5
%65 = xor i32 %64, %63
store i32 %65, i32* %5
%66 = load [256 x i32]*, [256 x i32]** %8
%67 = getelementptr inbounds [256 x i32], [256 x i32]* %66, i64 3
%68 = load i32, i32* %5
%69 = and i32 %68, 255
%70 = sext i32 %69 to i64
%71 = getelementptr inbounds [256 x i32], [256 x i32]* %67, i64 0, i64 %70
%72 = load i32, i32* %71
%73 = load [256 x i32]*, [256 x i32]** %8
%74 = getelementptr inbounds [256 x i32], [256 x i32]* %73, i64 2
%75 = load i32, i32* %5
%76 = ashr i32 %75, 8
%77 = and i32 %76, 255
%78 = sext i32 %77 to i64
%79 = getelementptr inbounds [256 x i32], [256 x i32]* %74, i64 0, i64 %78
%80 = load i32, i32* %79
%81 = xor i32 %72, %80
%82 = load [256 x i32]*, [256 x i32]** %8
%83 = getelementptr inbounds [256 x i32], [256 x i32]* %82, i64 1
%84 = load i32, i32* %5
%85 = ashr i32 %84, 16
%86 = and i32 %85, 255
%87 = sext i32 %86 to i64
%88 = getelementptr inbounds [256 x i32], [256 x i32]* %83, i64 0, i64 %87
%89 = load i32, i32* %88
%90 = xor i32 %81, %89
%91 = load [256 x i32]*, [256 x i32]** %8
%92 = getelementptr inbounds [256 x i32], [256 x i32]* %91, i64 0
%93 = load i32, i32* %5
%94 = ashr i32 %93, 24
%95 = and i32 %94, 255
%96 = sext i32 %95 to i64
%97 = getelementptr inbounds [256 x i32], [256 x i32]* %92, i64 0, i64 %96
%98 = load i32, i32* %97
%99 = xor i32 %90, %98
store i32 %99, i32* %5
br label %100
100: ; preds = %60
%101 = load i64, i64* %7
%102 = add i64 %101, -1
store i64 %102, i64* %7
br label %57
103: ; preds = %57
%104 = load i64, i64* %10
store i64 %104, i64* %7
%105 = load i64, i64* %7
%106 = icmp ne i64 %105, 0
br i1 %106, label %107, label %131
107: ; preds = %103
%108 = load i32*, i32** %9
%109 = getelementptr inbounds i32, i32* %108, i64 1
%110 = getelementptr inbounds i32, i32* %109, i64 -1
store i32* %110, i32** %11
br label %111
111: ; preds = %126, %107
%112 = load [256 x i32]*, [256 x i32]** %8
%113 = getelementptr inbounds [256 x i32], [256 x i32]* %112, i64 0
%114 = load i32, i32* %5
%115 = load i32*, i32** %11
%116 = getelementptr inbounds i32, i32* %115, i32 1
store i32* %116, i32** %11
%117 = load i32, i32* %116
%118 = xor i32 %114, %117
%119 = and i32 %118, 255
%120 = sext i32 %119 to i64
%121 = getelementptr inbounds [256 x i32], [256 x i32]* %113, i64 0, i64 %120
%122 = load i32, i32* %121
%123 = load i32, i32* %5
%124 = ashr i32 %123, 8
%125 = xor i32 %122, %124
store i32 %125, i32* %5
br label %126
126: ; preds = %111
%127 = load i64, i64* %7
%128 = add i64 %127, -1
store i64 %128, i64* %7
%129 = icmp ne i64 %128, 0
br i1 %129, label %111, label %130
130: ; preds = %126
br label %131
131: ; preds = %130, %103
%132 = load i32, i32* %5
ret i32 %132
}

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