// File: /workspace/github_c_makefile_star2_O0/cogbee[P]vmir-latest/src/vmir_transform.c
// Function: reg_alloc
static void
reg_alloc(ir_unit_t *iu, const uint32_t *mtx, int temp_values, int ffv,
          ir_function_t *f)
{
  int num_vertices = 0;
  int graph_degree = 0;

  value_info_t *vi = malloc(temp_values * sizeof(value_info_t));

  for(int i = 0; i < temp_values; i++) {
    const ir_value_t *iv = value_get(iu, i + ffv);
    if(iv->iv_class != IR_VC_TEMPORARY || iv->iv_precolored != -1)
      continue;

    int s = value_regframe_slots(iu, iv->iv_type);
    if(s == 2) {
      vi[num_vertices].class = RA_CLASS_REGFRAME_64;
    } else if(s == 1) {
      if(iv->iv_jit)
        vi[num_vertices].class = RA_CLASS_MACHINEREG_32;
      else
        vi[num_vertices].class = RA_CLASS_REGFRAME_32;
    } else {
      abort();
    }
    int score = iv->iv_edges;
    vi[num_vertices].value = i;
    vi[num_vertices].score = score;
    graph_degree = VMIR_MAX(graph_degree, iv->iv_edges);
    num_vertices++;
  }

  qsort(vi, num_vertices, sizeof(value_info_t), value_info_cmp);

  // Color graph and use color to allocate register

  uint32_t *colortab[RA_CLASSES];
  int class_reg_size[RA_CLASSES];
  const int degree_words = (graph_degree + 32) / 32;
  for(int i = 0; i < RA_CLASSES; i++) {
    colortab[i] = malloc(degree_words * sizeof(uint32_t));
  }

  class_reg_size[RA_CLASS_MACHINEREG_32] = 0;
  class_reg_size[RA_CLASS_REGFRAME_32] = 4;
  class_reg_size[RA_CLASS_REGFRAME_64] = 8;

  int *colors = malloc(sizeof(int) * temp_values);
  memset(colors, 0xff, sizeof(int) * temp_values);
  for(int i = 0; i < num_vertices; i++) {
    const int val_index = vi[i].value;
    const int class = vi[i].class;

    memset(colortab[class], 0xff, degree_words * sizeof(uint32_t));

    int x = 0;
    const int vivi = (val_index * val_index + val_index) / 2;

    for(; x < val_index; x++) {
      if(bitchk(mtx, vivi + x)) {
        int c = colors[x];
        if(c >= 0)
          bitclr(colortab[class], c);
      }
    }

    for(; x < temp_values; x++) {
      int xx = (x * x + x) / 2;
      if(bitchk(mtx, val_index + xx)) {
        int c = colors[x];
        if(c >= 0)
          bitclr(colortab[class], c);
      }
    }


    for(int j = 0 ; j < degree_words; j++) {
      int c = __builtin_ffs(colortab[class][j]);
      if(c == 0)
        continue;
      c = c - 1 + j * 32;
      colors[val_index] = c;
      break;
    }
  }

  if(iu->iu_debug_flags_func & VMIR_DBG_DUMP_REGALLOC)
    printf("%s: Reg allocation, %d temporaries",
           f->if_name, temp_values);


#ifdef JIT_MACHINE_REGS
  for(int c = 0; c < RA_CLASS_REGFRAME_32; c++) {

    int regframe_slots = 0;
    int machine_regs_used = 0;
    const int rsize = 4;

    for(int i = 0; i < num_vertices; i++) {
      const int val_index = vi[i].value;
      if(vi[i].class != c)
        continue;
      const int color = colors[val_index];
      ir_value_t *iv = VECTOR_ITEM(&iu->iu_values, val_index + ffv);

      if(color < JIT_MACHINE_REGS) {
        iv->iv_class = IR_VC_MACHINEREG;
        iv->iv_reg = color;
        machine_regs_used = VMIR_MAX(color + 1, machine_regs_used);
      } else {
        // Not enough machine regs, put value in regframe instead
        iv->iv_class = IR_VC_REGFRAME;
        const int rfcol = color - JIT_MACHINE_REGS;
        regframe_slots = VMIR_MAX(regframe_slots, rfcol + 1);
        iv->iv_reg = f->if_regframe_size + rfcol * rsize;
      }
    }
    f->if_regframe_size += regframe_slots * rsize;

    if(iu->iu_debug_flags_func & VMIR_DBG_DUMP_REGALLOC)
      printf(", %d machine regs (%d spilled)",
             machine_regs_used, regframe_slots);
  }
#endif

  for(int c = RA_CLASS_REGFRAME_32; c < RA_CLASSES; c++) {
    const int rsize = class_reg_size[c];
    int regframe_slots = 0;

    f->if_regframe_size = VMIR_ALIGN(f->if_regframe_size, rsize);

    for(int i = 0; i < num_vertices; i++) {
      const int val_index = vi[i].value;
      if(vi[i].class != c)
        continue;
      const int color = colors[val_index];
      ir_value_t *iv = VECTOR_ITEM(&iu->iu_values, val_index + ffv);
      iv->iv_class = IR_VC_REGFRAME;
      iv->iv_reg = f->if_regframe_size + color * rsize;
      regframe_slots = VMIR_MAX(regframe_slots, color + 1);
    }
    f->if_regframe_size += regframe_slots * rsize;

    if(iu->iu_debug_flags_func & VMIR_DBG_DUMP_REGALLOC)
      printf(", %d rf%d", regframe_slots, rsize);
  }

  if(iu->iu_debug_flags_func & VMIR_DBG_DUMP_REGALLOC)
    printf("\n");

  for(int i = 0; i < RA_CLASSES; i++) {
    free(colortab[i]);
  }
  free(colors);
  free(vi);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movl %ecx, -0x18(%rbp)
movq %r8, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
movl $0x0, -0x28(%rbp)
movslq -0x14(%rbp), %rax
imulq $0xc, %rax, %rdi
callq 0x3360
movq %rax, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x2ae39
movq -0x8(%rbp), %rdi
movl -0x34(%rbp), %esi
addl -0x18(%rbp), %esi
callq 0x20ee0
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
cmpl $0x4, (%rax)
jne 0x2ad45
movq -0x40(%rbp), %rax
cmpl $-0x1, 0x38(%rax)
je 0x2ad4a
jmp 0x2ae2b
movq -0x8(%rbp), %rdi
movq -0x40(%rbp), %rax
movl 0x24(%rax), %esi
callq 0x20a10
movl %eax, -0x44(%rbp)
cmpl $0x2, -0x44(%rbp)
jne 0x2ad7b
movq -0x30(%rbp), %rax
movslq -0x24(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movl $0x2, 0x8(%rax)
jmp 0x2adc2
cmpl $0x1, -0x44(%rbp)
jne 0x2adbb
movq -0x40(%rbp), %rax
cmpl $0x0, 0x30(%rax)
je 0x2ada3
movq -0x30(%rbp), %rax
movslq -0x24(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movl $0x0, 0x8(%rax)
jmp 0x2adb9
movq -0x30(%rbp), %rax
movslq -0x24(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movl $0x1, 0x8(%rax)
jmp 0x2adc0
callq 0x3050
jmp 0x2adc2
movq -0x40(%rbp), %rax
movl 0x28(%rax), %eax
movl %eax, -0x48(%rbp)
movl -0x34(%rbp), %ecx
movq -0x30(%rbp), %rax
movslq -0x24(%rbp), %rdx
imulq $0xc, %rdx, %rdx
addq %rdx, %rax
movl %ecx, (%rax)
movl -0x48(%rbp), %ecx
movq -0x30(%rbp), %rax
movslq -0x24(%rbp), %rdx
imulq $0xc, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x4(%rax)
movl -0x28(%rbp), %eax
movq -0x40(%rbp), %rcx
cmpl 0x28(%rcx), %eax
jle 0x2ae0c
movl -0x28(%rbp), %eax
movl %eax, -0xd0(%rbp)
jmp 0x2ae19
movq -0x40(%rbp), %rax
movl 0x28(%rax), %eax
movl %eax, -0xd0(%rbp)
movl -0xd0(%rbp), %eax
movl %eax, -0x28(%rbp)
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x2ad13
movq -0x30(%rbp), %rdi
movslq -0x24(%rbp), %rsi
movl $0xc, %edx
leaq 0x593(%rip), %rcx       # 0x2b3e0
callq 0x30d0
movl -0x28(%rbp), %eax
addl $0x20, %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl %eax, -0x70(%rbp)
movl $0x0, -0x74(%rbp)
cmpl $0x3, -0x74(%rbp)
jge 0x2ae94
movslq -0x70(%rbp), %rdi
shlq $0x2, %rdi
callq 0x3360
movq %rax, %rcx
movslq -0x74(%rbp), %rax
movq %rcx, -0x60(%rbp,%rax,8)
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x2ae6a
movl $0x0, -0x6c(%rbp)
movl $0x4, -0x68(%rbp)
movl $0x8, -0x64(%rbp)
movslq -0x14(%rbp), %rdi
shlq $0x2, %rdi
callq 0x3360
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rdi
movslq -0x14(%rbp), %rdx
shlq $0x2, %rdx
movl $0xff, %esi
callq 0x31f0
movl $0x0, -0x84(%rbp)
movl -0x84(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x2b115
movq -0x30(%rbp), %rax
movslq -0x84(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movl (%rax), %eax
movl %eax, -0x88(%rbp)
movq -0x30(%rbp), %rax
movslq -0x84(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
movl %eax, -0x8c(%rbp)
movslq -0x8c(%rbp), %rax
movq -0x60(%rbp,%rax,8), %rdi
movslq -0x70(%rbp), %rdx
shlq $0x2, %rdx
movl $0xff, %esi
callq 0x31f0
movl $0x0, -0x90(%rbp)
movl -0x88(%rbp), %eax
imull -0x88(%rbp), %eax
addl -0x88(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, -0x94(%rbp)
movl -0x90(%rbp), %eax
cmpl -0x88(%rbp), %eax
jge 0x2afd8
movq -0x10(%rbp), %rdi
movl -0x94(%rbp), %esi
addl -0x90(%rbp), %esi
callq 0x2a480
cmpl $0x0, %eax
je 0x2afc5
movq -0x80(%rbp), %rax
movslq -0x90(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x98(%rbp)
cmpl $0x0, -0x98(%rbp)
jl 0x2afc3
movslq -0x8c(%rbp), %rax
movq -0x60(%rbp,%rax,8), %rdi
movl -0x98(%rbp), %esi
callq 0x2a450
jmp 0x2afc5
jmp 0x2afc7
movl -0x90(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x90(%rbp)
jmp 0x2af67
jmp 0x2afda
movl -0x90(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x2b070
movl -0x90(%rbp), %eax
imull -0x90(%rbp), %eax
addl -0x90(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, -0x9c(%rbp)
movq -0x10(%rbp), %rdi
movl -0x88(%rbp), %esi
addl -0x9c(%rbp), %esi
callq 0x2a480
cmpl $0x0, %eax
je 0x2b05a
movq -0x80(%rbp), %rax
movslq -0x90(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0xa0(%rbp)
cmpl $0x0, -0xa0(%rbp)
jl 0x2b058
movslq -0x8c(%rbp), %rax
movq -0x60(%rbp,%rax,8), %rdi
movl -0xa0(%rbp), %esi
callq 0x2a450
jmp 0x2b05a
jmp 0x2b05c
movl -0x90(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x90(%rbp)
jmp 0x2afda
movl $0x0, -0xa4(%rbp)
movl -0xa4(%rbp), %eax
cmpl -0x70(%rbp), %eax
jge 0x2b0ff
movslq -0x8c(%rbp), %rax
movq -0x60(%rbp,%rax,8), %rax
movslq -0xa4(%rbp), %rcx
movl (%rax,%rcx,4), %edx
tzcntl %edx, %eax
addl $0x1, %eax
xorl %ecx, %ecx
cmpl $0x0, %edx
cmovel %ecx, %eax
movl %eax, -0xa8(%rbp)
cmpl $0x0, -0xa8(%rbp)
jne 0x2b0bb
jmp 0x2b0eb
movl -0xa8(%rbp), %eax
subl $0x1, %eax
movl -0xa4(%rbp), %ecx
shll $0x5, %ecx
addl %ecx, %eax
movl %eax, -0xa8(%rbp)
movl -0xa8(%rbp), %edx
movq -0x80(%rbp), %rax
movslq -0x88(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
jmp 0x2b0ff
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x2b07a
jmp 0x2b101
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
jmp 0x2aeda
movq -0x8(%rbp), %rax
movl 0x104(%rax), %eax
andl $0x10, %eax
cmpl $0x0, %eax
je 0x2b140
movq -0x20(%rbp), %rax
movq 0x20(%rax), %rsi
movl -0x14(%rbp), %edx
leaq 0x14da1(%rip), %rdi     # 0x3feda
movb $0x0, %al
callq 0x3170
movl $0x1, -0xac(%rbp)
cmpl $0x3, -0xac(%rbp)
jge 0x2b2f8
movslq -0xac(%rbp), %rax
movl -0x6c(%rbp,%rax,4), %eax
movl %eax, -0xb0(%rbp)
movl $0x0, -0xb4(%rbp)
movq -0x20(%rbp), %rax
movl 0x2c(%rax), %ecx
addl -0xb0(%rbp), %ecx
subl $0x1, %ecx
movl -0xb0(%rbp), %eax
subl $0x1, %eax
xorl $-0x1, %eax
andl %eax, %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x2c(%rax)
movl $0x0, -0xb8(%rbp)
movl -0xb8(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x2b29f
movq -0x30(%rbp), %rax
movslq -0xb8(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movl (%rax), %eax
movl %eax, -0xbc(%rbp)
movq -0x30(%rbp), %rax
movslq -0xb8(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
cmpl -0xac(%rbp), %eax
je 0x2b1ec
jmp 0x2b28b
movq -0x80(%rbp), %rax
movslq -0xbc(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0xc0(%rbp)
movq -0x8(%rbp), %rax
movq 0x180(%rax), %rax
movl -0xbc(%rbp), %ecx
addl -0x18(%rbp), %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
movl $0x5, (%rax)
movq -0x20(%rbp), %rax
movl 0x2c(%rax), %ecx
movl -0xc0(%rbp), %eax
imull -0xb0(%rbp), %eax
addl %eax, %ecx
movq -0xc8(%rbp), %rax
movl %ecx, 0x30(%rax)
movl -0xb4(%rbp), %eax
movl -0xc0(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jle 0x2b270
movl -0xb4(%rbp), %eax
movl %eax, -0xd4(%rbp)
jmp 0x2b27f
movl -0xc0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd4(%rbp)
movl -0xd4(%rbp), %eax
movl %eax, -0xb4(%rbp)
movl -0xb8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb8(%rbp)
jmp 0x2b1a1
movl -0xb4(%rbp), %ecx
imull -0xb0(%rbp), %ecx
movq -0x20(%rbp), %rax
addl 0x2c(%rax), %ecx
movl %ecx, 0x2c(%rax)
movq -0x8(%rbp), %rax
movl 0x104(%rax), %eax
andl $0x10, %eax
cmpl $0x0, %eax
je 0x2b2e2
movl -0xb4(%rbp), %esi
movl -0xb0(%rbp), %edx
leaq 0x14c22(%rip), %rdi     # 0x3fefd
movb $0x0, %al
callq 0x3170
jmp 0x2b2e4
movl -0xac(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xac(%rbp)
jmp 0x2b14a
movq -0x8(%rbp), %rax
movl 0x104(%rax), %eax
andl $0x10, %eax
cmpl $0x0, %eax
je 0x2b318
leaq 0x166e0(%rip), %rdi     # 0x419f1
movb $0x0, %al
callq 0x3170
movl $0x0, -0xcc(%rbp)
cmpl $0x3, -0xcc(%rbp)
jge 0x2b34d
movslq -0xcc(%rbp), %rax
movq -0x60(%rbp,%rax,8), %rdi
callq 0x3030
movl -0xcc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xcc(%rbp)
jmp 0x2b322
movq -0x80(%rbp), %rdi
callq 0x3030
movq -0x30(%rbp), %rdi
callq 0x3030
addq $0xe0, %rsp
popq %rbp
retq
nopl (%rax,%rax)