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

/* Variables and functions */
int KEY_MAX;
int count_bits(const char *mask) {
  int count = 0, i;
  static const uint8_t nybble_lookup[16] = {0, 1, 1, 2, 1, 2, 2, 3,
                                            1, 2, 2, 3, 2, 3, 3, 4};
  for (i = 0; i < KEY_MAX / 8 + 1; i++) {
    char byte = mask[i];
    count += nybble_lookup[byte & 0x0F] + nybble_lookup[byte >> 4];
  }
  return count;
}


x86 assembly (clang, -O0):
<count_bits>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
movl   $0x0,-0xc(%rbp)
movl   $0x0,-0x10(%rbp)
mov    -0x10(%rbp),%eax
mov    %eax,-0x18(%rbp)
mov    0x2ebd(%rip),%rax
mov    (%rax),%eax
mov    $0x8,%ecx
cltd
idiv   %ecx
mov    %eax,%ecx
mov    -0x18(%rbp),%eax
add    $0x1,%ecx
cmp    %ecx,%eax
jge    1187 <count_bits+0x87>
mov    -0x8(%rbp),%rax
movslq -0x10(%rbp),%rcx
mov    (%rax,%rcx,1),%al
mov    %al,-0x11(%rbp)
movsbl -0x11(%rbp),%eax
and    $0xf,%eax
movslq %eax,%rcx
lea    0xea4(%rip),%rax
mov    (%rax,%rcx,4),%eax
movsbl -0x11(%rbp),%ecx
sar    $0x4,%ecx
movslq %ecx,%rdx
lea    0xe90(%rip),%rcx
add    (%rcx,%rdx,4),%eax
add    -0xc(%rbp),%eax
mov    %eax,-0xc(%rbp)
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    1116 <count_bits+0x16>
mov    -0xc(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<count_bits>:
mov    0x2ed9(%rip),%rax
mov    (%rax),%r8d
xor    %eax,%eax
cmp    $0xfffffff9,%r8d
jl     11aa <count_bits+0xaa>
lea    0x7(%r8),%eax
test   %r8d,%r8d
cmovs  %eax,%r8d
sar    $0x3,%r8d
add    $0x1,%r8d
cmp    $0xf,%eax
jae    1134 <count_bits+0x34>
xor    %edx,%edx
xor    %eax,%eax
jmp    1188 <count_bits+0x88>
mov    %r8d,%r9d
and    $0xfffffffe,%r9d
xor    %edx,%edx
lea    0xebc(%rip),%r10
xor    %eax,%eax
cs nopw 0x0(%rax,%rax,1)
movsbl (%rdi,%rdx,1),%esi
mov    %esi,%ecx
and    $0xf,%ecx
sar    $0x4,%esi
movslq %esi,%rsi
add    (%r10,%rcx,4),%eax
add    (%r10,%rsi,4),%eax
movsbl 0x1(%rdi,%rdx,1),%ecx
mov    %ecx,%esi
and    $0xf,%esi
sar    $0x4,%ecx
movslq %ecx,%rcx
add    (%r10,%rsi,4),%eax
add    (%r10,%rcx,4),%eax
add    $0x2,%rdx
cmp    %rdx,%r9
jne    1150 <count_bits+0x50>
test   $0x1,%r8b
je     11aa <count_bits+0xaa>
movsbl (%rdi,%rdx,1),%ecx
mov    %ecx,%edx
and    $0xf,%edx
lea    0xe62(%rip),%rsi
sar    $0x4,%ecx
movslq %ecx,%rcx
add    (%rsi,%rdx,4),%eax
add    (%rsi,%rcx,4),%eax
ret

LLVM IR (-O0):
@count_bits.nybble_lookup = internal constant [16 x i32] [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]
@KEY_MAX = global i32 0
define i32 @count_bits(i8* %0) {
%2 = alloca i8*
%3 = alloca i32
%4 = alloca i32
%5 = alloca i8
store i8* %0, i8** %2
store i32 0, i32* %3
store i32 0, i32* %4
br label %6
6: ; preds = %33, %1
%7 = load i32, i32* %4
%8 = load i32, i32* @KEY_MAX
%9 = sdiv i32 %8, 8
%10 = add nsw i32 %9, 1
%11 = icmp slt i32 %7, %10
br i1 %11, label %12, label %36
12: ; preds = %6
%13 = load i8*, i8** %2
%14 = load i32, i32* %4
%15 = sext i32 %14 to i64
%16 = getelementptr inbounds i8, i8* %13, i64 %15
%17 = load i8, i8* %16
store i8 %17, i8* %5
%18 = load i8, i8* %5
%19 = sext i8 %18 to i32
%20 = and i32 %19, 15
%21 = sext i32 %20 to i64
%22 = getelementptr inbounds [16 x i32], [16 x i32]* @count_bits.nybble_lookup, i64 0, i64 %21
%23 = load i32, i32* %22
%24 = load i8, i8* %5
%25 = sext i8 %24 to i32
%26 = ashr i32 %25, 4
%27 = sext i32 %26 to i64
%28 = getelementptr inbounds [16 x i32], [16 x i32]* @count_bits.nybble_lookup, i64 0, i64 %27
%29 = load i32, i32* %28
%30 = add nsw i32 %23, %29
%31 = load i32, i32* %3
%32 = add nsw i32 %31, %30
store i32 %32, i32* %3
br label %33
33: ; preds = %12
%34 = load i32, i32* %4
%35 = add nsw i32 %34, 1
store i32 %35, i32* %4
br label %6
36: ; preds = %6
%37 = load i32, i32* %3
ret i32 %37
}

LLVM IR (-O2):
@count_bits.nybble_lookup = internal unnamed_addr constant [16 x i32] [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]
@KEY_MAX = global i32 0
define i32 @count_bits(i8* nocapture %0) {
%2 = load i32, i32* @KEY_MAX
%3 = icmp slt i32 %2, -7
br i1 %3, label %66, label %4
4: ; preds = %1
%5 = sdiv i32 %2, 8
%6 = add nuw nsw i32 %5, 1
%7 = zext i32 %6 to i64
%8 = and i64 %7, 1
%9 = add i32 %2, 7
%10 = icmp ult i32 %9, 15
br i1 %10, label %47, label %11
11: ; preds = %4
%12 = and i64 %7, 4294967294
br label %13
13: ; preds = %13, %11
%14 = phi i64 [ 0, %11 ], [ %44, %13 ]
%15 = phi i32 [ 0, %11 ], [ %43, %13 ]
%16 = phi i64 [ 0, %11 ], [ %45, %13 ]
%17 = getelementptr inbounds i8, i8* %0, i64 %14
%18 = load i8, i8* %17
%19 = sext i8 %18 to i32
%20 = and i32 %19, 15
%21 = zext i32 %20 to i64
%22 = getelementptr inbounds [16 x i32], [16 x i32]* @count_bits.nybble_lookup, i64 0, i64 %21
%23 = load i32, i32* %22
%24 = ashr i32 %19, 4
%25 = sext i32 %24 to i64
%26 = getelementptr inbounds [16 x i32], [16 x i32]* @count_bits.nybble_lookup, i64 0, i64 %25
%27 = load i32, i32* %26
%28 = add i32 %23, %15
%29 = add i32 %28, %27
%30 = or i64 %14, 1
%31 = getelementptr inbounds i8, i8* %0, i64 %30
%32 = load i8, i8* %31
%33 = sext i8 %32 to i32
%34 = and i32 %33, 15
%35 = zext i32 %34 to i64
%36 = getelementptr inbounds [16 x i32], [16 x i32]* @count_bits.nybble_lookup, i64 0, i64 %35
%37 = load i32, i32* %36
%38 = ashr i32 %33, 4
%39 = sext i32 %38 to i64
%40 = getelementptr inbounds [16 x i32], [16 x i32]* @count_bits.nybble_lookup, i64 0, i64 %39
%41 = load i32, i32* %40
%42 = add i32 %37, %29
%43 = add i32 %42, %41
%44 = add nuw nsw i64 %14, 2
%45 = add i64 %16, 2
%46 = icmp eq i64 %45, %12
br i1 %46, label %47, label %13
47: ; preds = %13, %4
%48 = phi i32 [ undef, %4 ], [ %43, %13 ]
%49 = phi i64 [ 0, %4 ], [ %44, %13 ]
%50 = phi i32 [ 0, %4 ], [ %43, %13 ]
%51 = icmp eq i64 %8, 0
br i1 %51, label %66, label %52
52: ; preds = %47
%53 = getelementptr inbounds i8, i8* %0, i64 %49
%54 = load i8, i8* %53
%55 = sext i8 %54 to i32
%56 = and i32 %55, 15
%57 = zext i32 %56 to i64
%58 = getelementptr inbounds [16 x i32], [16 x i32]* @count_bits.nybble_lookup, i64 0, i64 %57
%59 = load i32, i32* %58
%60 = ashr i32 %55, 4
%61 = sext i32 %60 to i64
%62 = getelementptr inbounds [16 x i32], [16 x i32]* @count_bits.nybble_lookup, i64 0, i64 %61
%63 = load i32, i32* %62
%64 = add i32 %59, %50
%65 = add i32 %64, %63
br label %66
66: ; preds = %52, %47, %1
%67 = phi i32 [ 0, %1 ], [ %48, %47 ], [ %65, %52 ]
ret i32 %67
}