// File: 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:
subq $0x118, %rsp            # imm = 0x118
movq %rdi, 0x110(%rsp)
movq %rsi, 0x108(%rsp)
movq 0x108(%rsp), %rdi
addq $0x38, %rdi
callq 0x10bd0
movq %rax, 0x100(%rsp)
movq 0x108(%rsp), %rdi
addq $0x38, %rdi
callq 0x10c00
movq %rax, 0xf8(%rsp)
leaq 0x100(%rsp), %rdi
leaq 0xf8(%rsp), %rsi
callq 0x10c30
testb $0x1, %al
jne 0x81677
jmp 0x81b82
leaq 0x100(%rsp), %rdi
callq 0x10c70
movq (%rax), %rax
movq %rax, 0xf0(%rsp)
movq 0xf0(%rsp), %rdi
addq $0x30, %rdi
callq 0xcaa0
movq %rax, 0xe8(%rsp)
movq 0xf0(%rsp), %rdi
addq $0x30, %rdi
callq 0xcad0
movq %rax, 0xe0(%rsp)
leaq 0xe8(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0xcb00
testb $0x1, %al
jne 0x816df
jmp 0x81b6e
leaq 0xe8(%rsp), %rdi
callq 0xf5c0
movq (%rax), %rax
movq %rax, 0x28(%rsp)
cmpq $0x0, %rax
je 0x8171d
movq 0x28(%rsp), %rdi
leaq 0xc8e82(%rip), %rsi     # 0x14a588
leaq 0xc8dd3(%rip), %rdx     # 0x14a4e0
xorl %eax, %eax
movl %eax, %ecx
callq 0x8410
movq %rax, 0x20(%rsp)
jmp 0x81726
xorl %eax, %eax
movq %rax, 0x20(%rsp)
jmp 0x81726
movq 0x20(%rsp), %rax
movq %rax, 0xd8(%rsp)
cmpq $0x0, 0xd8(%rsp)
je 0x81b5c
movq $0x0, 0xd0(%rsp)
movq $0x0, 0xc8(%rsp)
leaq 0x100(%rsp), %rdi
movl $0x1, %esi
callq 0x81b90
movq %rax, 0xc0(%rsp)
movq 0x108(%rsp), %rdi
addq $0x38, %rdi
callq 0x10c00
movq %rax, 0xb8(%rsp)
leaq 0xc0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x10c30
testb $0x1, %al
jne 0x817a8
jmp 0x817da
leaq 0x100(%rsp), %rdi
movl $0x1, %esi
callq 0x81b90
movq %rax, 0xb0(%rsp)
leaq 0xb0(%rsp), %rdi
callq 0x10c70
movq (%rax), %rax
movq %rax, 0xd0(%rsp)
leaq 0x100(%rsp), %rdi
movl $0x2, %esi
callq 0x81b90
movq %rax, 0xa8(%rsp)
movq 0x108(%rsp), %rdi
addq $0x38, %rdi
callq 0x10c00
movq %rax, 0xa0(%rsp)
leaq 0xa8(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x10c30
testb $0x1, %al
jne 0x81828
jmp 0x8185a
leaq 0x100(%rsp), %rdi
movl $0x2, %esi
callq 0x81b90
movq %rax, 0x98(%rsp)
leaq 0x98(%rsp), %rdi
callq 0x10c70
movq (%rax), %rax
movq %rax, 0xc8(%rsp)
movq 0xd8(%rsp), %rax
cmpl $0x0, 0x10(%rax)
je 0x81b4d
xorl %eax, %eax
cmpq 0xd0(%rsp), %rax
je 0x81b4d
xorl %eax, %eax
cmpq 0xc8(%rsp), %rax
je 0x81b4d
movq 0xd8(%rsp), %rdi
addq $0x18, %rdi
movq 0xc8(%rsp), %rsi
addq $0x8, %rsi
callq 0x1a650
testb $0x1, %al
jne 0x818b2
jmp 0x81b4d
movq 0xd0(%rsp), %rdi
addq $0x48, %rdi
callq 0x81bd0
cmpq $0x1, %rax
jne 0x81b4d
movq 0xd0(%rsp), %rdi
addq $0x48, %rdi
callq 0x81bf0
movq (%rax), %rax
cmpq 0xf0(%rsp), %rax
jne 0x81b4d
movq 0xd0(%rsp), %rdi
addq $0x30, %rdi
callq 0xf220
cmpq $0x4, %rax
ja 0x81b4d
movb $0x1, 0x97(%rsp)
movq 0xd8(%rsp), %rax
movl 0x10(%rax), %edi
callq 0x99d0
movl %eax, 0x90(%rsp)
movq 0xd0(%rsp), %rdi
addq $0x30, %rdi
callq 0xcaa0
movq %rax, 0x88(%rsp)
movq 0xd0(%rsp), %rdi
addq $0x30, %rdi
callq 0xcad0
movq %rax, 0x80(%rsp)
leaq 0x88(%rsp), %rdi
leaq 0x80(%rsp), %rsi
callq 0xcb00
testb $0x1, %al
jne 0x81979
jmp 0x81a74
leaq 0x88(%rsp), %rdi
callq 0xf5c0
movq (%rax), %rax
movq %rax, 0x78(%rsp)
movq 0x78(%rsp), %rax
cmpl $0x0, 0x10(%rax)
je 0x819b7
movq 0x78(%rsp), %rax
movl 0x10(%rax), %eax
cmpl 0x90(%rsp), %eax
je 0x819b7
movb $0x0, 0x97(%rsp)
jmp 0x81a74
leaq 0x88(%rsp), %rdi
movl $0x1, %esi
callq 0xfbd0
movq %rax, 0x70(%rsp)
movq 0xd0(%rsp), %rdi
addq $0x30, %rdi
callq 0xcad0
movq %rax, 0x68(%rsp)
leaq 0x70(%rsp), %rdi
leaq 0x68(%rsp), %rsi
callq 0x70970
testb $0x1, %al
jne 0x819f9
jmp 0x819fb
jmp 0x81a74
movq 0x78(%rsp), %rax
movq %rax, 0x18(%rsp)
cmpq $0x0, %rax
je 0x81a2e
movq 0x18(%rsp), %rdi
leaq 0xc8b71(%rip), %rsi     # 0x14a588
leaq 0xc8ac2(%rip), %rdx     # 0x14a4e0
xorl %eax, %eax
movl %eax, %ecx
callq 0x8410
movq %rax, 0x10(%rsp)
jmp 0x81a37
xorl %eax, %eax
movq %rax, 0x10(%rsp)
jmp 0x81a37
movq 0x10(%rsp), %rax
movq %rax, 0x60(%rsp)
cmpq $0x0, 0x60(%rsp)
je 0x81a60
movq 0x60(%rsp), %rax
testb $0x1, 0x38(%rax)
je 0x81a5e
movb $0x0, 0x97(%rsp)
jmp 0x81a74
jmp 0x81a60
jmp 0x81a62
leaq 0x88(%rsp), %rdi
callq 0xf8f0
jmp 0x81942
testb $0x1, 0x97(%rsp)
je 0x81b4b
movl 0xcacfc(%rip), %eax     # 0x14c784
addl $0x1, %eax
movl %eax, 0xcacf3(%rip)     # 0x14c784
movq 0xd0(%rsp), %rax
addq $0x30, %rax
movq %rax, 0x58(%rsp)
movq 0x58(%rsp), %rdi
callq 0xcaa0
movq %rax, 0x50(%rsp)
movq 0x58(%rsp), %rdi
callq 0xcad0
movq %rax, 0x48(%rsp)
leaq 0x50(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0xcb00
testb $0x1, %al
jne 0x81ad5
jmp 0x81b02
leaq 0x50(%rsp), %rdi
callq 0xf5c0
movq (%rax), %rax
movq %rax, 0x40(%rsp)
movl 0x90(%rsp), %ecx
movq 0x40(%rsp), %rax
movl %ecx, 0x10(%rax)
leaq 0x50(%rsp), %rdi
callq 0xf8f0
jmp 0x81ac0
movq 0xf0(%rsp), %rax
addq $0x30, %rax
movq %rax, 0x8(%rsp)
leaq 0x30(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0xcb80
movq 0x8(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x80b80
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rax
movq %rax, 0xe8(%rsp)
jmp 0x816a8
jmp 0x81b4d
leaq 0xe8(%rsp), %rdi
callq 0xf8f0
jmp 0x81b69
leaq 0xe8(%rsp), %rdi
callq 0xf8f0
jmp 0x816a8
jmp 0x81b70
leaq 0x100(%rsp), %rdi
callq 0x10c80
jmp 0x81640
addq $0x118, %rsp            # imm = 0x118
retq
nopw (%rax,%rax)