#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 __m256i;

/* Variables and functions */
int _mm256_sad_epu8(int, int);
int _mm256_set1_epi8(int);
int _mm256_setr_epi8(int, int, int, int, int, int, int, int, int, int, int, int,
                     int, int, int, int, int, int, int, int, int, int, int, int,
                     int, int, int, int, int, int, int, int);
int _mm256_shuffle_epi8(int, int);
int _mm256_srli_epi16(int, int);
__attribute__((target("avx2"))) __m256i popcnt256(__m256i v) {
  __m256i lookup1 =
      _mm256_setr_epi8(4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5,
                       6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8);
  __m256i lookup2 =
      _mm256_setr_epi8(4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0, 4, 3, 3,
                       2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0);
  __m256i low_mask = _mm256_set1_epi8(0x0f);
  __m256i lo = v & low_mask;
  __m256i hi = _mm256_srli_epi16(v, 4) & low_mask;
  __m256i popcnt1 = _mm256_shuffle_epi8(lookup1, lo);
  __m256i popcnt2 = _mm256_shuffle_epi8(lookup2, hi);
  return _mm256_sad_epu8(popcnt1, popcnt2);
}


x86 assembly (clang, -O0):
<popcnt256>:
push   %rbp
mov    %rsp,%rbp
sub    $0xf0,%rsp
mov    %edi,-0x4(%rbp)
mov    $0x4,%edi
mov    $0x5,%r8d
mov    $0x6,%r9d
mov    %r8d,%esi
mov    %r8d,%edx
mov    %r9d,%ecx
movl   $0x6,(%rsp)
movl   $0x7,0x8(%rsp)
movl   $0x5,0x10(%rsp)
movl   $0x6,0x18(%rsp)
movl   $0x6,0x20(%rsp)
movl   $0x7,0x28(%rsp)
movl   $0x6,0x30(%rsp)
movl   $0x7,0x38(%rsp)
movl   $0x7,0x40(%rsp)
movl   $0x8,0x48(%rsp)
movl   $0x4,0x50(%rsp)
movl   $0x5,0x58(%rsp)
movl   $0x5,0x60(%rsp)
movl   $0x6,0x68(%rsp)
movl   $0x5,0x70(%rsp)
movl   $0x6,0x78(%rsp)
movl   $0x6,0x80(%rsp)
movl   $0x7,0x88(%rsp)
movl   $0x5,0x90(%rsp)
movl   $0x6,0x98(%rsp)
movl   $0x6,0xa0(%rsp)
movl   $0x7,0xa8(%rsp)
movl   $0x6,0xb0(%rsp)
movl   $0x7,0xb8(%rsp)
movl   $0x7,0xc0(%rsp)
movl   $0x8,0xc8(%rsp)
call   1050 <_mm256_setr_epi8@plt>
mov    %eax,-0x8(%rbp)
mov    $0x4,%edi
mov    $0x3,%r8d
mov    $0x2,%r9d
xor    %eax,%eax
mov    %r8d,%esi
mov    %r8d,%edx
mov    %r9d,%ecx
movl   $0x2,(%rsp)
movl   $0x1,0x8(%rsp)
movl   $0x3,0x10(%rsp)
movl   $0x2,0x18(%rsp)
movl   $0x2,0x20(%rsp)
movl   $0x1,0x28(%rsp)
movl   $0x2,0x30(%rsp)
movl   $0x1,0x38(%rsp)
movl   $0x1,0x40(%rsp)
movl   $0x0,0x48(%rsp)
movl   $0x4,0x50(%rsp)
movl   $0x3,0x58(%rsp)
movl   $0x3,0x60(%rsp)
movl   $0x2,0x68(%rsp)
movl   $0x3,0x70(%rsp)
movl   $0x2,0x78(%rsp)
movl   $0x2,0x80(%rsp)
movl   $0x1,0x88(%rsp)
movl   $0x3,0x90(%rsp)
movl   $0x2,0x98(%rsp)
movl   $0x2,0xa0(%rsp)
movl   $0x1,0xa8(%rsp)
movl   $0x2,0xb0(%rsp)
movl   $0x1,0xb8(%rsp)
movl   $0x1,0xc0(%rsp)
movl   $0x0,0xc8(%rsp)
call   1050 <_mm256_setr_epi8@plt>
mov    %eax,-0xc(%rbp)
mov    $0xf,%edi
call   1070 <_mm256_set1_epi8@plt>
mov    %eax,-0x10(%rbp)
mov    -0x4(%rbp),%eax
and    -0x10(%rbp),%eax
mov    %eax,-0x14(%rbp)
mov    -0x4(%rbp),%edi
mov    $0x4,%esi
call   1030 <_mm256_srli_epi16@plt>
and    -0x10(%rbp),%eax
mov    %eax,-0x18(%rbp)
mov    -0x8(%rbp),%edi
mov    -0x14(%rbp),%esi
call   1060 <_mm256_shuffle_epi8@plt>
mov    %eax,-0x1c(%rbp)
mov    -0xc(%rbp),%edi
mov    -0x18(%rbp),%esi
call   1060 <_mm256_shuffle_epi8@plt>
mov    %eax,-0x20(%rbp)
mov    -0x1c(%rbp),%edi
mov    -0x20(%rbp),%esi
call   1040 <_mm256_sad_epu8@plt>
add    $0xf0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<popcnt256>:
push   %rbp
push   %r15
push   %r14
push   %r12
push   %rbx
mov    %edi,%r14d
mov    $0x4,%edi
mov    $0x5,%esi
mov    $0x5,%edx
mov    $0x6,%ecx
mov    $0x5,%r8d
mov    $0x6,%r9d
push   $0x8
push   $0x7
push   $0x7
push   $0x6
push   $0x7
push   $0x6
push   $0x6
push   $0x5
push   $0x7
push   $0x6
push   $0x6
push   $0x5
push   $0x6
push   $0x5
push   $0x5
push   $0x4
push   $0x8
push   $0x7
push   $0x7
push   $0x6
push   $0x7
push   $0x6
push   $0x6
push   $0x5
push   $0x7
push   $0x6
call   1050 <_mm256_setr_epi8@plt>
add    $0xd0,%rsp
mov    %eax,%r15d
mov    $0x4,%edi
mov    $0x3,%esi
mov    $0x3,%edx
mov    $0x2,%ecx
mov    $0x3,%r8d
mov    $0x2,%r9d
push   $0x0
push   $0x1
push   $0x1
push   $0x2
push   $0x1
push   $0x2
push   $0x2
push   $0x3
push   $0x1
push   $0x2
push   $0x2
push   $0x3
push   $0x2
push   $0x3
push   $0x3
push   $0x4
push   $0x0
push   $0x1
push   $0x1
push   $0x2
push   $0x1
push   $0x2
push   $0x2
push   $0x3
push   $0x1
push   $0x2
call   1050 <_mm256_setr_epi8@plt>
add    $0xd0,%rsp
mov    %eax,%r12d
mov    $0xf,%edi
call   1070 <_mm256_set1_epi8@plt>
mov    %eax,%ebp
mov    %eax,%ebx
and    %r14d,%ebx
mov    %r14d,%edi
mov    $0x4,%esi
call   1030 <_mm256_srli_epi16@plt>
and    %eax,%ebp
mov    %r15d,%edi
mov    %ebx,%esi
call   1060 <_mm256_shuffle_epi8@plt>
mov    %eax,%ebx
mov    %r12d,%edi
mov    %ebp,%esi
call   1060 <_mm256_shuffle_epi8@plt>
mov    %ebx,%edi
mov    %eax,%esi
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
pop    %rbp
jmp    1040 <_mm256_sad_epu8@plt>

LLVM IR (-O0):
define i32 @popcnt256(i32 %0) {
%2 = alloca i32
%3 = alloca i32
%4 = alloca i32
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32
store i32 %0, i32* %2
%10 = call i32 @_mm256_setr_epi8(i32 4, i32 5, i32 5, i32 6, i32 5, i32 6, i32 6, i32 7, i32 5, i32 6, i32 6, i32 7, i32 6, i32 7, i32 7, i32 8, i32 4, i32 5, i32 5, i32 6, i32 5, i32 6, i32 6, i32 7, i32 5, i32 6, i32 6, i32 7, i32 6, i32 7, i32 7, i32 8)
store i32 %10, i32* %3
%11 = call i32 @_mm256_setr_epi8(i32 4, i32 3, i32 3, i32 2, i32 3, i32 2, i32 2, i32 1, i32 3, i32 2, i32 2, i32 1, i32 2, i32 1, i32 1, i32 0, i32 4, i32 3, i32 3, i32 2, i32 3, i32 2, i32 2, i32 1, i32 3, i32 2, i32 2, i32 1, i32 2, i32 1, i32 1, i32 0)
store i32 %11, i32* %4
%12 = call i32 @_mm256_set1_epi8(i32 15)
store i32 %12, i32* %5
%13 = load i32, i32* %2
%14 = load i32, i32* %5
%15 = and i32 %13, %14
store i32 %15, i32* %6
%16 = load i32, i32* %2
%17 = call i32 @_mm256_srli_epi16(i32 %16, i32 4)
%18 = load i32, i32* %5
%19 = and i32 %17, %18
store i32 %19, i32* %7
%20 = load i32, i32* %3
%21 = load i32, i32* %6
%22 = call i32 @_mm256_shuffle_epi8(i32 %20, i32 %21)
store i32 %22, i32* %8
%23 = load i32, i32* %4
%24 = load i32, i32* %7
%25 = call i32 @_mm256_shuffle_epi8(i32 %23, i32 %24)
store i32 %25, i32* %9
%26 = load i32, i32* %8
%27 = load i32, i32* %9
%28 = call i32 @_mm256_sad_epu8(i32 %26, i32 %27)
ret i32 %28
}

LLVM IR (-O2):
define i32 @popcnt256(i32 %0) {
%2 = tail call i32 @_mm256_setr_epi8(i32 4, i32 5, i32 5, i32 6, i32 5, i32 6, i32 6, i32 7, i32 5, i32 6, i32 6, i32 7, i32 6, i32 7, i32 7, i32 8, i32 4, i32 5, i32 5, i32 6, i32 5, i32 6, i32 6, i32 7, i32 5, i32 6, i32 6, i32 7, i32 6, i32 7, i32 7, i32 8)
%3 = tail call i32 @_mm256_setr_epi8(i32 4, i32 3, i32 3, i32 2, i32 3, i32 2, i32 2, i32 1, i32 3, i32 2, i32 2, i32 1, i32 2, i32 1, i32 1, i32 0, i32 4, i32 3, i32 3, i32 2, i32 3, i32 2, i32 2, i32 1, i32 3, i32 2, i32 2, i32 1, i32 2, i32 1, i32 1, i32 0)
%4 = tail call i32 @_mm256_set1_epi8(i32 15)
%5 = and i32 %4, %0
%6 = tail call i32 @_mm256_srli_epi16(i32 %0, i32 4)
%7 = and i32 %6, %4
%8 = tail call i32 @_mm256_shuffle_epi8(i32 %2, i32 %5)
%9 = tail call i32 @_mm256_shuffle_epi8(i32 %3, i32 %7)
%10 = tail call i32 @_mm256_sad_epu8(i32 %8, i32 %9)
ret i32 %10
}