// File: travisdowns[P]avx-turbo/avx-turbo.cpp
// Function: inner_result run_test<RdtscClock, 101ul, 3ul>(void (*)(unsigned long), unsigned long, outer_timer&, hot_barrier*)
inner_result run_test(cal_f* func, size_t iters, outer_timer& outer, hot_barrier *barrier) {
    assert(iters % 100 == 0);

    std::array<typename CLOCK::delta_t, TRIES> results;

    inner_result result;

    if (arg_dirty) {
        dirty_it();
    }

    if (arg_dirty16) {
        dirty_it16();
    }

    result.ostart_ts = RdtscClock::now();
    for (size_t w = 0; w < WARMUP + 1; w++) {
        result.istart_ts = RdtscClock::now();
        outer.start();
        for (size_t r = 0; r < TRIES; r++) {
            auto t0 = CLOCK::now();
            func(iters);
            auto t1 = CLOCK::now();
            func(iters * 2);
            auto t2 = CLOCK::now();
            results[r] = (t2 - t1) - (t1 - t0);
        }
        outer.stop();
        result.iend_ts = RdtscClock::now();
    }

    for (barrier->increment(); !barrier->is_broken();) {
        func(iters);
    }
    result.oend_ts = RdtscClock::now();

    std::array<uint64_t, TRIES> nanos = {};
    std::transform(results.begin(), results.end(), nanos.begin(), CLOCK::to_nanos);
    DescriptiveStats stats = get_stats(nanos.begin(), nanos.end());

    result.mops = ((double)iters / stats.getMedian());
    return result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x710, %rsp            # imm = 0x710
movq %rdi, -0x6d0(%rbp)
movq %rdi, -0x6c8(%rbp)
movq %rsi, -0x8(%rbp)
movq %rdx, -0x10(%rbp)
movq %rcx, -0x18(%rbp)
movq %r8, -0x20(%rbp)
movq -0x10(%rbp), %rax
movl $0x64, %ecx
xorl %edx, %edx
divq %rcx
cmpq $0x0, %rdx
jne 0x31e7f
jmp 0x31e9e
leaq 0xfa9f(%rip), %rdi      # 0x41925
leaq 0xe80d(%rip), %rsi      # 0x4069a
movl $0x17b, %edx            # imm = 0x17B
leaq 0xfa9d(%rip), %rcx      # 0x41936
callq 0x72e0
leaq 0x29d33(%rip), %rdi     # 0x5bbd8
callq 0x10ee0
testb $0x1, %al
jne 0x31eb0
jmp 0x31eb5
callq 0x3f215
leaq 0x29de4(%rip), %rdi     # 0x5bca0
callq 0x10ee0
testb $0x1, %al
jne 0x31ec7
jmp 0x31ecc
callq 0x3f21f
callq 0x31e10
movq %rax, %rcx
movq -0x6d0(%rbp), %rax
movq %rcx, 0x8(%rax)
movq $0x0, -0x350(%rbp)
cmpq $0x4, -0x350(%rbp)
jae 0x31ff6
callq 0x31e10
movq %rax, %rcx
movq -0x6d0(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x18(%rbp), %rdi
movq (%rdi), %rax
callq *(%rax)
movq $0x0, -0x358(%rbp)
cmpq $0x65, -0x358(%rbp)
jae 0x31fc2
callq 0x31e10
movq %rax, -0x360(%rbp)
movq -0x8(%rbp), %rax
movq -0x10(%rbp), %rdi
callq *%rax
callq 0x31e10
movq %rax, -0x368(%rbp)
movq -0x8(%rbp), %rax
movq -0x10(%rbp), %rdi
shlq %rdi
callq *%rax
callq 0x31e10
movq %rax, -0x370(%rbp)
movq -0x370(%rbp), %rax
subq -0x368(%rbp), %rax
movq -0x368(%rbp), %rcx
subq -0x360(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x6d8(%rbp)
movq -0x358(%rbp), %rsi
leaq -0x348(%rbp), %rdi
callq 0x327e0
movq -0x6d8(%rbp), %rcx
movq %rcx, (%rax)
movq -0x358(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x358(%rbp)
jmp 0x31f1f
movq -0x18(%rbp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
callq 0x31e10
movq %rax, %rcx
movq -0x6d0(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x350(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x350(%rbp)
jmp 0x31eea
movq -0x20(%rbp), %rdi
callq 0x32620
movq -0x20(%rbp), %rdi
callq 0x32650
xorb $-0x1, %al
testb $0x1, %al
jne 0x32010
jmp 0x3201c
movq -0x8(%rbp), %rax
movq -0x10(%rbp), %rdi
callq *%rax
jmp 0x31fff
callq 0x31e10
movq %rax, %rcx
movq -0x6d0(%rbp), %rax
movq %rcx, 0x10(%rax)
leaq -0x698(%rbp), %rdi
movq %rdi, -0x6f0(%rbp)
xorl %esi, %esi
movl $0x328, %edx            # imm = 0x328
callq 0x7230
leaq -0x348(%rbp), %rdi
movq %rdi, -0x708(%rbp)
callq 0x32870
movq -0x708(%rbp), %rdi
movq %rax, -0x700(%rbp)
callq 0x32890
movq -0x6f0(%rbp), %rdi
movq %rax, -0x6f8(%rbp)
callq 0x32870
movq -0x700(%rbp), %rdi
movq -0x6f8(%rbp), %rsi
movq %rax, %rdx
leaq 0x486(%rip), %rcx       # 0x32520
callq 0x32810
movq -0x6f0(%rbp), %rdi
callq 0x32870
movq -0x6f0(%rbp), %rdi
movq %rax, -0x6e8(%rbp)
callq 0x32890
movq -0x6e8(%rbp), %rsi
movq %rax, %rdx
leaq -0x6c0(%rbp), %rdi
callq 0x328c0
movaps 0xdf35(%rip), %xmm1     # 0x40010
movq -0x10(%rbp), %xmm0
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0xdf34(%rip), %xmm1     # 0x40020
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd %xmm0, -0x6e0(%rbp)
leaq -0x6c0(%rbp), %rdi
callq 0x32a60
movq -0x6d0(%rbp), %rcx
movq -0x6c8(%rbp), %rax
movaps %xmm0, %xmm1
movsd -0x6e0(%rbp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, (%rcx)
addq $0x710, %rsp            # imm = 0x710
popq %rbp
retq
nopl (%rax)