// File: /workspace/github_c_makefile_star2_O1/cogbee[P]vmir-latest/src/vmir_transform.c
// Function: exit_ssa_edge
static void
exit_ssa_edge(ir_unit_t *iu, ir_function_t *f, ir_bb_t *bb,
              ir_bb_edge_t *ibe)
{
  phi_lift_node_t *dst, *src;
  phi_lift_egde_t *ple, *ple_next;
  ir_instr_t *ii;
  struct phi_lift_node_list nodes;
  struct phi_lift_edge_list edges;

  LIST_INIT(&nodes);
  LIST_INIT(&edges);
  ir_bb_t *prebb = ibe->ibe_from;
  const int predecessor = prebb->ib_id;

  TAILQ_FOREACH(ii, &bb->ib_instrs, ii_link) {
    if(ii->ii_class != IR_IC_PHI)
      break;

    ir_instr_phi_t *iip = (ir_instr_phi_t *)ii;
    for(int i = 0; i < iip->num_nodes; i++) {
      if(iip->nodes[i].predecessor != predecessor)
        continue;

      if(iip->super.ii_ret.value == iip->nodes[i].value.value)
        continue;

      dst = phi_lift_node_find(&nodes, iip->super.ii_ret.value);
      if(dst == NULL) {
        dst = alloca(sizeof(phi_lift_node_t));
        phi_lift_node_init(&nodes, dst, iip->super.ii_ret);
      }

      src = phi_lift_node_find(&nodes, iip->nodes[i].value.value);
      if(src == NULL) {
        src = alloca(sizeof(phi_lift_node_t));
        phi_lift_node_init(&nodes, src, iip->nodes[i].value);
      }
      if(dst->pln_dst != NULL)
        parser_error(iu, "Multiple PHI entries point to same register");

      ple = alloca(sizeof(phi_lift_egde_t));
      ple->ple_src = src;
      ple->ple_dst = dst;
      LIST_INSERT_HEAD(&src->pln_src, ple, ple_src_link);
      dst->pln_dst = ple;
      LIST_INSERT_HEAD(&edges,        ple, ple_link);
    }
  }

  if(LIST_FIRST(&edges) == NULL)
    return;

  // First moves where destination is not also a source
  ir_instr_t *last = TAILQ_LAST(&prebb->ib_instrs, ir_instr_queue);


  while(1) {
    int progress = 0;

    for(ple = LIST_FIRST(&edges); ple != NULL; ple = ple_next) {
      ple_next = LIST_NEXT(ple, ple_link);
      if(LIST_FIRST(&ple->ple_dst->pln_src) != NULL)
        continue;

      insert_move(iu, ple->ple_dst->pln_vt, ple->ple_src->pln_vt, last);

      progress = 1;
      LIST_REMOVE(ple, ple_link);
      LIST_REMOVE(ple, ple_src_link);
      LIST_REMOVE(ple->ple_dst, pln_link);
      if(LIST_FIRST(&ple->ple_src->pln_src) == NULL)
        LIST_REMOVE(ple->ple_src, pln_link);
    }

    if(LIST_FIRST(&edges) == NULL)
      return;

    if(!progress)
      break;
  }



  while(1) {
    phi_lift_node_t *start = LIST_FIRST(&nodes);
    if(start == NULL)
      break;
    // Add a move to temporary register to resolve cycle

    ir_valuetype_t tmpreg = value_alloc_temporary(iu, start->pln_vt.type);
    insert_move(iu, tmpreg, start->pln_vt, last);

    phi_lift_node_t *cur = start;
    while(1) {
      phi_lift_node_t *src = cur->pln_dst->ple_src;
      if(src == start)
        break;

      insert_move(iu, cur->pln_vt, src->pln_vt, last);
      LIST_REMOVE(cur, pln_link);
      cur = src;
    }

    insert_move(iu, cur->pln_vt, tmpreg, last);
    LIST_REMOVE(cur, pln_link);
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
xorl %eax, %eax
movq %rax, -0x40(%rbp)
movq %rax, -0x30(%rbp)
movq 0x30(%rdx), %rax
movq %rax, -0x38(%rbp)
movq 0x10(%rsi), %rcx
testq %rcx, %rcx
je 0x174fb
movq -0x38(%rbp), %rax
movl 0x28(%rax), %edx
leaq -0x30(%rbp), %rax
movq (%rax), %r15
leaq -0x40(%rbp), %rax
movq (%rax), %r8
xorps %xmm0, %xmm0
cmpl $0x9, 0x28(%rcx)
jne 0x174fb
cmpl $0x0, 0x58(%rcx)
jle 0x174ef
leaq 0x5c(%rcx), %r9
xorl %r10d, %r10d
movq %r8, %r14
movq %r15, %r11
leaq (%r10,%r10,2), %rsi
cmpl %edx, (%r9,%rsi,4)
jne 0x174df
leaq (%r9,%rsi,4), %r13
movl 0x2c(%rcx), %edi
cmpl 0x4(%r13), %edi
je 0x174df
movq %rax, %r12
movq (%r12), %r12
testq %r12, %r12
je 0x173f7
cmpl %edi, 0x20(%r12)
jne 0x173e5
jmp 0x173fa
xorl %r12d, %r12d
testq %r12, %r12
jne 0x17431
movq %rsp, %rsi
leaq -0x30(%rsi), %r8
movq %r8, %rsp
movq 0x2c(%rcx), %rdi
movq %rdi, -0x10(%rsi)
movq %r14, -0x30(%rsi)
testq %r14, %r14
je 0x1741e
movq %r8, 0x8(%r14)
movq %r8, -0x40(%rbp)
movq %rax, 0x8(%r8)
movaps %xmm0, 0x10(%r8)
movq %r8, %r14
movq %r8, %r12
movl 0x4(%r13), %r15d
movq %rax, %rdi
movq (%rdi), %rdi
testq %rdi, %rdi
je 0x17448
cmpl %r15d, 0x20(%rdi)
jne 0x17438
jmp 0x1744a
xorl %edi, %edi
testq %rdi, %rdi
jne 0x17481
movq %rsp, %rsi
leaq -0x30(%rsi), %r8
movq %r8, %rsp
movq 0x4(%r13), %rdi
movq %rdi, -0x10(%rsi)
movq %r14, -0x30(%rsi)
testq %r14, %r14
je 0x1746e
movq %r8, 0x8(%r14)
movq %r8, -0x40(%rbp)
movq %rax, 0x8(%r8)
movaps %xmm0, 0x10(%r8)
movq %r8, %r14
movq %r8, %rdi
cmpq $0x0, 0x18(%r12)
jne 0x176e0
movq %rsp, %r13
leaq -0x30(%r13), %r15
movq %r15, %rsp
movq %rdi, -0x10(%r13)
movq %r12, -0x8(%r13)
movq 0x10(%rdi), %rsi
movq %rsi, -0x20(%r13)
testq %rsi, %rsi
je 0x174b4
addq $-0x20, %r13
movq %r13, 0x18(%rsi)
addq $0x10, %rdi
movq %r15, (%rdi)
movq %rdi, 0x18(%r15)
movq %r15, 0x18(%r12)
movq %r11, (%r15)
testq %r11, %r11
je 0x174d0
movq %r15, 0x8(%r11)
movq %r15, -0x30(%rbp)
leaq -0x30(%rbp), %rsi
movq %rsi, 0x8(%r15)
movq %r15, %r11
incq %r10
movslq 0x58(%rcx), %rsi
cmpq %rsi, %r10
jl 0x173c3
movq (%rcx), %rcx
testq %rcx, %rcx
jne 0x173a2
cmpq $0x0, -0x30(%rbp)
je 0x176d1
movq -0x38(%rbp), %rax
movq 0x18(%rax), %rax
movq 0x8(%rax), %rax
movq (%rax), %r14
movl $0x1, %r15d
movq -0x30(%rbp), %r12
movl $0x11, %eax
testq %r12, %r12
je 0x175e6
xorl %eax, %eax
movq %r12, %r13
movq (%r12), %r12
movq 0x28(%r13), %rcx
cmpq $0x0, 0x10(%rcx)
jne 0x175ce
movq 0x20(%r13), %rax
movq 0x20(%rcx), %rsi
movq 0x20(%rax), %rdx
movq %rbx, %rdi
movq %r14, %rcx
callq 0x176fd
movq (%r13), %rax
testq %rax, %rax
je 0x1756d
movq 0x8(%r13), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%r13), %rcx
movq %rax, (%rcx)
movq 0x10(%r13), %rax
testq %rax, %rax
je 0x17585
movq 0x18(%r13), %rcx
movq %rcx, 0x18(%rax)
movq 0x18(%r13), %rcx
movq %rax, (%rcx)
movq 0x28(%r13), %rax
movq (%rax), %rcx
testq %rcx, %rcx
je 0x175a0
movq 0x8(%rax), %rdx
movq %rdx, 0x8(%rcx)
movq 0x8(%rax), %rax
movq %rcx, (%rax)
movq 0x20(%r13), %rcx
movl $0x1, %eax
cmpq $0x0, 0x10(%rcx)
jne 0x175ce
movq (%rcx), %rdx
testq %rdx, %rdx
je 0x175c7
movq 0x8(%rcx), %rsi
movq %rsi, 0x8(%rdx)
movq 0x8(%rcx), %rcx
movq %rdx, (%rcx)
testq %r12, %r12
jne 0x1752f
testl %eax, %eax
movl $0x0, %eax
movl $0x11, %ecx
cmovel %ecx, %eax
cmpq $0x0, -0x30(%rbp)
cmovel %r15d, %eax
testl %eax, %eax
je 0x1751b
cmpl $0x11, %eax
jne 0x176d1
movq -0x40(%rbp), %r15
testq %r15, %r15
je 0x176d1
movl 0x24(%r15), %r12d
movq %rbx, %rdi
callq 0xf5a0
movq 0x180(%rbx), %rcx
cltq
movq (%rcx,%rax,8), %rcx
movl $0x4, (%rcx)
movl $0xffffffff, 0x38(%rcx) # imm = 0xFFFFFFFF
movl %r12d, 0x24(%rcx)
shlq $0x20, %r12
movl %eax, %esi
orq %r12, %rsi
movq 0x20(%r15), %rdx
movq %rbx, %rdi
movq %rsi, -0x38(%rbp)
movq %r14, %rcx
callq 0x176fd
movq %r15, %r12
movq 0x18(%r12), %rax
movq 0x20(%rax), %r13
cmpq %r15, %r13
je 0x17695
movq 0x20(%r12), %rsi
movq 0x20(%r13), %rdx
movq %rbx, %rdi
movq %r14, %rcx
callq 0x176fd
movq (%r12), %rax
testq %rax, %rax
je 0x1768a
movq 0x8(%r12), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%r12), %rcx
movq %rax, (%rcx)
movq %r13, %r12
cmpq %r15, %r13
jne 0x17656
movq 0x20(%r12), %rsi
movq %rbx, %rdi
movq -0x38(%rbp), %rdx
movq %r14, %rcx
callq 0x176fd
movq (%r12), %rax
testq %rax, %rax
je 0x176c0
movq 0x8(%r12), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%r12), %rcx
movq %rax, (%rcx)
testq %r15, %r15
jne 0x17600
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xea2d(%rip), %rsi      # 0x26114
leaq 0xee56(%rip), %rcx      # 0x26544
movq %rbx, %rdi
movl $0x3a8, %edx            # imm = 0x3A8
xorl %eax, %eax
callq 0xca73