// File: WojciechMula[P]utf16utf8/benchmarks/benchmark_from_utf16.cpp
// Function: Benchmark::run_from_utf16(RandomUTF16&, unsigned long)
void run_from_utf16(RandomUTF16& generator, size_t repeat) {

        const auto UTF16 = generator.generate(size);
        size_t volume = UTF16.size() * sizeof(UTF16[0]);


        std::vector<uint8_t> scalar_out;
        std::vector<uint8_t> sse_out;
        scalar_out.resize(4 * size + 32);
        sse_out.resize(4 * size + 32);

        auto scalar = [&UTF16, &scalar_out]() {
            utf16_to_utf8(UTF16.data(), (uint8_t*)scalar_out.data());
        };

        auto scalar_utf8lib = [&UTF16, &scalar_out]() {
            scalar_out.clear();
            utf8::utf16to8(UTF16.begin(), UTF16.end(), back_inserter(scalar_out));
        };

        auto sse = [&UTF16, &sse_out, size=size]() {
            sse_convert_utf16_to_utf8(UTF16.data(), size, (uint8_t*)sse_out.data());
        };

        auto sse_hybrid= [&UTF16, &sse_out, size=size]() {
            sse_convert_utf16_to_utf8_hybrid(UTF16.data(), size, (uint8_t*)sse_out.data());
        };

        RUN("scalar", scalar);
        RUN("scalar_utf8lib", scalar_utf8lib);

        RUN("SSE",    sse);
        RUN("SSEH",   sse_hybrid);
    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x800, %rsp            # imm = 0x800
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x718(%rbp)
movq -0x10(%rbp), %rsi
movq (%rax), %rdx
leaq -0x30(%rbp), %rdi
movq %rdi, -0x720(%rbp)
callq 0x75c0
movq -0x720(%rbp), %rdi
callq 0x7980
addq %rax, %rax
movq %rax, -0x38(%rbp)
leaq -0x50(%rbp), %rdi
movq %rdi, -0x710(%rbp)
callq 0xb440
leaq -0x68(%rbp), %rdi
callq 0xb440
movq -0x718(%rbp), %rax
movq -0x710(%rbp), %rdi
movq (%rax), %rax
leaq 0x20(,%rax,4), %rsi
callq 0xdd70
jmp 0xd275
movq -0x718(%rbp), %rax
movq (%rax), %rax
leaq 0x20(,%rax,4), %rsi
leaq -0x68(%rbp), %rdi
callq 0xdd70
jmp 0xd292
movq -0x718(%rbp), %rax
leaq -0x30(%rbp), %rdx
movq %rdx, -0x88(%rbp)
leaq -0x50(%rbp), %rcx
movq %rcx, -0x80(%rbp)
movq %rdx, -0x98(%rbp)
movq %rcx, -0x90(%rbp)
movq %rdx, -0xb0(%rbp)
leaq -0x68(%rbp), %rcx
movq %rcx, -0xa8(%rbp)
movq (%rax), %rsi
movq %rsi, -0xa0(%rbp)
movq %rdx, -0xc8(%rbp)
movq %rcx, -0xc0(%rbp)
movq (%rax), %rax
movq %rax, -0xb8(%rbp)
leaq 0xc0b4(%rip), %rdi      # 0x193a9
leaq 0xc0b6(%rip), %rsi      # 0x193b2
xorl %eax, %eax
callq 0x2050
jmp 0xd305
movq 0x14ca4(%rip), %rax     # 0x21fb0
movq (%rax), %rdi
callq 0x2200
jmp 0xd316
leaq -0x1b0(%rbp), %rdi
callq 0xde00
jmp 0xd324
leaq -0x218(%rbp), %rdi
callq 0xdf10
jmp 0xd332
movq $0x0, -0x220(%rbp)
movq -0x220(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0xd41c
leaq -0x1b0(%rbp), %rdi
callq 0xdfa0
jmp 0xd35c
leaq -0x88(%rbp), %rdi
callq 0xdfe0
jmp 0xd36a
leaq -0x1b0(%rbp), %rdi
callq 0xe030
movq %rax, -0x728(%rbp)
jmp 0xd37f
movq -0x728(%rbp), %rsi
leaq -0x240(%rbp), %rdi
callq 0xe0a0
jmp 0xd394
leaq -0x218(%rbp), %rdi
leaq -0x240(%rbp), %rsi
callq 0xe0e0
jmp 0xd3a9
leaq -0x240(%rbp), %rdi
callq 0xe180
movq -0x220(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x220(%rbp)
jmp 0xd33d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xdd0e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xd648
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xd63c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x240(%rbp), %rdi
callq 0xe180
jmp 0xd63c
leaq -0x1f0(%rbp), %rdi
callq 0xe1a0
vmovsd %xmm0, -0x730(%rbp)
jmp 0xd432
leaq -0x1f0(%rbp), %rdi
callq 0xe1d0
vmovsd %xmm0, -0x738(%rbp)
jmp 0xd448
vmovsd -0x730(%rbp), %xmm0
vmovsd -0x738(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd 0xbe34(%rip), %xmm1     # 0x19298
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x248(%rbp)
leaq -0x1f0(%rbp), %rdi
callq 0xe200
vmovsd %xmm0, -0x740(%rbp)
jmp 0xd486
vmovsd -0x740(%rbp), %xmm0
vcvtusi2sdq -0x38(%rbp), %xmm1, %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x250(%rbp)
vcvtusi2sdq -0x38(%rbp), %xmm0, %xmm0
vmovsd %xmm0, -0x750(%rbp)
leaq -0x1f0(%rbp), %rdi
callq 0xe230
vmovsd %xmm0, -0x748(%rbp)
jmp 0xd4c6
vmovsd -0x750(%rbp), %xmm0
vmovsd -0x748(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x258(%rbp)
leaq -0x1b0(%rbp), %rdi
callq 0xe260
movb %al, -0x751(%rbp)
jmp 0xd4f6
movb -0x751(%rbp), %al
testb $0x1, %al
jne 0xd502
jmp 0xd52c
vmovsd -0x250(%rbp), %xmm0
vmovsd -0x248(%rbp), %xmm1
vmovsd -0x258(%rbp), %xmm2
leaq 0xbe98(%rip), %rdi      # 0x193b9
movb $0x3, %al
callq 0x2050
jmp 0xd52a
jmp 0xd546
vmovsd -0x258(%rbp), %xmm0
leaq 0xbec5(%rip), %rdi      # 0x19400
movb $0x1, %al
callq 0x2050
jmp 0xd544
jmp 0xd546
leaq -0x218(%rbp), %rdi
callq 0xe290
leaq -0x1b0(%rbp), %rdi
callq 0xe2d0
leaq 0xbe44(%rip), %rdi      # 0x193a9
leaq 0xbec0(%rip), %rsi      # 0x1942c
xorl %eax, %eax
callq 0x2050
jmp 0xd575
movq 0x14a34(%rip), %rax     # 0x21fb0
movq (%rax), %rdi
callq 0x2200
jmp 0xd586
leaq -0x340(%rbp), %rdi
callq 0xde00
jmp 0xd594
leaq -0x3a8(%rbp), %rdi
callq 0xdf10
jmp 0xd5a2
movq $0x0, -0x3b0(%rbp)
movq -0x3b0(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0xd698
leaq -0x340(%rbp), %rdi
callq 0xdfa0
jmp 0xd5cc
leaq -0x98(%rbp), %rdi
callq 0xe300
jmp 0xd5da
leaq -0x340(%rbp), %rdi
callq 0xe030
movq %rax, -0x760(%rbp)
jmp 0xd5ef
movq -0x760(%rbp), %rsi
leaq -0x3d0(%rbp), %rdi
callq 0xe0a0
jmp 0xd604
leaq -0x3a8(%rbp), %rdi
leaq -0x3d0(%rbp), %rsi
callq 0xe0e0
jmp 0xd619
leaq -0x3d0(%rbp), %rdi
callq 0xe180
movq -0x3b0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x3b0(%rbp)
jmp 0xd5ad
leaq -0x218(%rbp), %rdi
callq 0xe290
leaq -0x1b0(%rbp), %rdi
callq 0xe2d0
jmp 0xdd0e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xd8c4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xd8b8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x3d0(%rbp), %rdi
callq 0xe180
jmp 0xd8b8
leaq -0x380(%rbp), %rdi
callq 0xe1a0
vmovsd %xmm0, -0x768(%rbp)
jmp 0xd6ae
leaq -0x380(%rbp), %rdi
callq 0xe1d0
vmovsd %xmm0, -0x770(%rbp)
jmp 0xd6c4
vmovsd -0x768(%rbp), %xmm0
vmovsd -0x770(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd 0xbbb8(%rip), %xmm1     # 0x19298
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x3d8(%rbp)
leaq -0x380(%rbp), %rdi
callq 0xe200
vmovsd %xmm0, -0x778(%rbp)
jmp 0xd702
vmovsd -0x778(%rbp), %xmm0
vcvtusi2sdq -0x38(%rbp), %xmm1, %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x3e0(%rbp)
vcvtusi2sdq -0x38(%rbp), %xmm0, %xmm0
vmovsd %xmm0, -0x788(%rbp)
leaq -0x380(%rbp), %rdi
callq 0xe230
vmovsd %xmm0, -0x780(%rbp)
jmp 0xd742
vmovsd -0x788(%rbp), %xmm0
vmovsd -0x780(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x3e8(%rbp)
leaq -0x340(%rbp), %rdi
callq 0xe260
movb %al, -0x789(%rbp)
jmp 0xd772
movb -0x789(%rbp), %al
testb $0x1, %al
jne 0xd77e
jmp 0xd7a8
vmovsd -0x3e0(%rbp), %xmm0
vmovsd -0x3d8(%rbp), %xmm1
vmovsd -0x3e8(%rbp), %xmm2
leaq 0xbc1c(%rip), %rdi      # 0x193b9
movb $0x3, %al
callq 0x2050
jmp 0xd7a6
jmp 0xd7c2
vmovsd -0x3e8(%rbp), %xmm0
leaq 0xbc49(%rip), %rdi      # 0x19400
movb $0x1, %al
callq 0x2050
jmp 0xd7c0
jmp 0xd7c2
leaq -0x3a8(%rbp), %rdi
callq 0xe290
leaq -0x340(%rbp), %rdi
callq 0xe2d0
leaq 0xbbc8(%rip), %rdi      # 0x193a9
leaq 0xbc53(%rip), %rsi      # 0x1943b
xorl %eax, %eax
callq 0x2050
jmp 0xd7f1
movq 0x147b8(%rip), %rax     # 0x21fb0
movq (%rax), %rdi
callq 0x2200
jmp 0xd802
leaq -0x4d0(%rbp), %rdi
callq 0xde00
jmp 0xd810
leaq -0x538(%rbp), %rdi
callq 0xdf10
jmp 0xd81e
movq $0x0, -0x540(%rbp)
movq -0x540(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0xd914
leaq -0x4d0(%rbp), %rdi
callq 0xdfa0
jmp 0xd848
leaq -0xb0(%rbp), %rdi
callq 0xe370
jmp 0xd856
leaq -0x4d0(%rbp), %rdi
callq 0xe030
movq %rax, -0x798(%rbp)
jmp 0xd86b
movq -0x798(%rbp), %rsi
leaq -0x560(%rbp), %rdi
callq 0xe0a0
jmp 0xd880
leaq -0x538(%rbp), %rdi
leaq -0x560(%rbp), %rsi
callq 0xe0e0
jmp 0xd895
leaq -0x560(%rbp), %rdi
callq 0xe180
movq -0x540(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x540(%rbp)
jmp 0xd829
leaq -0x3a8(%rbp), %rdi
callq 0xe290
leaq -0x340(%rbp), %rdi
callq 0xe2d0
jmp 0xdd0e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xdb40
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xdb34
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x560(%rbp), %rdi
callq 0xe180
jmp 0xdb34
leaq -0x510(%rbp), %rdi
callq 0xe1a0
vmovsd %xmm0, -0x7a0(%rbp)
jmp 0xd92a
leaq -0x510(%rbp), %rdi
callq 0xe1d0
vmovsd %xmm0, -0x7a8(%rbp)
jmp 0xd940
vmovsd -0x7a0(%rbp), %xmm0
vmovsd -0x7a8(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd 0xb93c(%rip), %xmm1     # 0x19298
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x568(%rbp)
leaq -0x510(%rbp), %rdi
callq 0xe200
vmovsd %xmm0, -0x7b0(%rbp)
jmp 0xd97e
vmovsd -0x7b0(%rbp), %xmm0
vcvtusi2sdq -0x38(%rbp), %xmm1, %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x570(%rbp)
vcvtusi2sdq -0x38(%rbp), %xmm0, %xmm0
vmovsd %xmm0, -0x7c0(%rbp)
leaq -0x510(%rbp), %rdi
callq 0xe230
vmovsd %xmm0, -0x7b8(%rbp)
jmp 0xd9be
vmovsd -0x7c0(%rbp), %xmm0
vmovsd -0x7b8(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x578(%rbp)
leaq -0x4d0(%rbp), %rdi
callq 0xe260
movb %al, -0x7c1(%rbp)
jmp 0xd9ee
movb -0x7c1(%rbp), %al
testb $0x1, %al
jne 0xd9fa
jmp 0xda24
vmovsd -0x570(%rbp), %xmm0
vmovsd -0x568(%rbp), %xmm1
vmovsd -0x578(%rbp), %xmm2
leaq 0xb9a0(%rip), %rdi      # 0x193b9
movb $0x3, %al
callq 0x2050
jmp 0xda22
jmp 0xda3e
vmovsd -0x578(%rbp), %xmm0
leaq 0xb9cd(%rip), %rdi      # 0x19400
movb $0x1, %al
callq 0x2050
jmp 0xda3c
jmp 0xda3e
leaq -0x538(%rbp), %rdi
callq 0xe290
leaq -0x4d0(%rbp), %rdi
callq 0xe2d0
leaq 0xb94c(%rip), %rdi      # 0x193a9
leaq 0xb9db(%rip), %rsi      # 0x1943f
xorl %eax, %eax
callq 0x2050
jmp 0xda6d
movq 0x1453c(%rip), %rax     # 0x21fb0
movq (%rax), %rdi
callq 0x2200
jmp 0xda7e
leaq -0x660(%rbp), %rdi
callq 0xde00
jmp 0xda8c
leaq -0x6c8(%rbp), %rdi
callq 0xdf10
jmp 0xda9a
movq $0x0, -0x6d0(%rbp)
movq -0x6d0(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0xdb90
leaq -0x660(%rbp), %rdi
callq 0xdfa0
jmp 0xdac4
leaq -0xc8(%rbp), %rdi
callq 0xe3c0
jmp 0xdad2
leaq -0x660(%rbp), %rdi
callq 0xe030
movq %rax, -0x7d0(%rbp)
jmp 0xdae7
movq -0x7d0(%rbp), %rsi
leaq -0x6f0(%rbp), %rdi
callq 0xe0a0
jmp 0xdafc
leaq -0x6c8(%rbp), %rdi
leaq -0x6f0(%rbp), %rsi
callq 0xe0e0
jmp 0xdb11
leaq -0x6f0(%rbp), %rdi
callq 0xe180
movq -0x6d0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x6d0(%rbp)
jmp 0xdaa5
leaq -0x538(%rbp), %rdi
callq 0xe290
leaq -0x4d0(%rbp), %rdi
callq 0xe2d0
jmp 0xdd0e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xdd02
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xdcf6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x6f0(%rbp), %rdi
callq 0xe180
jmp 0xdcf6
leaq -0x6a0(%rbp), %rdi
callq 0xe1a0
vmovsd %xmm0, -0x7d8(%rbp)
jmp 0xdba6
leaq -0x6a0(%rbp), %rdi
callq 0xe1d0
vmovsd %xmm0, -0x7e0(%rbp)
jmp 0xdbbc
vmovsd -0x7d8(%rbp), %xmm0
vmovsd -0x7e0(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd 0xb6c0(%rip), %xmm1     # 0x19298
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x6f8(%rbp)
leaq -0x6a0(%rbp), %rdi
callq 0xe200
vmovsd %xmm0, -0x7e8(%rbp)
jmp 0xdbfa
vmovsd -0x7e8(%rbp), %xmm0
vcvtusi2sdq -0x38(%rbp), %xmm1, %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x700(%rbp)
vcvtusi2sdq -0x38(%rbp), %xmm0, %xmm0
vmovsd %xmm0, -0x7f8(%rbp)
leaq -0x6a0(%rbp), %rdi
callq 0xe230
vmovsd %xmm0, -0x7f0(%rbp)
jmp 0xdc3a
vmovsd -0x7f8(%rbp), %xmm0
vmovsd -0x7f0(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x708(%rbp)
leaq -0x660(%rbp), %rdi
callq 0xe260
movb %al, -0x7f9(%rbp)
jmp 0xdc6a
movb -0x7f9(%rbp), %al
testb $0x1, %al
jne 0xdc76
jmp 0xdca0
vmovsd -0x700(%rbp), %xmm0
vmovsd -0x6f8(%rbp), %xmm1
vmovsd -0x708(%rbp), %xmm2
leaq 0xb724(%rip), %rdi      # 0x193b9
movb $0x3, %al
callq 0x2050
jmp 0xdc9e
jmp 0xdcba
vmovsd -0x708(%rbp), %xmm0
leaq 0xb751(%rip), %rdi      # 0x19400
movb $0x1, %al
callq 0x2050
jmp 0xdcb8
jmp 0xdcba
leaq -0x6c8(%rbp), %rdi
callq 0xe290
leaq -0x660(%rbp), %rdi
callq 0xe2d0
leaq -0x68(%rbp), %rdi
callq 0xb630
leaq -0x50(%rbp), %rdi
callq 0xb630
leaq -0x30(%rbp), %rdi
callq 0x7a40
addq $0x800, %rsp            # imm = 0x800
popq %rbp
retq
leaq -0x6c8(%rbp), %rdi
callq 0xe290
leaq -0x660(%rbp), %rdi
callq 0xe2d0
leaq -0x68(%rbp), %rdi
callq 0xb630
leaq -0x50(%rbp), %rdi
callq 0xb630
leaq -0x30(%rbp), %rdi
callq 0x7a40
movq -0x70(%rbp), %rdi
callq 0x22e0
nopw %cs:(%rax,%rax)
nopl (%rax)