#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*/ __m128i;

/* Variables and functions */
int /*<<< orphan*/ _mm_add_epi8(int /*<<< orphan*/ const,
                                int /*<<< orphan*/ const);
int /*<<< orphan*/ _mm_and_si128(int /*<<< orphan*/, int /*<<< orphan*/ const);
int /*<<< orphan*/ _mm_sad_epu8(int /*<<< orphan*/, int /*<<< orphan*/);
int /*<<< orphan*/ _mm_set1_epi8(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*/ _mm_setzero_si128();
int /*<<< orphan*/ _mm_shuffle_epi8(int /*<<< orphan*/ const,
                                    int /*<<< orphan*/ const);
int /*<<< orphan*/ _mm_srli_epi16(int /*<<< orphan*/, int);
__attribute__((always_)) __m128i popcount(__m128i v) {
  const __m128i lookup =
      _mm_setr_epi8(0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4);
  const __m128i low_mask = _mm_set1_epi8(0x0f);
  const __m128i lo = _mm_and_si128(v, low_mask);
  const __m128i hi = _mm_and_si128(_mm_srli_epi16(v, 4), low_mask);
  const __m128i popcnt1 = _mm_shuffle_epi8(lookup, lo);
  const __m128i popcnt2 = _mm_shuffle_epi8(lookup, hi);
  return _mm_sad_epu8(_mm_add_epi8(popcnt1, popcnt2), _mm_setzero_si128());
}


x86 assembly (clang, -O0):
<popcount>:
push   %rbp
mov    %rsp,%rbp
sub    $0x70,%rsp
mov    %edi,-0x4(%rbp)
xor    %edi,%edi
mov    $0x1,%r8d
mov    $0x2,%r9d
mov    %r8d,%esi
mov    %r8d,%edx
mov    %r9d,%ecx
movl   $0x2,(%rsp)
movl   $0x3,0x8(%rsp)
movl   $0x1,0x10(%rsp)
movl   $0x2,0x18(%rsp)
movl   $0x2,0x20(%rsp)
movl   $0x3,0x28(%rsp)
movl   $0x2,0x30(%rsp)
movl   $0x3,0x38(%rsp)
movl   $0x3,0x40(%rsp)
movl   $0x4,0x48(%rsp)
call   1070 <_mm_setr_epi8@plt>
mov    %eax,-0x8(%rbp)
mov    $0xf,%edi
call   1050 <_mm_set1_epi8@plt>
mov    %eax,-0xc(%rbp)
mov    -0x4(%rbp),%edi
mov    -0xc(%rbp),%esi
call   10a0 <_mm_and_si128@plt>
mov    %eax,-0x10(%rbp)
mov    -0x4(%rbp),%edi
mov    $0x4,%esi
call   1040 <_mm_srli_epi16@plt>
mov    %eax,%edi
mov    -0xc(%rbp),%esi
call   10a0 <_mm_and_si128@plt>
mov    %eax,-0x14(%rbp)
mov    -0x8(%rbp),%edi
mov    -0x10(%rbp),%esi
call   1060 <_mm_shuffle_epi8@plt>
mov    %eax,-0x18(%rbp)
mov    -0x8(%rbp),%edi
mov    -0x14(%rbp),%esi
call   1060 <_mm_shuffle_epi8@plt>
mov    %eax,-0x1c(%rbp)
mov    -0x18(%rbp),%edi
mov    -0x1c(%rbp),%esi
call   1080 <_mm_add_epi8@plt>
mov    %eax,-0x20(%rbp)
mov    $0x0,%al
call   1030 <_mm_setzero_si128@plt>
mov    -0x20(%rbp),%edi
mov    %eax,%esi
call   1090 <_mm_sad_epu8@plt>
add    $0x70,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<popcount>:
push   %rbp
push   %r15
push   %r14
push   %r12
push   %rbx
mov    %edi,%r14d
xor    %edi,%edi
mov    $0x1,%esi
mov    $0x1,%edx
mov    $0x2,%ecx
mov    $0x1,%r8d
mov    $0x2,%r9d
push   $0x4
push   $0x3
push   $0x3
push   $0x2
push   $0x3
push   $0x2
push   $0x2
push   $0x1
push   $0x3
push   $0x2
call   1070 <_mm_setr_epi8@plt>
add    $0x50,%rsp
mov    %eax,%r12d
mov    $0xf,%edi
call   1050 <_mm_set1_epi8@plt>
mov    %eax,%ebx
mov    %r14d,%edi
mov    %eax,%esi
call   10a0 <_mm_and_si128@plt>
mov    %eax,%r15d
mov    %r14d,%edi
mov    $0x4,%esi
call   1040 <_mm_srli_epi16@plt>
mov    %eax,%edi
mov    %ebx,%esi
call   10a0 <_mm_and_si128@plt>
mov    %eax,%ebx
mov    %r12d,%edi
mov    %r15d,%esi
call   1060 <_mm_shuffle_epi8@plt>
mov    %eax,%ebp
mov    %r12d,%edi
mov    %ebx,%esi
call   1060 <_mm_shuffle_epi8@plt>
mov    %ebp,%edi
mov    %eax,%esi
call   1080 <_mm_add_epi8@plt>
mov    %eax,%ebx
xor    %eax,%eax
call   1030 <_mm_setzero_si128@plt>
mov    %ebx,%edi
mov    %eax,%esi
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
pop    %rbp
jmp    1090 <_mm_sad_epu8@plt>

LLVM IR (-O0):
define i32 @popcount(i32 %0) {
%2 = alloca i32
%3 = alloca i32
%4 = alloca i32
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
store i32 %0, i32* %2
%9 = call i32 @_mm_setr_epi8(i32 0, i32 1, i32 1, i32 2, i32 1, i32 2, i32 2, i32 3, i32 1, i32 2, i32 2, i32 3, i32 2, i32 3, i32 3, i32 4)
store i32 %9, i32* %3
%10 = call i32 @_mm_set1_epi8(i32 15)
store i32 %10, i32* %4
%11 = load i32, i32* %2
%12 = load i32, i32* %4
%13 = call i32 @_mm_and_si128(i32 %11, i32 %12)
store i32 %13, i32* %5
%14 = load i32, i32* %2
%15 = call i32 @_mm_srli_epi16(i32 %14, i32 4)
%16 = load i32, i32* %4
%17 = call i32 @_mm_and_si128(i32 %15, i32 %16)
store i32 %17, i32* %6
%18 = load i32, i32* %3
%19 = load i32, i32* %5
%20 = call i32 @_mm_shuffle_epi8(i32 %18, i32 %19)
store i32 %20, i32* %7
%21 = load i32, i32* %3
%22 = load i32, i32* %6
%23 = call i32 @_mm_shuffle_epi8(i32 %21, i32 %22)
store i32 %23, i32* %8
%24 = load i32, i32* %7
%25 = load i32, i32* %8
%26 = call i32 @_mm_add_epi8(i32 %24, i32 %25)
%27 = call i32 (...) @_mm_setzero_si128()
%28 = call i32 @_mm_sad_epu8(i32 %26, i32 %27)
ret i32 %28
}

LLVM IR (-O2):
define i32 @popcount(i32 %0) {
%2 = tail call i32 @_mm_setr_epi8(i32 0, i32 1, i32 1, i32 2, i32 1, i32 2, i32 2, i32 3, i32 1, i32 2, i32 2, i32 3, i32 2, i32 3, i32 3, i32 4)
%3 = tail call i32 @_mm_set1_epi8(i32 15)
%4 = tail call i32 @_mm_and_si128(i32 %0, i32 %3)
%5 = tail call i32 @_mm_srli_epi16(i32 %0, i32 4)
%6 = tail call i32 @_mm_and_si128(i32 %5, i32 %3)
%7 = tail call i32 @_mm_shuffle_epi8(i32 %2, i32 %4)
%8 = tail call i32 @_mm_shuffle_epi8(i32 %2, i32 %6)
%9 = tail call i32 @_mm_add_epi8(i32 %7, i32 %8)
%10 = tail call i32 (...) @_mm_setzero_si128()
%11 = tail call i32 @_mm_sad_epu8(i32 %9, i32 %10)
ret i32 %11
}