News for hackers. Stuff that matters.
Re:Hand-Coded Assembly Beats Intrinsics in Speed and Simplicity by corysama on Tuesday August 11, 2015 @05:18PM (#10044458)
Switching to __popcnt64 uses 8 byte popcnt. But, I can't get rid of the false dependency problem.

    RES64 cnt0=0, cnt1=0, cnt2=0, cnt3=0;
	SIZE_T ndqwords = len / (sizeof(RES64) * 4);
	for(; ndqwords; ndqwords--) {
		cnt0 += __popcnt64(*(RES64*)buf);
		cnt1 += __popcnt64(*(RES64*)(buf + sizeof(RES64) ));
		cnt2 += __popcnt64(*(RES64*)(buf + sizeof(RES64) * 2 ));
		cnt3 += __popcnt64(*(RES64*)(buf + sizeof(RES64) * 3 ));
		buf += sizeof(RES64) * 4;
	}
    cnt = cnt0 + cnt1 + cnt2 + cnt3;


    000000013FD61FF3  popcnt      rax,qword ptr [rdx]  
    000000013FD61FF8  add         rdx,20h  
    000000013FD61FFC  add         r9,rax  
    000000013FD61FFF  popcnt      rax,qword ptr [rdx-18h]  
    000000013FD62005  add         r10,rax  
    000000013FD62008  popcnt      rax,qword ptr [rdx-10h]  
    000000013FD6200E  add         r8,rax  
    000000013FD62011  popcnt      rax,qword ptr [rdx-8]  
    000000013FD62017  add         r11,rax  
    000000013FD6201A  dec         rcx  
    000000013FD6201D  jne         main+0C3h (13FD61FF3h)
Re:Hand-Coded Assembly Beats Intrinsics in Speed and Simplicity by corysama on Tuesday August 11, 2015 @06:23PM (#10044815)
This gets rid of the false dependency problem. Not a shining example of simplicity or reliability. But, interesting that it works.

    struct A { RES64 cnt0; RES64 cnt1; RES64 cnt2; RES64 cnt3; } a;
    RES64 cnt0=0, cnt1=0, cnt2=0, cnt3=0;
    SIZE_T ndqwords = len / (sizeof(RES64) * 4);
    for(; ndqwords; ndqwords--) {
        a.cnt0 = __popcnt64(*(RES64*)buf);
        a.cnt1 = __popcnt64(*(RES64*)(buf + sizeof(RES64) ));
        a.cnt2 = __popcnt64(*(RES64*)(buf + sizeof(RES64) * 2 ));
        a.cnt3 = __popcnt64(*(RES64*)(buf + sizeof(RES64) * 3 ));
        cnt0 += a.cnt0;
        cnt1 += a.cnt1;
        cnt2 += a.cnt2;
        cnt3 += a.cnt3;
        buf += sizeof(RES64) * 4;
    }
    cnt = cnt0 + cnt1 + cnt2 + cnt3;

    000000013F2320C0  popcnt      rax,qword ptr [r8]  
    000000013F2320C5  popcnt      rcx,qword ptr [r8+8]  
    000000013F2320CB  popcnt      rdx,qword ptr [r8+10h]  
    000000013F2320D1  popcnt      rbx,qword ptr [r8+18h]  
    000000013F2320D7  add         r11,rax  
    000000013F2320DA  add         rdi,rcx  
    000000013F2320DD  add         rsi,rdx  
    000000013F2320E0  add         r8,20h  
    000000013F2320E4  add         rbp,rbx  
    000000013F2320E7  dec         r10  
    000000013F2320EA  jne         main+0D0h (13F2320C0h)
Re:Hand-Coded Assembly Beats Intrinsics in Speed and Simplicity by bro-stick on Tuesday August 11, 2015 @06:34PM (#10044862)
In writing a fast Hamming distance library in Go, dropping inline popcnt64 in using cgo was far slower than good, old-fashioned lookup table method for a single byte on a Haswell mobile processor. For the uint64 case, bitfolding was still faster than popcnt64. Perhaps for the vector buffer case, popcnt64 is faster.