// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/bitops.c
// Function: redisPopcount
size_t redisPopcount(void *s, long count) {
    size_t bits = 0;
    unsigned char *p = s;
    uint32_t *p4;
    // 通过查表来计算，对于 1 字节所能表示的值来说
    // 这些值的二进制表示所带有的 1 的数量
    // 比如整数 3 的二进制表示 0011 ，带有两个 1
    // 正好是查表 bitsinbyte[3] == 2
    static const unsigned char bitsinbyte[256] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};

    /* Count initial bytes not aligned to 32 bit. */
    while((unsigned long)p & 3 && count) {
        bits += bitsinbyte[*p++];
        count--;
    }

    /* Count bits 16 bytes at a time */
    // 每次统计 16 字节
    // 关于这里所使用的优化算法，可以参考：
    // http://yesteapea.wordpress.com/2013/03/03/counting-the-number-of-set-bits-in-an-integer/
    p4 = (uint32_t*)p;
    while(count>=16) {
        uint32_t aux1, aux2, aux3, aux4;

        aux1 = *p4++;
        aux2 = *p4++;
        aux3 = *p4++;
        aux4 = *p4++;
        count -= 16;

        aux1 = aux1 - ((aux1 >> 1) & 0x55555555);
        aux1 = (aux1 & 0x33333333) + ((aux1 >> 2) & 0x33333333);
        aux2 = aux2 - ((aux2 >> 1) & 0x55555555);
        aux2 = (aux2 & 0x33333333) + ((aux2 >> 2) & 0x33333333);
        aux3 = aux3 - ((aux3 >> 1) & 0x55555555);
        aux3 = (aux3 & 0x33333333) + ((aux3 >> 2) & 0x33333333);
        aux4 = aux4 - ((aux4 >> 1) & 0x55555555);
        aux4 = (aux4 & 0x33333333) + ((aux4 >> 2) & 0x33333333);
        bits += ((((aux1 + (aux1 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24) +
                ((((aux2 + (aux2 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24) +
                ((((aux3 + (aux3 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24) +
                ((((aux4 + (aux4 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
    }

    /* Count the remaining bytes. */
    // 不足 16 字节的，剩下的每个字节通过查表来完成
    p = (unsigned char*)p4;
    while(count--) bits += bitsinbyte[*p++];
    return bits;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
testb $0x3, %dil
sete %al
testq %rsi, %rsi
sete %cl
orb %al, %cl
leaq 0x45114(%rip), %rcx     # 0x9eb60
jne 0x59a7e
leaq 0x1(%rdi), %rdx
xorl %eax, %eax
movq %rsi, %r8
movq %rax, %rsi
movzbl (%rdi), %eax
incq %rdi
movzbl (%rax,%rcx), %eax
addq %rsi, %rax
leaq -0x1(%r8), %rsi
testb $0x3, %dl
je 0x59a80
incq %rdx
cmpq $0x1, %r8
movq %rsi, %r8
jne 0x59a57
jmp 0x59a80
xorl %eax, %eax
cmpq $0x10, %rsi
jl 0x59b95
movl $0x55555555, %edx       # imm = 0x55555555
movl $0x33333333, %r8d       # imm = 0x33333333
movl $0xf0f0f0f, %r9d        # imm = 0xF0F0F0F
movq %rsi, %r10
movl (%rdi), %r14d
movl 0x4(%rdi), %ebp
movl 0x8(%rdi), %ebx
movl 0xc(%rdi), %r11d
addq $0x10, %rdi
addq $-0x10, %rsi
movl %r14d, %r15d
shrl %r15d
andl %edx, %r15d
subl %r15d, %r14d
movl %r14d, %r15d
andl %r8d, %r15d
shrl $0x2, %r14d
andl %r8d, %r14d
addl %r15d, %r14d
movl %ebp, %r15d
shrl %r15d
andl %edx, %r15d
subl %r15d, %ebp
movl %ebp, %r15d
andl %r8d, %r15d
shrl $0x2, %ebp
andl %r8d, %ebp
addl %r15d, %ebp
movl %ebx, %r15d
shrl %r15d
andl %edx, %r15d
subl %r15d, %ebx
movl %ebx, %r15d
andl %r8d, %r15d
shrl $0x2, %ebx
andl %r8d, %ebx
addl %r15d, %ebx
movl %r11d, %r15d
shrl %r15d
andl %edx, %r15d
subl %r15d, %r11d
movl %r11d, %r15d
andl %r8d, %r15d
shrl $0x2, %r11d
andl %r8d, %r11d
addl %r15d, %r11d
movl %r14d, %r15d
shrl $0x4, %r15d
addl %r14d, %r15d
andl %r9d, %r15d
imull $0x1010101, %r15d, %r14d # imm = 0x1010101
shrl $0x18, %r14d
movl %ebp, %r15d
shrl $0x4, %r15d
addl %ebp, %r15d
andl %r9d, %r15d
imull $0x1010101, %r15d, %ebp # imm = 0x1010101
shrl $0x18, %ebp
addl %r14d, %ebp
movl %ebx, %r14d
shrl $0x4, %r14d
addl %ebx, %r14d
andl %r9d, %r14d
imull $0x1010101, %r14d, %ebx # imm = 0x1010101
shrl $0x18, %ebx
movl %r11d, %r14d
shrl $0x4, %r14d
addl %r11d, %r14d
andl %r9d, %r14d
imull $0x1010101, %r14d, %r11d # imm = 0x1010101
shrl $0x18, %r11d
addl %ebx, %r11d
addl %ebp, %r11d
addq %r11, %rax
cmpq $0x1f, %r10
jg 0x59a9b
testq %rsi, %rsi
je 0x59bb1
xorl %edx, %edx
movzbl (%rdi,%rdx), %r8d
movzbl (%r8,%rcx), %r8d
addq %r8, %rax
incq %rdx
cmpq %rdx, %rsi
jne 0x59b9c
popq %rbx
popq %r14
popq %r15
popq %rbp
retq