// File: /workspace/github_cpp_makefile_star2_O1/sid1607[P]avx2-merge-sort/merge_sort.cpp
// Function: merge_phase(int*, int*, int, int, int)
void merge_phase(int *a, int *out, int start, int mid, int end) {
  int i=start, j=mid+1, k=start;
  int i_end = i + mid - start + 1;
  int j_end = j + end - mid;

  auto ra = load_reg256(&a[i]);
  auto rb = load_reg256(&a[j]);

  i += SIMD_SIZE;
  j += SIMD_SIZE;

  // 8-by-8 merge
  if (mid-start+1 == SIMD_SIZE) {
    bitonic_merge(ra, rb);
    // save the smaller half
    store_reg256(&out[k], ra);
    k += SIMD_SIZE;
    // then save the larger half
    store_reg256(&out[k], rb);
    k += SIMD_SIZE;
    return;
  }

  do {
    bitonic_merge(ra, rb);
    
    // save the smaller half
    store_reg256(&out[k], ra);
    k += SIMD_SIZE;
    
    // use the larger half for the next comparison
    ra = rb;

    // select the input with the lowest value at the current pointer
    if (a[i] < a[j]) {
      rb = load_reg256(&a[i]);
      i += SIMD_SIZE;
    } else {
      rb = load_reg256(&a[j]);
      j += SIMD_SIZE;
    }
  } while (i < i_end && j < j_end);

  // merge the final pair of registers from each input
  bitonic_merge(ra, rb);
  store_reg256(&out[k], ra);
  k += SIMD_SIZE;
  ra = rb;

  // consume remaining data from a, if left
  while (i < i_end) {
    rb = load_reg256(&a[i]);
    i += SIMD_SIZE;
    bitonic_merge(ra, rb);
    store_reg256(&out[k], ra);
    k += SIMD_SIZE;
    ra = rb;
  }

  // consume remaining data from b, if left
  while (j < j_end) {
    rb = load_reg256(&a[j]);
    j += SIMD_SIZE;
    bitonic_merge(ra, rb);
    store_reg256(&out[k], ra);
    k += SIMD_SIZE;
    ra = rb;
  }

  // store the final batch
  store_reg256(&out[k], ra);
  k += SIMD_SIZE;
}

// Assembly:
movslq %edx, %r10
vmovdqa (%rdi,%r10,4), %ymm0
movslq %ecx, %rdx
vmovdqa 0x4(%rdi,%rdx,4), %ymm1
movl %edx, %r9d
subl %r10d, %r9d
leal 0x8(%r10), %eax
cmpl $0x7, %r9d
jne 0x245b
vmovdqa 0x3dc1(%rip), %ymm2     # 0x6180
vpermd %ymm1, %ymm2, %ymm1
vpminsd %ymm1, %ymm0, %ymm2
vpmaxsd %ymm1, %ymm0, %ymm0
vmovdqa 0x3dca(%rip), %ymm1     # 0x61a0
vpermd %ymm2, %ymm1, %ymm3
vpermd %ymm0, %ymm1, %ymm1
vpminsd %ymm3, %ymm2, %ymm4
vpmaxsd %ymm3, %ymm2, %ymm2
vpblendd $0xf0, %ymm2, %ymm4, %ymm2 # ymm2 = ymm4[0,1,2,3],ymm2[4,5,6,7]
vpminsd %ymm1, %ymm0, %ymm3
vpmaxsd %ymm1, %ymm0, %ymm0
vpblendd $0xf0, %ymm0, %ymm3, %ymm0 # ymm0 = ymm3[0,1,2,3],ymm0[4,5,6,7]
vpshufd $0x4e, %ymm2, %ymm1     # ymm1 = ymm2[2,3,0,1,6,7,4,5]
vpshufd $0x4e, %ymm0, %ymm3     # ymm3 = ymm0[2,3,0,1,6,7,4,5]
vpminsd %ymm1, %ymm2, %ymm4
vpmaxsd %ymm1, %ymm2, %ymm1
vpunpcklqdq %ymm1, %ymm4, %ymm1 # ymm1 = ymm4[0],ymm1[0],ymm4[2],ymm1[2]
vpminsd %ymm3, %ymm0, %ymm2
vpmaxsd %ymm3, %ymm0, %ymm0
vpunpcklqdq %ymm0, %ymm2, %ymm0 # ymm0 = ymm2[0],ymm0[0],ymm2[2],ymm0[2]
vpshufd $0xb1, %ymm1, %ymm2     # ymm2 = ymm1[1,0,3,2,5,4,7,6]
vpshufd $0xb1, %ymm0, %ymm3     # ymm3 = ymm0[1,0,3,2,5,4,7,6]
vpminsd %ymm2, %ymm1, %ymm4
vpmaxsd %ymm2, %ymm1, %ymm1
vpblendd $0xaa, %ymm1, %ymm4, %ymm1 # ymm1 = ymm4[0],ymm1[1],ymm4[2],ymm1[3],ymm4[4],ymm1[5],ymm4[6],ymm1[7]
vpminsd %ymm3, %ymm0, %ymm2
vpmaxsd %ymm3, %ymm0, %ymm0
vpblendd $0xaa, %ymm0, %ymm2, %ymm0 # ymm0 = ymm2[0],ymm0[1],ymm2[2],ymm0[3],ymm2[4],ymm0[5],ymm2[6],ymm0[7]
vmovdqa %ymm1, (%rsi,%r10,4)
jmp 0x2797
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
incl %r8d
leal 0x9(%rcx), %r9d
leaq (%rsi,%r10,4), %rbx
shlq $0x20, %r10
movabsq $0x800000000, %r14      # imm = 0x800000000
movl %eax, %r11d
vmovdqa 0x3cf9(%rip), %ymm2     # 0x6180
vpermd %ymm1, %ymm2, %ymm1
vpminsd %ymm1, %ymm0, %ymm2
vpmaxsd %ymm1, %ymm0, %ymm0
vmovdqa 0x3d02(%rip), %ymm1     # 0x61a0
vpermd %ymm2, %ymm1, %ymm3
vpermd %ymm0, %ymm1, %ymm1
vpminsd %ymm3, %ymm2, %ymm4
vpmaxsd %ymm3, %ymm2, %ymm2
vpblendd $0xf0, %ymm2, %ymm4, %ymm2 # ymm2 = ymm4[0,1,2,3],ymm2[4,5,6,7]
vpminsd %ymm1, %ymm0, %ymm3
vpmaxsd %ymm1, %ymm0, %ymm0
vpblendd $0xf0, %ymm0, %ymm3, %ymm0 # ymm0 = ymm3[0,1,2,3],ymm0[4,5,6,7]
vpshufd $0x4e, %ymm2, %ymm1     # ymm1 = ymm2[2,3,0,1,6,7,4,5]
vpshufd $0x4e, %ymm0, %ymm3     # ymm3 = ymm0[2,3,0,1,6,7,4,5]
vpminsd %ymm1, %ymm2, %ymm4
vpmaxsd %ymm1, %ymm2, %ymm1
vpunpcklqdq %ymm1, %ymm4, %ymm1 # ymm1 = ymm4[0],ymm1[0],ymm4[2],ymm1[2]
vpminsd %ymm3, %ymm0, %ymm2
vpmaxsd %ymm3, %ymm0, %ymm0
vpunpcklqdq %ymm0, %ymm2, %ymm0 # ymm0 = ymm2[0],ymm0[0],ymm2[2],ymm0[2]
vpshufd $0xb1, %ymm1, %ymm2     # ymm2 = ymm1[1,0,3,2,5,4,7,6]
vpshufd $0xb1, %ymm0, %ymm3     # ymm3 = ymm0[1,0,3,2,5,4,7,6]
vpminsd %ymm2, %ymm1, %ymm4
vpmaxsd %ymm2, %ymm1, %ymm1
vpblendd $0xaa, %ymm1, %ymm4, %ymm1 # ymm1 = ymm4[0],ymm1[1],ymm4[2],ymm1[3],ymm4[4],ymm1[5],ymm4[6],ymm1[7]
vpminsd %ymm3, %ymm0, %ymm2
vpmaxsd %ymm3, %ymm0, %ymm0
vpblendd $0xaa, %ymm0, %ymm2, %ymm0 # ymm0 = ymm2[0],ymm0[1],ymm2[2],ymm0[3],ymm2[4],ymm0[5],ymm2[6],ymm0[7]
vmovdqa %ymm1, (%rbx)
movslq %r11d, %r15
movl (%rdi,%r15,4), %ebp
movslq %r9d, %r12
leal 0x8(%r15), %r11d
cmpl (%rdi,%r12,4), %ebp
leal 0x8(%r12), %r9d
cmovll %r12d, %r9d
cmovlq %r15, %r12
cmovgel %r15d, %r11d
vmovdqa (%rdi,%r12,4), %ymm1
addl $0x8, %eax
addq %r14, %r10
cmpl %ecx, %r11d
jg 0x255d
addq $0x20, %rbx
cmpl %r8d, %r9d
jl 0x247f
vmovdqa 0x3c1b(%rip), %ymm2     # 0x6180
vpermd %ymm1, %ymm2, %ymm1
vpminsd %ymm1, %ymm0, %ymm2
vpmaxsd %ymm1, %ymm0, %ymm0
vmovdqa 0x3c24(%rip), %ymm1     # 0x61a0
vpermd %ymm2, %ymm1, %ymm3
vpermd %ymm0, %ymm1, %ymm1
vpminsd %ymm3, %ymm2, %ymm4
vpmaxsd %ymm3, %ymm2, %ymm2
vpblendd $0xf0, %ymm2, %ymm4, %ymm2 # ymm2 = ymm4[0,1,2,3],ymm2[4,5,6,7]
vpminsd %ymm1, %ymm0, %ymm3
vpmaxsd %ymm1, %ymm0, %ymm0
vpblendd $0xf0, %ymm0, %ymm3, %ymm0 # ymm0 = ymm3[0,1,2,3],ymm0[4,5,6,7]
vpshufd $0x4e, %ymm2, %ymm1     # ymm1 = ymm2[2,3,0,1,6,7,4,5]
vpshufd $0x4e, %ymm0, %ymm3     # ymm3 = ymm0[2,3,0,1,6,7,4,5]
vpminsd %ymm1, %ymm2, %ymm4
vpmaxsd %ymm1, %ymm2, %ymm1
vpunpcklqdq %ymm1, %ymm4, %ymm1 # ymm1 = ymm4[0],ymm1[0],ymm4[2],ymm1[2]
vpminsd %ymm3, %ymm0, %ymm2
vpmaxsd %ymm3, %ymm0, %ymm0
vpunpcklqdq %ymm0, %ymm2, %ymm0 # ymm0 = ymm2[0],ymm0[0],ymm2[2],ymm0[2]
vpshufd $0xb1, %ymm1, %ymm2     # ymm2 = ymm1[1,0,3,2,5,4,7,6]
vpshufd $0xb1, %ymm0, %ymm3     # ymm3 = ymm0[1,0,3,2,5,4,7,6]
vpminsd %ymm2, %ymm1, %ymm4
vpmaxsd %ymm2, %ymm1, %ymm1
vpblendd $0xaa, %ymm1, %ymm4, %ymm1 # ymm1 = ymm4[0],ymm1[1],ymm4[2],ymm1[3],ymm4[4],ymm1[5],ymm4[6],ymm1[7]
vpminsd %ymm3, %ymm0, %ymm2
vpmaxsd %ymm3, %ymm0, %ymm0
vpblendd $0xaa, %ymm0, %ymm2, %ymm0 # ymm0 = ymm2[0],ymm0[1],ymm2[2],ymm0[3],ymm2[4],ymm0[5],ymm2[6],ymm0[7]
sarq $0x1e, %r10
vmovdqa %ymm1, (%rsi,%r10)
cmpl %ecx, %r11d
jg 0x26c6
movslq %r11d, %rcx
movslq %eax, %r10
leaq (%rsi,%r10,4), %r10
vmovdqa 0x3b65(%rip), %ymm1     # 0x6180
vpermd (%rdi,%rcx,4), %ymm1, %ymm1
addq $0x8, %rcx
vpminsd %ymm1, %ymm0, %ymm2
vpmaxsd %ymm1, %ymm0, %ymm0
vmovdqa 0x3b69(%rip), %ymm1     # 0x61a0
vpermd %ymm2, %ymm1, %ymm3
vpermd %ymm0, %ymm1, %ymm1
vpminsd %ymm3, %ymm2, %ymm4
vpmaxsd %ymm3, %ymm2, %ymm2
vpblendd $0xf0, %ymm2, %ymm4, %ymm2 # ymm2 = ymm4[0,1,2,3],ymm2[4,5,6,7]
vpminsd %ymm1, %ymm0, %ymm3
vpmaxsd %ymm1, %ymm0, %ymm0
vpblendd $0xf0, %ymm0, %ymm3, %ymm0 # ymm0 = ymm3[0,1,2,3],ymm0[4,5,6,7]
vpshufd $0x4e, %ymm2, %ymm1     # ymm1 = ymm2[2,3,0,1,6,7,4,5]
vpshufd $0x4e, %ymm0, %ymm3     # ymm3 = ymm0[2,3,0,1,6,7,4,5]
vpminsd %ymm1, %ymm2, %ymm4
vpmaxsd %ymm1, %ymm2, %ymm1
vpunpcklqdq %ymm1, %ymm4, %ymm1 # ymm1 = ymm4[0],ymm1[0],ymm4[2],ymm1[2]
vpminsd %ymm3, %ymm0, %ymm2
vpmaxsd %ymm3, %ymm0, %ymm0
vpunpcklqdq %ymm0, %ymm2, %ymm0 # ymm0 = ymm2[0],ymm0[0],ymm2[2],ymm0[2]
vpshufd $0xb1, %ymm1, %ymm2     # ymm2 = ymm1[1,0,3,2,5,4,7,6]
vpshufd $0xb1, %ymm0, %ymm3     # ymm3 = ymm0[1,0,3,2,5,4,7,6]
vpminsd %ymm2, %ymm1, %ymm4
vpmaxsd %ymm2, %ymm1, %ymm1
vpblendd $0xaa, %ymm1, %ymm4, %ymm1 # ymm1 = ymm4[0],ymm1[1],ymm4[2],ymm1[3],ymm4[4],ymm1[5],ymm4[6],ymm1[7]
vpminsd %ymm3, %ymm0, %ymm2
vpmaxsd %ymm3, %ymm0, %ymm0
vpblendd $0xaa, %ymm0, %ymm2, %ymm0 # ymm0 = ymm2[0],ymm0[1],ymm2[2],ymm0[3],ymm2[4],ymm0[5],ymm2[6],ymm0[7]
vmovdqa %ymm1, (%r10)
addq $0x20, %r10
addl $0x8, %eax
cmpq %rdx, %rcx
jle 0x2613
cmpl %r8d, %r9d
jge 0x278f
movslq %r9d, %rcx
movslq %r8d, %rdx
movslq %eax, %r8
leaq (%rsi,%r8,4), %r8
vmovdqa 0x3a9c(%rip), %ymm1     # 0x6180
vpermd (%rdi,%rcx,4), %ymm1, %ymm1
addq $0x8, %rcx
vpminsd %ymm1, %ymm0, %ymm2
vpmaxsd %ymm1, %ymm0, %ymm0
vmovdqa 0x3aa0(%rip), %ymm1     # 0x61a0
vpermd %ymm2, %ymm1, %ymm3
vpermd %ymm0, %ymm1, %ymm1
vpminsd %ymm3, %ymm2, %ymm4
vpmaxsd %ymm3, %ymm2, %ymm2
vpblendd $0xf0, %ymm2, %ymm4, %ymm2 # ymm2 = ymm4[0,1,2,3],ymm2[4,5,6,7]
vpminsd %ymm1, %ymm0, %ymm3
vpmaxsd %ymm1, %ymm0, %ymm0
vpblendd $0xf0, %ymm0, %ymm3, %ymm0 # ymm0 = ymm3[0,1,2,3],ymm0[4,5,6,7]
vpshufd $0x4e, %ymm2, %ymm1     # ymm1 = ymm2[2,3,0,1,6,7,4,5]
vpshufd $0x4e, %ymm0, %ymm3     # ymm3 = ymm0[2,3,0,1,6,7,4,5]
vpminsd %ymm1, %ymm2, %ymm4
vpmaxsd %ymm1, %ymm2, %ymm1
vpunpcklqdq %ymm1, %ymm4, %ymm1 # ymm1 = ymm4[0],ymm1[0],ymm4[2],ymm1[2]
vpminsd %ymm3, %ymm0, %ymm2
vpmaxsd %ymm3, %ymm0, %ymm0
vpunpcklqdq %ymm0, %ymm2, %ymm0 # ymm0 = ymm2[0],ymm0[0],ymm2[2],ymm0[2]
vpshufd $0xb1, %ymm1, %ymm2     # ymm2 = ymm1[1,0,3,2,5,4,7,6]
vpshufd $0xb1, %ymm0, %ymm3     # ymm3 = ymm0[1,0,3,2,5,4,7,6]
vpminsd %ymm2, %ymm1, %ymm4
vpmaxsd %ymm2, %ymm1, %ymm1
vpblendd $0xaa, %ymm1, %ymm4, %ymm1 # ymm1 = ymm4[0],ymm1[1],ymm4[2],ymm1[3],ymm4[4],ymm1[5],ymm4[6],ymm1[7]
vpminsd %ymm3, %ymm0, %ymm2
vpmaxsd %ymm3, %ymm0, %ymm0
vpblendd $0xaa, %ymm0, %ymm2, %ymm0 # ymm0 = ymm2[0],ymm0[1],ymm2[2],ymm0[3],ymm2[4],ymm0[5],ymm2[6],ymm0[7]
vmovdqa %ymm1, (%r8)
addq $0x20, %r8
addl $0x8, %eax
cmpq %rdx, %rcx
jl 0x26dc
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
cltq
vmovdqa %ymm0, (%rsi,%rax,4)
vzeroupper
retq