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

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

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

        auto scalar = [&UTF8, &scalar_out]() {
            utf8_to_utf16(UTF8.data(), scalar_out.data());
        };

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

        auto sse = [&UTF8, &sse_out, size=size]() {
            sse_convert_valid_utf8_to_utf16_lemire(UTF8.data(), size, sse_out.data());
        };

        auto pext = [&UTF8, &pext_out, size=size]() {
            pext_convert_utf8_to_utf16(UTF8.data(), size, pext_out.data());
        };

        RUN("scalar", scalar);
        RUN("scalar_utf8lib", scalar_utf8lib);
        RUN("SSE",    sse);
        RUN("PEXT",   pext);
    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x820, %rsp            # imm = 0x820
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x730(%rbp)
movq -0x10(%rbp), %rsi
movq (%rax), %rdx
leaq -0x30(%rbp), %rdi
movq %rdi, -0x738(%rbp)
callq 0xaf20
movq -0x738(%rbp), %rdi
callq 0xb540
movq %rax, -0x38(%rbp)
leaq -0x50(%rbp), %rdi
movq %rdi, -0x728(%rbp)
callq 0x7870
leaq -0x68(%rbp), %rdi
callq 0x7870
leaq -0x80(%rbp), %rdi
callq 0x7870
movq -0x730(%rbp), %rax
movq -0x728(%rbp), %rdi
movq (%rax), %rax
leaq 0x20(,%rax,4), %rsi
callq 0xdf30
jmp 0xd3bb
movq -0x730(%rbp), %rax
movq (%rax), %rax
leaq 0x20(,%rax,4), %rsi
leaq -0x68(%rbp), %rdi
callq 0xdf30
jmp 0xd3d8
movq -0x730(%rbp), %rax
movq (%rax), %rax
leaq 0x20(,%rax,4), %rsi
leaq -0x80(%rbp), %rdi
callq 0xdf30
jmp 0xd3f5
movq -0x730(%rbp), %rax
leaq -0x30(%rbp), %rcx
movq %rcx, -0xa0(%rbp)
leaq -0x50(%rbp), %rdx
movq %rdx, -0x98(%rbp)
movq %rcx, -0xb0(%rbp)
movq %rdx, -0xa8(%rbp)
movq %rcx, -0xc8(%rbp)
leaq -0x68(%rbp), %rdx
movq %rdx, -0xc0(%rbp)
movq (%rax), %rdx
movq %rdx, -0xb8(%rbp)
movq %rcx, -0xe0(%rbp)
leaq -0x80(%rbp), %rcx
movq %rcx, -0xd8(%rbp)
movq (%rax), %rax
movq %rax, -0xd0(%rbp)
leaq 0xc00b(%rip), %rdi      # 0x1946a
leaq 0xc00d(%rip), %rsi      # 0x19473
xorl %eax, %eax
callq 0x2050
jmp 0xd46f
movq 0x14b3a(%rip), %rax     # 0x21fb0
movq (%rax), %rdi
callq 0x2200
jmp 0xd480
leaq -0x1c8(%rbp), %rdi
callq 0xdfc0
jmp 0xd48e
leaq -0x230(%rbp), %rdi
callq 0xe0d0
jmp 0xd49c
movq $0x0, -0x238(%rbp)
movq -0x238(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0xd59e
leaq -0x1c8(%rbp), %rdi
callq 0xe160
jmp 0xd4c6
leaq -0xa0(%rbp), %rdi
callq 0xe1a0
jmp 0xd4d4
leaq -0x1c8(%rbp), %rdi
callq 0xe1f0
movq %rax, -0x740(%rbp)
jmp 0xd4e9
movq -0x740(%rbp), %rsi
leaq -0x258(%rbp), %rdi
callq 0xe260
jmp 0xd4fe
leaq -0x230(%rbp), %rdi
leaq -0x258(%rbp), %rsi
callq 0xe2a0
jmp 0xd513
leaq -0x258(%rbp), %rdi
callq 0xe340
movq -0x238(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x238(%rbp)
jmp 0xd4a7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0xdecf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0xd7ca
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0xd7be
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x258(%rbp), %rdi
callq 0xe340
jmp 0xd7be
leaq -0x208(%rbp), %rdi
callq 0xe360
vmovsd %xmm0, -0x748(%rbp)
jmp 0xd5b4
leaq -0x208(%rbp), %rdi
callq 0xe390
vmovsd %xmm0, -0x750(%rbp)
jmp 0xd5ca
vmovsd -0x748(%rbp), %xmm0
vmovsd -0x750(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd 0xbcb2(%rip), %xmm1     # 0x19298
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x260(%rbp)
leaq -0x208(%rbp), %rdi
callq 0xe3c0
vmovsd %xmm0, -0x758(%rbp)
jmp 0xd608
vmovsd -0x758(%rbp), %xmm0
vcvtusi2sdq -0x38(%rbp), %xmm1, %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x268(%rbp)
vcvtusi2sdq -0x38(%rbp), %xmm0, %xmm0
vmovsd %xmm0, -0x768(%rbp)
leaq -0x208(%rbp), %rdi
callq 0xe3f0
vmovsd %xmm0, -0x760(%rbp)
jmp 0xd648
vmovsd -0x768(%rbp), %xmm0
vmovsd -0x760(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x270(%rbp)
leaq -0x1c8(%rbp), %rdi
callq 0xe420
movb %al, -0x769(%rbp)
jmp 0xd678
movb -0x769(%rbp), %al
testb $0x1, %al
jne 0xd684
jmp 0xd6ae
vmovsd -0x268(%rbp), %xmm0
vmovsd -0x260(%rbp), %xmm1
vmovsd -0x270(%rbp), %xmm2
leaq 0xbdd7(%rip), %rdi      # 0x1947a
movb $0x3, %al
callq 0x2050
jmp 0xd6ac
jmp 0xd6c8
vmovsd -0x270(%rbp), %xmm0
leaq 0xbe04(%rip), %rdi      # 0x194c1
movb $0x1, %al
callq 0x2050
jmp 0xd6c6
jmp 0xd6c8
leaq -0x230(%rbp), %rdi
callq 0xe450
leaq -0x1c8(%rbp), %rdi
callq 0xe490
leaq 0xbd83(%rip), %rdi      # 0x1946a
leaq 0xbdff(%rip), %rsi      # 0x194ed
xorl %eax, %eax
callq 0x2050
jmp 0xd6f7
movq 0x148b2(%rip), %rax     # 0x21fb0
movq (%rax), %rdi
callq 0x2200
jmp 0xd708
leaq -0x358(%rbp), %rdi
callq 0xdfc0
jmp 0xd716
leaq -0x3c0(%rbp), %rdi
callq 0xe0d0
jmp 0xd724
movq $0x0, -0x3c8(%rbp)
movq -0x3c8(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0xd82c
leaq -0x358(%rbp), %rdi
callq 0xe160
jmp 0xd74e
leaq -0xb0(%rbp), %rdi
callq 0xe4c0
jmp 0xd75c
leaq -0x358(%rbp), %rdi
callq 0xe1f0
movq %rax, -0x778(%rbp)
jmp 0xd771
movq -0x778(%rbp), %rsi
leaq -0x3e8(%rbp), %rdi
callq 0xe260
jmp 0xd786
leaq -0x3c0(%rbp), %rdi
leaq -0x3e8(%rbp), %rsi
callq 0xe2a0
jmp 0xd79b
leaq -0x3e8(%rbp), %rdi
callq 0xe340
movq -0x3c8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x3c8(%rbp)
jmp 0xd72f
leaq -0x230(%rbp), %rdi
callq 0xe450
leaq -0x1c8(%rbp), %rdi
callq 0xe490
jmp 0xdecf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0xda58
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0xda4c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x3e8(%rbp), %rdi
callq 0xe340
jmp 0xda4c
leaq -0x398(%rbp), %rdi
callq 0xe360
vmovsd %xmm0, -0x780(%rbp)
jmp 0xd842
leaq -0x398(%rbp), %rdi
callq 0xe390
vmovsd %xmm0, -0x788(%rbp)
jmp 0xd858
vmovsd -0x780(%rbp), %xmm0
vmovsd -0x788(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd 0xba24(%rip), %xmm1     # 0x19298
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x3f0(%rbp)
leaq -0x398(%rbp), %rdi
callq 0xe3c0
vmovsd %xmm0, -0x790(%rbp)
jmp 0xd896
vmovsd -0x790(%rbp), %xmm0
vcvtusi2sdq -0x38(%rbp), %xmm1, %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x3f8(%rbp)
vcvtusi2sdq -0x38(%rbp), %xmm0, %xmm0
vmovsd %xmm0, -0x7a0(%rbp)
leaq -0x398(%rbp), %rdi
callq 0xe3f0
vmovsd %xmm0, -0x798(%rbp)
jmp 0xd8d6
vmovsd -0x7a0(%rbp), %xmm0
vmovsd -0x798(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x400(%rbp)
leaq -0x358(%rbp), %rdi
callq 0xe420
movb %al, -0x7a1(%rbp)
jmp 0xd906
movb -0x7a1(%rbp), %al
testb $0x1, %al
jne 0xd912
jmp 0xd93c
vmovsd -0x3f8(%rbp), %xmm0
vmovsd -0x3f0(%rbp), %xmm1
vmovsd -0x400(%rbp), %xmm2
leaq 0xbb49(%rip), %rdi      # 0x1947a
movb $0x3, %al
callq 0x2050
jmp 0xd93a
jmp 0xd956
vmovsd -0x400(%rbp), %xmm0
leaq 0xbb76(%rip), %rdi      # 0x194c1
movb $0x1, %al
callq 0x2050
jmp 0xd954
jmp 0xd956
leaq -0x3c0(%rbp), %rdi
callq 0xe450
leaq -0x358(%rbp), %rdi
callq 0xe490
leaq 0xbaf5(%rip), %rdi      # 0x1946a
leaq 0xbb80(%rip), %rsi      # 0x194fc
xorl %eax, %eax
callq 0x2050
jmp 0xd985
movq 0x14624(%rip), %rax     # 0x21fb0
movq (%rax), %rdi
callq 0x2200
jmp 0xd996
leaq -0x4e8(%rbp), %rdi
callq 0xdfc0
jmp 0xd9a4
leaq -0x550(%rbp), %rdi
callq 0xe0d0
jmp 0xd9b2
movq $0x0, -0x558(%rbp)
movq -0x558(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0xdaba
leaq -0x4e8(%rbp), %rdi
callq 0xe160
jmp 0xd9dc
leaq -0xc8(%rbp), %rdi
callq 0xe530
jmp 0xd9ea
leaq -0x4e8(%rbp), %rdi
callq 0xe1f0
movq %rax, -0x7b0(%rbp)
jmp 0xd9ff
movq -0x7b0(%rbp), %rsi
leaq -0x578(%rbp), %rdi
callq 0xe260
jmp 0xda14
leaq -0x550(%rbp), %rdi
leaq -0x578(%rbp), %rsi
callq 0xe2a0
jmp 0xda29
leaq -0x578(%rbp), %rdi
callq 0xe340
movq -0x558(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x558(%rbp)
jmp 0xd9bd
leaq -0x3c0(%rbp), %rdi
callq 0xe450
leaq -0x358(%rbp), %rdi
callq 0xe490
jmp 0xdecf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0xdce6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0xdcda
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x578(%rbp), %rdi
callq 0xe340
jmp 0xdcda
leaq -0x528(%rbp), %rdi
callq 0xe360
vmovsd %xmm0, -0x7b8(%rbp)
jmp 0xdad0
leaq -0x528(%rbp), %rdi
callq 0xe390
vmovsd %xmm0, -0x7c0(%rbp)
jmp 0xdae6
vmovsd -0x7b8(%rbp), %xmm0
vmovsd -0x7c0(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd 0xb796(%rip), %xmm1     # 0x19298
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x580(%rbp)
leaq -0x528(%rbp), %rdi
callq 0xe3c0
vmovsd %xmm0, -0x7c8(%rbp)
jmp 0xdb24
vmovsd -0x7c8(%rbp), %xmm0
vcvtusi2sdq -0x38(%rbp), %xmm1, %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x588(%rbp)
vcvtusi2sdq -0x38(%rbp), %xmm0, %xmm0
vmovsd %xmm0, -0x7d8(%rbp)
leaq -0x528(%rbp), %rdi
callq 0xe3f0
vmovsd %xmm0, -0x7d0(%rbp)
jmp 0xdb64
vmovsd -0x7d8(%rbp), %xmm0
vmovsd -0x7d0(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x590(%rbp)
leaq -0x4e8(%rbp), %rdi
callq 0xe420
movb %al, -0x7d9(%rbp)
jmp 0xdb94
movb -0x7d9(%rbp), %al
testb $0x1, %al
jne 0xdba0
jmp 0xdbca
vmovsd -0x588(%rbp), %xmm0
vmovsd -0x580(%rbp), %xmm1
vmovsd -0x590(%rbp), %xmm2
leaq 0xb8bb(%rip), %rdi      # 0x1947a
movb $0x3, %al
callq 0x2050
jmp 0xdbc8
jmp 0xdbe4
vmovsd -0x590(%rbp), %xmm0
leaq 0xb8e8(%rip), %rdi      # 0x194c1
movb $0x1, %al
callq 0x2050
jmp 0xdbe2
jmp 0xdbe4
leaq -0x550(%rbp), %rdi
callq 0xe450
leaq -0x4e8(%rbp), %rdi
callq 0xe490
leaq 0xb867(%rip), %rdi      # 0x1946a
leaq 0xb8f6(%rip), %rsi      # 0x19500
xorl %eax, %eax
callq 0x2050
jmp 0xdc13
movq 0x14396(%rip), %rax     # 0x21fb0
movq (%rax), %rdi
callq 0x2200
jmp 0xdc24
leaq -0x678(%rbp), %rdi
callq 0xdfc0
jmp 0xdc32
leaq -0x6e0(%rbp), %rdi
callq 0xe0d0
jmp 0xdc40
movq $0x0, -0x6e8(%rbp)
movq -0x6e8(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0xdd48
leaq -0x678(%rbp), %rdi
callq 0xe160
jmp 0xdc6a
leaq -0xe0(%rbp), %rdi
callq 0xe580
jmp 0xdc78
leaq -0x678(%rbp), %rdi
callq 0xe1f0
movq %rax, -0x7e8(%rbp)
jmp 0xdc8d
movq -0x7e8(%rbp), %rsi
leaq -0x708(%rbp), %rdi
callq 0xe260
jmp 0xdca2
leaq -0x6e0(%rbp), %rdi
leaq -0x708(%rbp), %rsi
callq 0xe2a0
jmp 0xdcb7
leaq -0x708(%rbp), %rdi
callq 0xe340
movq -0x6e8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x6e8(%rbp)
jmp 0xdc4b
leaq -0x550(%rbp), %rdi
callq 0xe450
leaq -0x4e8(%rbp), %rdi
callq 0xe490
jmp 0xdecf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0xdec3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0xdeb7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x708(%rbp), %rdi
callq 0xe340
jmp 0xdeb7
leaq -0x6b8(%rbp), %rdi
callq 0xe360
vmovsd %xmm0, -0x7f0(%rbp)
jmp 0xdd5e
leaq -0x6b8(%rbp), %rdi
callq 0xe390
vmovsd %xmm0, -0x7f8(%rbp)
jmp 0xdd74
vmovsd -0x7f0(%rbp), %xmm0
vmovsd -0x7f8(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd 0xb508(%rip), %xmm1     # 0x19298
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x710(%rbp)
leaq -0x6b8(%rbp), %rdi
callq 0xe3c0
vmovsd %xmm0, -0x800(%rbp)
jmp 0xddb2
vmovsd -0x800(%rbp), %xmm0
vcvtusi2sdq -0x38(%rbp), %xmm1, %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x718(%rbp)
vcvtusi2sdq -0x38(%rbp), %xmm0, %xmm0
vmovsd %xmm0, -0x810(%rbp)
leaq -0x6b8(%rbp), %rdi
callq 0xe3f0
vmovsd %xmm0, -0x808(%rbp)
jmp 0xddf2
vmovsd -0x810(%rbp), %xmm0
vmovsd -0x808(%rbp), %xmm1
vdivsd %xmm1, %xmm0, %xmm0
vmovsd %xmm0, -0x720(%rbp)
leaq -0x678(%rbp), %rdi
callq 0xe420
movb %al, -0x811(%rbp)
jmp 0xde22
movb -0x811(%rbp), %al
testb $0x1, %al
jne 0xde2e
jmp 0xde58
vmovsd -0x718(%rbp), %xmm0
vmovsd -0x710(%rbp), %xmm1
vmovsd -0x720(%rbp), %xmm2
leaq 0xb62d(%rip), %rdi      # 0x1947a
movb $0x3, %al
callq 0x2050
jmp 0xde56
jmp 0xde72
vmovsd -0x720(%rbp), %xmm0
leaq 0xb65a(%rip), %rdi      # 0x194c1
movb $0x1, %al
callq 0x2050
jmp 0xde70
jmp 0xde72
leaq -0x6e0(%rbp), %rdi
callq 0xe450
leaq -0x678(%rbp), %rdi
callq 0xe490
leaq -0x80(%rbp), %rdi
callq 0x7a40
leaq -0x68(%rbp), %rdi
callq 0x7a40
leaq -0x50(%rbp), %rdi
callq 0x7a40
leaq -0x30(%rbp), %rdi
callq 0xb630
addq $0x820, %rsp            # imm = 0x820
popq %rbp
retq
leaq -0x6e0(%rbp), %rdi
callq 0xe450
leaq -0x678(%rbp), %rdi
callq 0xe490
leaq -0x80(%rbp), %rdi
callq 0x7a40
leaq -0x68(%rbp), %rdi
callq 0x7a40
leaq -0x50(%rbp), %rdi
callq 0x7a40
leaq -0x30(%rbp), %rdi
callq 0xb630
movq -0x88(%rbp), %rdi
callq 0x22e0
nop