// File: /workspace/github_c_makefile_star2_O0/agraf[P]kvmbench/cpuid_csum.c
// Function: avxChecksumV2
int avxChecksumV2(const char * const target, size_t targetLength) {
	const __m256i zeroVec = _mm256_setzero_si256();
	const __m256i oneVec = _mm256_set1_epi16(1);
	__m256i accum = _mm256_setzero_si256();
	unsigned int checksum = 0;
	size_t offset = 0;

	if(targetLength >= 32) {
		for(; offset <= targetLength - 32; offset += 32) {
			__m256i vec = _mm256_loadu_si256(
			(const __m256i*)(target + offset));
			__m256i vl = _mm256_unpacklo_epi8(vec, zeroVec);
			__m256i vh = _mm256_unpackhi_epi8(vec, zeroVec);
			// There's no "add and unpack" instruction but multiplying by 
			// one has the same effect and gets us unpacking from 16-bits to 
			// 32 bits for free.
			accum = _mm256_add_epi32(accum, _mm256_madd_epi16(vl, oneVec));
			accum = _mm256_add_epi32(accum, _mm256_madd_epi16(vh, oneVec));
		}
	}

	for(; offset < targetLength; ++offset) {
		checksum += (unsigned int) target[offset];
	}

	// We could accomplish the same thing with horizontal add instructions as 
	// we did above but shifts and vertical adds have much lower instruction 
	// latency.
	accum = _mm256_add_epi32(accum, _mm256_srli_si256(accum, 4));
	accum = _mm256_add_epi32(accum, _mm256_srli_si256(accum, 8));
	return (_mm256_extract_epi32(accum, 0) + _mm256_extract_epi32(accum, 4) + 
		checksum) % 256;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
andq $-0x20, %rsp
subq $0x3e0, %rsp            # imm = 0x3E0
movq %rdi, 0x118(%rsp)
movq %rsi, 0x110(%rsp)
vxorps %xmm0, %xmm0, %xmm0
vmovaps %ymm0, 0x140(%rsp)
vmovaps 0x140(%rsp), %ymm1
vmovaps %ymm1, 0xe0(%rsp)
movw $0x1, 0x176(%rsp)
movw 0x176(%rsp), %ax
movw %ax, 0x1e(%rsp)
movw %ax, 0x3ce(%rsp)
movw %ax, 0x3cc(%rsp)
movw %ax, 0x3ca(%rsp)
movw %ax, 0x3c8(%rsp)
movw %ax, 0x3c6(%rsp)
movw %ax, 0x3c4(%rsp)
movw %ax, 0x3c2(%rsp)
movw %ax, 0x3c0(%rsp)
movw %ax, 0x3be(%rsp)
movw %ax, 0x3bc(%rsp)
movw %ax, 0x3ba(%rsp)
movw %ax, 0x3b8(%rsp)
movw %ax, 0x3b6(%rsp)
movw %ax, 0x3b4(%rsp)
movw %ax, 0x3b2(%rsp)
movw %ax, 0x3b0(%rsp)
movzwl 0x3b0(%rsp), %eax
vmovd %eax, %xmm1
movzwl 0x3b2(%rsp), %eax
vpinsrw $0x1, %eax, %xmm1, %xmm1
movzwl 0x3b4(%rsp), %eax
vpinsrw $0x2, %eax, %xmm1, %xmm1
movzwl 0x3b6(%rsp), %eax
vpinsrw $0x3, %eax, %xmm1, %xmm1
movzwl 0x3b8(%rsp), %eax
vpinsrw $0x4, %eax, %xmm1, %xmm1
movzwl 0x3ba(%rsp), %eax
vpinsrw $0x5, %eax, %xmm1, %xmm1
movzwl 0x3bc(%rsp), %eax
vpinsrw $0x6, %eax, %xmm1, %xmm1
movzwl 0x3be(%rsp), %eax
vpinsrw $0x7, %eax, %xmm1, %xmm1
movzwl 0x3c0(%rsp), %eax
vmovd %eax, %xmm2
movzwl 0x3c2(%rsp), %eax
vpinsrw $0x1, %eax, %xmm2, %xmm2
movzwl 0x3c4(%rsp), %eax
vpinsrw $0x2, %eax, %xmm2, %xmm2
movzwl 0x3c6(%rsp), %eax
vpinsrw $0x3, %eax, %xmm2, %xmm2
movzwl 0x3c8(%rsp), %eax
vpinsrw $0x4, %eax, %xmm2, %xmm2
movzwl 0x3ca(%rsp), %eax
vpinsrw $0x5, %eax, %xmm2, %xmm2
movzwl 0x3cc(%rsp), %eax
vpinsrw $0x6, %eax, %xmm2, %xmm2
movzwl 0x3ce(%rsp), %eax
vpinsrw $0x7, %eax, %xmm2, %xmm2
vmovdqa %xmm2, 0x390(%rsp)
vmovdqa %xmm1, 0x380(%rsp)
vmovaps 0x380(%rsp), %ymm1
vmovaps %ymm1, 0xc0(%rsp)
vmovaps %ymm0, 0x120(%rsp)
vmovdqa 0x120(%rsp), %ymm0
vmovdqa %ymm0, 0xa0(%rsp)
movl $0x0, 0x9c(%rsp)
movq $0x0, 0x90(%rsp)
cmpq $0x20, 0x110(%rsp)
jb 0x173b
jmp 0x157a
movq 0x90(%rsp), %rax
movq 0x110(%rsp), %rcx
subq $0x20, %rcx
cmpq %rcx, %rax
ja 0x1739
movq 0x118(%rsp), %rax
movq 0x90(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0x178(%rsp)
movq 0x178(%rsp), %rax
vmovups (%rax), %ymm0
vmovaps %ymm0, 0x60(%rsp)
vmovaps 0x60(%rsp), %ymm1
vmovaps 0xe0(%rsp), %ymm0
vmovaps %ymm1, 0x1a0(%rsp)
vmovaps %ymm0, 0x180(%rsp)
vmovaps 0x1a0(%rsp), %ymm0
vmovaps 0x180(%rsp), %ymm1
vpunpcklbw %ymm1, %ymm0, %ymm0 # ymm0 = ymm0[0],ymm1[0],ymm0[1],ymm1[1],ymm0[2],ymm1[2],ymm0[3],ymm1[3],ymm0[4],ymm1[4],ymm0[5],ymm1[5],ymm0[6],ymm1[6],ymm0[7],ymm1[7],ymm0[16],ymm1[16],ymm0[17],ymm1[17],ymm0[18],ymm1[18],ymm0[19],ymm1[19],ymm0[20],ymm1[20],ymm0[21],ymm1[21],ymm0[22],ymm1[22],ymm0[23],ymm1[23]
vmovaps %ymm0, 0x40(%rsp)
vmovaps 0x60(%rsp), %ymm1
vmovaps 0xe0(%rsp), %ymm0
vmovaps %ymm1, 0x1e0(%rsp)
vmovaps %ymm0, 0x1c0(%rsp)
vmovaps 0x1e0(%rsp), %ymm0
vmovaps 0x1c0(%rsp), %ymm1
vpunpckhbw %ymm1, %ymm0, %ymm0 # ymm0 = ymm0[8],ymm1[8],ymm0[9],ymm1[9],ymm0[10],ymm1[10],ymm0[11],ymm1[11],ymm0[12],ymm1[12],ymm0[13],ymm1[13],ymm0[14],ymm1[14],ymm0[15],ymm1[15],ymm0[24],ymm1[24],ymm0[25],ymm1[25],ymm0[26],ymm1[26],ymm0[27],ymm1[27],ymm0[28],ymm1[28],ymm0[29],ymm1[29],ymm0[30],ymm1[30],ymm0[31],ymm1[31]
vmovdqa %ymm0, 0x20(%rsp)
vmovdqa 0xa0(%rsp), %ymm1
vmovdqa 0x40(%rsp), %ymm2
vmovdqa 0xc0(%rsp), %ymm0
vmovdqa %ymm2, 0x360(%rsp)
vmovdqa %ymm0, 0x340(%rsp)
vmovdqa 0x360(%rsp), %ymm0
vmovdqa 0x340(%rsp), %ymm2
vpmaddwd %ymm2, %ymm0, %ymm0
vmovdqa %ymm1, 0x2e0(%rsp)
vmovdqa %ymm0, 0x2c0(%rsp)
vmovdqa 0x2e0(%rsp), %ymm0
vmovdqa 0x2c0(%rsp), %ymm1
vpaddd %ymm1, %ymm0, %ymm0
vmovdqa %ymm0, 0xa0(%rsp)
vmovdqa 0xa0(%rsp), %ymm1
vmovdqa 0x20(%rsp), %ymm2
vmovdqa 0xc0(%rsp), %ymm0
vmovdqa %ymm2, 0x320(%rsp)
vmovdqa %ymm0, 0x300(%rsp)
vmovdqa 0x320(%rsp), %ymm0
vmovdqa 0x300(%rsp), %ymm2
vpmaddwd %ymm2, %ymm0, %ymm0
vmovdqa %ymm1, 0x2a0(%rsp)
vmovdqa %ymm0, 0x280(%rsp)
vmovdqa 0x2a0(%rsp), %ymm0
vmovdqa 0x280(%rsp), %ymm1
vpaddd %ymm1, %ymm0, %ymm0
vmovdqa %ymm0, 0xa0(%rsp)
movq 0x90(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x90(%rsp)
jmp 0x157a
jmp 0x173b
jmp 0x173d
movq 0x90(%rsp), %rax
cmpq 0x110(%rsp), %rax
jae 0x1787
movq 0x118(%rsp), %rax
movq 0x90(%rsp), %rcx
movsbl (%rax,%rcx), %eax
addl 0x9c(%rsp), %eax
movl %eax, 0x9c(%rsp)
movq 0x90(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x90(%rsp)
jmp 0x173d
vmovaps 0xa0(%rsp), %ymm1
vpsrldq $0x4, %ymm1, %ymm0      # ymm0 = ymm1[4,5,6,7,8,9,10,11,12,13,14,15],zero,zero,zero,zero,ymm1[20,21,22,23,24,25,26,27,28,29,30,31],zero,zero,zero,zero
vmovaps %ymm1, 0x260(%rsp)
vmovaps %ymm0, 0x240(%rsp)
vmovaps 0x260(%rsp), %ymm0
vmovaps 0x240(%rsp), %ymm1
vpaddd %ymm1, %ymm0, %ymm0
vmovaps %ymm0, 0xa0(%rsp)
vmovaps 0xa0(%rsp), %ymm1
vpsrldq $0x8, %ymm1, %ymm0      # ymm0 = ymm1[8,9,10,11,12,13,14,15],zero,zero,zero,zero,zero,zero,zero,zero,ymm1[24,25,26,27,28,29,30,31],zero,zero,zero,zero,zero,zero,zero,zero
vmovaps %ymm1, 0x220(%rsp)
vmovaps %ymm0, 0x200(%rsp)
vmovaps 0x220(%rsp), %ymm0
vmovaps 0x200(%rsp), %ymm1
vpaddd %ymm1, %ymm0, %ymm0
vmovaps %ymm0, 0xa0(%rsp)
movl 0xa0(%rsp), %eax
movl 0xb0(%rsp), %ecx
addl %ecx, %eax
addl 0x9c(%rsp), %eax
andl $0xff, %eax
movq %rbp, %rsp
popq %rbp
vzeroupper
retq
nopl (%rax)