#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 /*<<< orphan*/ uint64_t;
typedef int /*<<< orphan*/ const __m128i;

/* Variables and functions */
int /*<<< orphan*/ const _mm_clmulepi64_si128(int /*<<< orphan*/ const,
                                              int /*<<< orphan*/, int);
int /*<<< orphan*/ _mm_cvtsi128_si64(int /*<<< orphan*/ const);
int /*<<< orphan*/ _mm_cvtsi64_si128(int);
int /*<<< orphan*/ _mm_setr_epi8(int /*<<< orphan*/, int, int, int, int, int,
                                 int, int, int, int, int, int, int, int, int,
                                 int);
int /*<<< orphan*/ const _mm_shuffle_epi8(int /*<<< orphan*/,
                                          int /*<<< orphan*/);
int /*<<< orphan*/ _mm_srli_si128(int /*<<< orphan*/ const, int);
int /*<<< orphan*/ const _mm_xor_si128(int /*<<< orphan*/ const,
                                       int /*<<< orphan*/ const);
uint64_t reduce(__m128i a) {
  const __m128i z = _mm_clmulepi64_si128(a, _mm_cvtsi64_si128(27), 0x01);
  const __m128i y =
      _mm_shuffle_epi8(_mm_setr_epi8(0, 27, 54, 45, 108, 119, 90, 65, 216, 195,
                                     238, 245, 180, 175, 130, 153),
                       _mm_srli_si128(z, 8));
  const __m128i x = _mm_xor_si128(a, _mm_xor_si128(y, z));
  return (uint64_t)_mm_cvtsi128_si64(x);
}


x86 assembly (clang, -O0):
<reduce>:
push   %rbp
mov    %rsp,%rbp
sub    $0x70,%rsp
mov    %edi,-0x4(%rbp)
mov    -0x4(%rbp),%eax
mov    %eax,-0x1c(%rbp)
mov    $0x1b,%edi
call   1080 <_mm_cvtsi64_si128@plt>
mov    -0x1c(%rbp),%edi
mov    %eax,%esi
mov    $0x1,%edx
call   1030 <_mm_clmulepi64_si128@plt>
mov    %eax,-0x8(%rbp)
xor    %edi,%edi
mov    $0x1b,%esi
mov    $0x36,%edx
mov    $0x2d,%ecx
mov    $0x6c,%r8d
mov    $0x77,%r9d
movl   $0x5a,(%rsp)
movl   $0x41,0x8(%rsp)
movl   $0xd8,0x10(%rsp)
movl   $0xc3,0x18(%rsp)
movl   $0xee,0x20(%rsp)
movl   $0xf5,0x28(%rsp)
movl   $0xb4,0x30(%rsp)
movl   $0xaf,0x38(%rsp)
movl   $0x82,0x40(%rsp)
movl   $0x99,0x48(%rsp)
call   1050 <_mm_setr_epi8@plt>
mov    %eax,-0x18(%rbp)
mov    -0x8(%rbp),%edi
mov    $0x8,%esi
call   1070 <_mm_srli_si128@plt>
mov    -0x18(%rbp),%edi
mov    %eax,%esi
call   1040 <_mm_shuffle_epi8@plt>
mov    %eax,-0xc(%rbp)
mov    -0x4(%rbp),%eax
mov    %eax,-0x14(%rbp)
mov    -0xc(%rbp),%edi
mov    -0x8(%rbp),%esi
call   1090 <_mm_xor_si128@plt>
mov    -0x14(%rbp),%edi
mov    %eax,%esi
call   1090 <_mm_xor_si128@plt>
mov    %eax,-0x10(%rbp)
mov    -0x10(%rbp),%edi
call   1060 <_mm_cvtsi128_si64@plt>
add    $0x70,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<reduce>:
push   %rbp
push   %r14
push   %rbx
mov    %edi,%r14d
mov    $0x1b,%edi
call   1080 <_mm_cvtsi64_si128@plt>
mov    %r14d,%edi
mov    %eax,%esi
mov    $0x1,%edx
call   1030 <_mm_clmulepi64_si128@plt>
mov    %eax,%ebp
xor    %edi,%edi
mov    $0x1b,%esi
mov    $0x36,%edx
mov    $0x2d,%ecx
mov    $0x6c,%r8d
mov    $0x77,%r9d
push   $0x99
push   $0x82
push   $0xaf
push   $0xb4
push   $0xf5
push   $0xee
push   $0xc3
push   $0xd8
push   $0x41
push   $0x5a
call   1050 <_mm_setr_epi8@plt>
add    $0x50,%rsp
mov    %eax,%ebx
mov    %ebp,%edi
mov    $0x8,%esi
call   1070 <_mm_srli_si128@plt>
mov    %ebx,%edi
mov    %eax,%esi
call   1040 <_mm_shuffle_epi8@plt>
mov    %eax,%edi
mov    %ebp,%esi
call   1090 <_mm_xor_si128@plt>
mov    %r14d,%edi
mov    %eax,%esi
call   1090 <_mm_xor_si128@plt>
mov    %eax,%edi
pop    %rbx
pop    %r14
pop    %rbp
jmp    1060 <_mm_cvtsi128_si64@plt>

LLVM IR (-O0):
define i32 @reduce(i32 %0) {
%2 = alloca i32
%3 = alloca i32
%4 = alloca i32
%5 = alloca i32
store i32 %0, i32* %2
%6 = load i32, i32* %2
%7 = call i32 @_mm_cvtsi64_si128(i32 27)
%8 = call i32 @_mm_clmulepi64_si128(i32 %6, i32 %7, i32 1)
store i32 %8, i32* %3
%9 = call i32 @_mm_setr_epi8(i32 0, i32 27, i32 54, i32 45, i32 108, i32 119, i32 90, i32 65, i32 216, i32 195, i32 238, i32 245, i32 180, i32 175, i32 130, i32 153)
%10 = load i32, i32* %3
%11 = call i32 @_mm_srli_si128(i32 %10, i32 8)
%12 = call i32 @_mm_shuffle_epi8(i32 %9, i32 %11)
store i32 %12, i32* %4
%13 = load i32, i32* %2
%14 = load i32, i32* %4
%15 = load i32, i32* %3
%16 = call i32 @_mm_xor_si128(i32 %14, i32 %15)
%17 = call i32 @_mm_xor_si128(i32 %13, i32 %16)
store i32 %17, i32* %5
%18 = load i32, i32* %5
%19 = call i32 @_mm_cvtsi128_si64(i32 %18)
ret i32 %19
}

LLVM IR (-O2):
define i32 @reduce(i32 %0) {
%2 = tail call i32 @_mm_cvtsi64_si128(i32 27)
%3 = tail call i32 @_mm_clmulepi64_si128(i32 %0, i32 %2, i32 1)
%4 = tail call i32 @_mm_setr_epi8(i32 0, i32 27, i32 54, i32 45, i32 108, i32 119, i32 90, i32 65, i32 216, i32 195, i32 238, i32 245, i32 180, i32 175, i32 130, i32 153)
%5 = tail call i32 @_mm_srli_si128(i32 %3, i32 8)
%6 = tail call i32 @_mm_shuffle_epi8(i32 %4, i32 %5)
%7 = tail call i32 @_mm_xor_si128(i32 %6, i32 %3)
%8 = tail call i32 @_mm_xor_si128(i32 %0, i32 %7)
%9 = tail call i32 @_mm_cvtsi128_si64(i32 %8)
ret i32 %9
}