// File: lemire[P]fastscancount/benchmark/counters.cpp
// Function: void bench<demo_data(std::vector<std::vector<unsigned int, std::allocator<unsigned int>>, std::allocator<std::vector<unsigned int, std::allocator<unsigned int>>>> const&, std::vector<std::vector<unsigned int, std::allocator<unsigned int>>, std::allocator<std::vector<unsigned int, std::allocator<unsigned int>>>> const&, unsigned long)::$_1>(demo_data(std::vector<std::vector<unsigned int, std::allocator<unsigned int>>, std::allocator<std::vector<unsigned int, std::allocator<unsigned int>>>> const&, std::vector<std::vector<unsigned int, std::allocator<unsigned int>>, std::allocator<std::vector<unsigned int, std::allocator<unsigned int>>>> const&, unsigned long)::$_1, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, LinuxEventsWrapper&, float&, std::vector<unsigned int, std::allocator<unsigned int>>&, unsigned long, unsigned long, bool)
void bench(F f, const std::string &name,
           LinuxEventsWrapper &unified,
           float& elapsed,
           std::vector<uint32_t> &answer, size_t sum, size_t expected,
           bool print) {
  WallClockTimer tm;
  unified.start();
  f();
  unified.end();
  elapsed += tm.split();
  if (answer.size() != expected)
    std::cerr << "bug: expected " << expected << " but got " << answer.size()
              << "\n";
#ifdef __linux__
  if (print) {
    double cycles = unified.get_result(PERF_COUNT_HW_CPU_CYCLES);
    double instructions = unified.get_result(PERF_COUNT_HW_INSTRUCTIONS);
    double misses = unified.get_result(PERF_COUNT_HW_BRANCH_MISSES);
    std::cout << name << std::endl;
    std::cout << cycles / sum << " cycles/element " << std::endl;
    std::cout << instructions / cycles << " instructions/cycles " << std::endl;
    std::cout << misses / sum << " miss/element " << std::endl;
  }
#endif
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movb 0x28(%rbp), %al
leaq 0x10(%rbp), %r10
movq %r10, -0x88(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
andb $0x1, %al
movb %al, -0x31(%rbp)
leaq -0x58(%rbp), %rdi
movq %rdi, -0x80(%rbp)
callq 0x11290
movq -0x10(%rbp), %rdi
callq 0x112f0
movq -0x88(%rbp), %rdi
callq 0x76e0
movq -0x10(%rbp), %rdi
callq 0x11380
movq -0x80(%rbp), %rdi
callq 0x11430
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x78(%rbp)
testq %rax, %rax
movss %xmm0, -0x74(%rbp)
js 0x522f
movss -0x78(%rbp), %xmm0
movss %xmm0, -0x74(%rbp)
movss -0x74(%rbp), %xmm0
movq -0x18(%rbp), %rax
addss (%rax), %xmm0
movss %xmm0, (%rax)
movq -0x20(%rbp), %rdi
callq 0x7a40
cmpq -0x30(%rbp), %rax
je 0x52ab
movq 0x18d92(%rip), %rdi     # 0x1dfe8
leaq 0xf065(%rip), %rsi      # 0x142c2
callq 0x3280
movq %rax, %rdi
movq -0x30(%rbp), %rsi
callq 0x3090
movq %rax, %rdi
leaq 0xf059(%rip), %rsi      # 0x142d1
callq 0x3280
movq %rax, -0x90(%rbp)
movq -0x20(%rbp), %rdi
callq 0x7a40
movq -0x90(%rbp), %rdi
movq %rax, %rsi
callq 0x3090
movq %rax, %rdi
leaq 0xee03(%rip), %rsi      # 0x140a9
callq 0x3280
testb $0x1, -0x31(%rbp)
je 0x5483
movq -0x10(%rbp), %rdi
xorl %esi, %esi
callq 0x11460
movq %rax, %xmm0
movaps 0xed44(%rip), %xmm1     # 0x14010
movaps %xmm1, -0xb0(%rbp)
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0xed41(%rip), %xmm1     # 0x14020
movaps %xmm1, -0xa0(%rbp)
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd %xmm0, -0x60(%rbp)
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x11460
movaps -0xb0(%rbp), %xmm2
movaps -0xa0(%rbp), %xmm1
movq %rax, %xmm0
punpckldq %xmm2, %xmm0    # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd %xmm0, -0x68(%rbp)
movq -0x10(%rbp), %rdi
movl $0x5, %esi
callq 0x11460
movaps -0xb0(%rbp), %xmm2
movaps -0xa0(%rbp), %xmm1
movq %rax, %xmm0
punpckldq %xmm2, %xmm0    # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd %xmm0, -0x70(%rbp)
movq -0x8(%rbp), %rsi
movq 0x18c51(%rip), %rdi     # 0x1dfc8
movq %rdi, -0xc0(%rbp)
callq 0x3260
movq %rax, %rdi
movq 0x18c1b(%rip), %rsi     # 0x1dfa8
movq %rsi, -0xb8(%rbp)
callq 0x32c0
movq -0xc0(%rbp), %rdi
movaps -0xb0(%rbp), %xmm3
movaps -0xa0(%rbp), %xmm2
movsd -0x60(%rbp), %xmm0
movq -0x28(%rbp), %xmm1
punpckldq %xmm3, %xmm1    # xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1]
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
callq 0x34a0
movq %rax, %rdi
leaq 0xeefd(%rip), %rsi      # 0x142db
callq 0x3280
movq -0xb8(%rbp), %rsi
movq %rax, %rdi
callq 0x32c0
movq -0xc0(%rbp), %rdi
movsd -0x68(%rbp), %xmm0
movsd -0x60(%rbp), %xmm1
divsd %xmm1, %xmm0
callq 0x34a0
movq %rax, %rdi
leaq 0xeed6(%rip), %rsi      # 0x142ec
callq 0x3280
movq -0xb8(%rbp), %rsi
movq %rax, %rdi
callq 0x32c0
movaps -0xb0(%rbp), %xmm3
movaps -0xa0(%rbp), %xmm2
movsd -0x70(%rbp), %xmm0
movq -0x28(%rbp), %xmm1
punpckldq %xmm3, %xmm1    # xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1]
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movq 0x18b68(%rip), %rdi     # 0x1dfc8
callq 0x34a0
movq %rax, %rdi
leaq 0xee93(%rip), %rsi      # 0x14302
callq 0x3280
movq %rax, %rdi
movq 0x18b2a(%rip), %rsi     # 0x1dfa8
callq 0x32c0
addq $0xc0, %rsp
popq %rbp
retq
nopl (%rax)