// File: /workspace/github_cpp_makefile_star2_O2/luooofan[P]hblzbd_compiler/src/Pass/cond_br_to_insts.cpp
// Function: CondBrToInsts::Run4Func(ArmFunction*)
void CondBrToInsts::Run4Func(ArmFunction* func) {
#ifdef DEBUG_CONDBRTOINSTS_PROCESS
  std::cout << "Run CondBrToInsts In Func: " << func->name_ << std::endl;
  // if (func->name_ != "reduce") return; // debug for single function in single testcase
#endif
  // 实际上也是简化arm的一种 但是simplify arm会给CondBrToInsts带来更多的优化机会 所以建议在simplify arm后跟CondBrToInsts
  // pass
  for (auto bb_it = func->bb_list_.begin(); bb_it != func->bb_list_.end(); ++bb_it) {
    auto bb = *bb_it;
    for (auto it = bb->inst_list_.begin(); it != bb->inst_list_.end();) {
      if (auto src_inst = dynamic_cast<Branch*>(*it)) {
        ArmBasicBlock *next_bb = nullptr, *next_next_bb = nullptr;
        if (bb_it + 1 != func->bb_list_.end()) next_bb = *(bb_it + 1);
        if (bb_it + 2 != func->bb_list_.end()) next_next_bb = *(bb_it + 2);
        // 有以下限制条件:
        // 1. 该指令必须是有条件的跳转指令
        // 2. 该基本块之后至少有两个基本块 并且该跳转指令跳转到之后的第二个基本块
        // 3. 该基本块之后的第一个基本块只能有一个前驱 即该基本块
        // 4. [HYPERPARAMETER] 下一个基本块内最多5条语句
        // 5. 下一个基本块内的指令如果有条件则不能带有跟该指令不同的条件 除最后一条语句外不能有函数调用 即bl(x)语句
        if (src_inst->cond_ != Cond::AL && nullptr != next_bb && nullptr != next_next_bb &&
            src_inst->label_ == next_next_bb->label_ && next_bb->pred_.size() == 1 && next_bb->pred_.front() == bb &&
            next_bb->inst_list_.size() <= kMaxInstNumInBB) {
          bool can_delete = true;
          auto cond = GetOppositeCond(src_inst->cond_);
          for (auto next_it = next_bb->inst_list_.begin(); next_it != next_bb->inst_list_.end(); ++next_it) {
            auto inst = *next_it;
            if (inst->cond_ != Cond::AL && inst->cond_ != cond) {
              can_delete = false;
              break;
            }
            if (next_it + 1 == next_bb->inst_list_.end()) break;
            if (auto src_inst = dynamic_cast<Branch*>(inst)) {
              if (src_inst->has_l_) {
                can_delete = false;
                break;
              }
            }
          }
#ifdef DEBUG_CONDBRTOINSTS_PROCESS
          std::cout << "Check If to Cond BB:" << std::endl;
          next_bb->EmitCode(std::cout);
          std::cout << "  Result: " << can_delete << " " << CondToString(cond) << std::endl;
#endif
          if (can_delete) {
            ++kCount;
            for (auto inst : next_bb->inst_list_) {
              inst->cond_ = cond;
            }
            it = bb->inst_list_.erase(it);  // pop_back
            continue;
          }
        }
        ++it;
      }
      // 其他直接跳过
      else {
        ++it;
      }
    }
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rsi, 0x18(%rsp)
movq 0x38(%rsi), %r12
movq 0x18(%rsp), %rax
cmpq 0x40(%rax), %r12
je 0x307d8
movq (%r12), %r14
leaq 0x30(%r14), %rax
movq %rax, 0x20(%rsp)
movq 0x30(%r14), %r13
leaq 0x8(%r12), %rbx
addq $0x10, %r12
movq %rbx, 0x10(%rsp)
cmpq 0x38(%r14), %r13
je 0x307d0
movq (%r13), %rdi
testq %rdi, %rdi
je 0x306ce
leaq 0x4ef53(%rip), %rsi     # 0x7f5f8
leaq 0x4eea4(%rip), %rdx     # 0x7f550
xorl %ecx, %ecx
callq 0x82c0
testq %rax, %rax
je 0x306ce
movq %rax, %rbp
movq 0x18(%rsp), %rax
movq 0x40(%rax), %rax
cmpq %rax, %rbx
je 0x306d4
movq (%rbx), %rbx
jmp 0x306d6
addq $0x8, %r13
jmp 0x3068b
xorl %ebx, %ebx
cmpq %rax, %r12
je 0x306e1
movq (%r12), %rsi
jmp 0x306e3
xorl %esi, %esi
cmpl $0x0, 0x10(%rbp)
je 0x3078d
testq %rbx, %rbx
je 0x3078d
testq %rsi, %rsi
je 0x3078d
movq %rbp, %rdi
addq $0x18, %rdi
addq $0x8, %rsi
callq 0xe1ca
testb %al, %al
je 0x3078d
movq 0x48(%rbx), %rax
movq 0x50(%rbx), %rcx
subq %rax, %rcx
cmpq $0x8, %rcx
jne 0x3078d
cmpq %r14, (%rax)
jne 0x3078d
movq 0x38(%rbx), %rax
subq 0x30(%rbx), %rax
cmpq $0x20, %rax
ja 0x3078d
movl 0x10(%rbp), %edi
callq 0x8f5c
movl %eax, 0xc(%rsp)
movq 0x30(%rbx), %r15
movq 0x38(%rbx), %rbx
movq %r15, %rbp
cmpq %rbx, %rbp
je 0x3079b
movq (%rbp), %rdi
movl 0x10(%rdi), %eax
testl %eax, %eax
je 0x30764
cmpl 0xc(%rsp), %eax
jne 0x3078d
addq $0x8, %rbp
cmpq %rbx, %rbp
je 0x3079b
leaq 0x4ee84(%rip), %rsi     # 0x7f5f8
leaq 0x4edd5(%rip), %rdx     # 0x7f550
xorl %ecx, %ecx
callq 0x82c0
testq %rax, %rax
je 0x3074e
cmpb $0x0, 0x38(%rax)
je 0x3074e
addq $0x8, %r13
movq 0x10(%rsp), %rbx
jmp 0x3068b
incl 0x50f03(%rip)           # 0x816a4
movl 0xc(%rsp), %ecx
cmpq %rbx, %r15
je 0x307b6
movq (%r15), %rax
movl %ecx, 0x10(%rax)
addq $0x8, %r15
jmp 0x307a5
movq 0x20(%rsp), %rdi
movq %r13, %rsi
callq 0x30460
movq %rax, %r13
movq 0x10(%rsp), %rbx
jmp 0x3068b
movq %rbx, %r12
jmp 0x3065d
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop