// File: /workspace/github_cpp_makefile_star2_O2/luooofan[P]hblzbd_compiler/src/Pass/global_value_numbering.cpp
// Function: GlobalValueNumbering::CommenExpressionEliminate(SSABasicBlock*)
void GlobalValueNumbering::CommenExpressionEliminate(SSABasicBlock* bb) {
#ifdef DEBUG_GVN_PROCESS
  std::cout << "  BB: " << bb->GetLabel() << std::endl;
#endif

  int src_vec_size = exp_val_vec.size();

  // compute exp and perform eliminate
  for (auto it = bb->GetInstList().begin(); it != bb->GetInstList().end();) {
    auto inst = *it;
    Expression exp(inst);

    auto find_if_cmp = [&exp](std::pair<Expression, Value*>& kv) {
      if (exp.op_ == kv.first.op_) {
        // 满足交换律的加和乘操作 假设最多只有一个操作数是常数 把常数操作数放后面(之前执行SimpleOptimizePass即满足假设)
        if (exp.op_ == Expression::ADD || exp.op_ == Expression::MUL) {
          if (nullptr != dynamic_cast<ConstantInt*>(exp.operands_[0])) {
            auto temp = exp.operands_[1];
            exp.operands_[1] = exp.operands_[0];
            exp.operands_[0] = temp;
          }
          if (nullptr != dynamic_cast<ConstantInt*>(kv.first.operands_[0])) {
            auto temp = kv.first.operands_[1];
            kv.first.operands_[1] = kv.first.operands_[0];
            kv.first.operands_[0] = temp;
          }
        }
        // 比较每个操作数是否一致 对于常数来说比较的是立即数值 对于其他value来说比较的是指针
        for (int i = 0; i < exp.operands_.size(); ++i) {
          if (auto constint = dynamic_cast<ConstantInt*>(exp.operands_[i])) {
            if (auto constint2 = dynamic_cast<ConstantInt*>(kv.first.operands_[i])) {
              if (constint->GetImm() == constint2->GetImm()) continue;
            } else {
              return false;
            }
          }
          if (exp.operands_[i] != kv.first.operands_[i]) return false;
        }
        return true;
      } else {
        return false;
      }
    };
    auto replace = [&bb, &it](Value* src, Value* target) {
      ++kCount;
#ifdef DEBUG_GVN_PROCESS
      std::cout << "  find redundant: ";
      src->Print(std::cout);
      std::cout << "             ==>: ";
      target->Print(std::cout);
      std::cout << std::endl;
#endif
      src->ReplaceAllUseWith(target);
      it = bb->GetInstList().erase(it);
      delete src;
    };
    auto find_and_replace = [&exp, &it, &find_if_cmp, &replace, this](Value* src) {
      auto vec_it = std::find_if(exp_val_vec.begin(), exp_val_vec.end(), find_if_cmp);
      if (vec_it == exp_val_vec.end()) {
        exp_val_vec.push_back({exp, src});
        ++it;
      } else {
        replace(src, (*vec_it).second);
      }
    };

    // 二元运算语句
    if (auto src_inst = dynamic_cast<BinaryOperator*>(inst)) {
      switch (src_inst->op_) {
        case BinaryOperator::ADD:
          exp.op_ = Expression::ADD;
          break;
        case BinaryOperator::SUB:
          exp.op_ = Expression::SUB;
          break;
        case BinaryOperator::MUL:
          exp.op_ = Expression::MUL;
          break;
        case BinaryOperator::DIV:
          exp.op_ = Expression::DIV;
          break;
        case BinaryOperator::MOD:
          exp.op_ = Expression::MOD;
          break;
        default:
          MyAssert(0);
          break;
      }
      exp.operands_.push_back(src_inst->GetOperand(0));
      exp.operands_.push_back(src_inst->GetOperand(1));

      find_and_replace(src_inst);
    }
    // 一元运算语句
    else if (auto src_inst = dynamic_cast<UnaryOperator*>(inst)) {
      switch (src_inst->op_) {
        case UnaryOperator::NEG:
          exp.op_ = Expression::NEG;
          break;
        case UnaryOperator::NOT:
          exp.op_ = Expression::NOT;
          break;
        default:
          MyAssert(0);
          break;
      }
      exp.operands_.push_back(src_inst->GetOperand(0));

      find_and_replace(src_inst);
    }
    // Call语句 需要关注call的函数是否有副作用 有副作用则不可删 kill掉原来的
    else if (auto src_inst = dynamic_cast<CallInst*>(inst)) {
      auto func_val = dynamic_cast<FunctionValue*>(src_inst->GetOperand(0));
      MyAssert(nullptr != func_val);
      // 如果调用了有副作用的函数 不用处理该语句
      if (no_side_effect_funcs.find(func_val->GetFunction()) == no_side_effect_funcs.end()) {
        // TODO: 这里可以考虑把该基本块内的load exp都kill掉
        ++it;
        continue;
      }
      // 调用了void函数也可以算作表达式 虽然没有使用 但是可以删除一条多余的call
      // 如果前面做了死代码消除 不应该出现调用无副作用void函数的call语句

      // Expression exp(Expression::CALL);
      exp.op_ = Expression::CALL;
      for (int i = 0; i < src_inst->GetNumOperands(); ++i) {
        exp.operands_.push_back(src_inst->GetOperand(i));
      }

      find_and_replace(src_inst);
    }
    // Load语句 如果找到一条公共的load语句 需要检查从该语句开始到当前语句的所有执行路径上都没有对target的store语句
    else if (auto src_inst = dynamic_cast<LoadInst*>(inst)) {
      exp.op_ = Expression::LOAD;
      for (int i = 0; i < src_inst->GetNumOperands(); ++i) {
        exp.operands_.push_back(src_inst->GetOperand(i));
      }

      auto check_inst_range = [this](std::list<SSAInstruction*>::iterator begin,
                                     std::list<SSAInstruction*>::iterator end, LoadInst* target) {
        Value* memory = target->GetOperand(0);
        for (; begin != end; ++begin) {
          // 是调用了有副作用函数的call语句
          auto call_inst = dynamic_cast<CallInst*>(*begin);
          if (nullptr != call_inst) {
            auto func_val = dynamic_cast<FunctionValue*>(call_inst->GetOperand(0));
            if (no_side_effect_funcs.find(func_val->GetFunction()) == no_side_effect_funcs.end()) {
              return false;
            }
          }

          // 是对同一块内存区域的store语句
          auto store_inst = dynamic_cast<StoreInst*>(*begin);
          if (nullptr != store_inst && store_inst->GetOperand(1) == memory) {
            // 如果load和store语句的偏移都是常量的话可以比较立即数 如果不同 则跳过这条store语句
            // NOTE: 都有偏移 要么都有 要么都没 不会出现一个有一个没有
            if (target->GetNumOperands() == 2 && store_inst->GetNumOperands() == 3) {
              if (auto constint = dynamic_cast<ConstantInt*>(target->GetOperand(1))) {
                if (auto constint2 = dynamic_cast<ConstantInt*>(store_inst->GetOperand(2))) {
                  if (constint->GetImm() != constint2->GetImm()) continue;
                }
              }
            }
            return false;
          }
        }
        return true;
      };

      auto check = [this, &check_inst_range](SSAInstruction* source, LoadInst* target) {
        // 检查从source指令开始到target指定的所有路径上有没有对同一块内存区域的store语句或者对副作用函数的调用语句
        // source可能是load或store target一定是load
        // source->Print(std::cout);
        // target->Print(std::cout);
        auto source_bb = source->GetParent();
        auto target_bb = target->GetParent();
        // 1 if source and target in the same bb
        if (source_bb == target_bb) {
          auto inst_list = source_bb->GetInstList();
          auto st = ++std::find(inst_list.begin(), inst_list.end(), source),
               ed = std::find(st, inst_list.end(), target);
          return check_inst_range(st, ed, target);
        }
        // 2 in different bbs
        // NOTE: 好像会导致更多的溢出 禁用 等决赛可以取消禁用提交一次
        else {
          // return false;
          // 2.1 check source bb
          auto src_inst_list = source_bb->GetInstList();
          if (!check_inst_range(++std::find(src_inst_list.begin(), src_inst_list.end(), source), src_inst_list.end(),
                                target))
            return false;
          // std::cout << 1 << std::endl;
          // 2.2 check target bb
          auto tar_inst_list = target_bb->GetInstList();
          if (!check_inst_range(tar_inst_list.begin(), std::find(tar_inst_list.begin(), tar_inst_list.end(), target),
                                target))
            return false;
          // std::cout << 2 << std::endl;
          // 2.3 check all reached bb in road
          std::unordered_set<SSABasicBlock*> src_reach;
          std::unordered_set<SSABasicBlock*> tar_reach;
          std::queue<SSABasicBlock*> q;
          std::unordered_set<SSABasicBlock*> vis;
          auto dfs = [&q, &vis](std::unordered_set<SSABasicBlock*>& reach, bool succ = true) {
            while (!q.empty()) {
              auto front = q.front();
              reach.insert(front);
              q.pop();
              for (auto next_bb : (succ ? front->GetSuccBB() : front->GetPredBB())) {
                if (vis.count(next_bb)) continue;
                q.push(next_bb);
                vis.insert(next_bb);
              }
            }
            vis.clear();
          };

          // 2.3.1 fill src_reach
          q.push(source_bb);
          vis.insert(source_bb);
          dfs(src_reach, true);

          // 2.3.2 fill tar_reach
          q.push(target_bb);
          vis.insert(target_bb);
          dfs(tar_reach, false);

          // 2.3.3 compute cross set
          std::unordered_set<SSABasicBlock*> reached_bb;
          for (auto reach_bb : src_reach)
            if (tar_reach.count(reach_bb)) reached_bb.insert(reach_bb);

          // 2.3.4 determine source_bb and target_bb whether in road or not(just end point).
          if (!bbs_in_loop.count(source_bb)) reached_bb.erase(source_bb);
          if (!bbs_in_loop.count(target_bb)) reached_bb.erase(target_bb);

          // 2.3.5 check all bbs in road
          for (auto bb : reached_bb) {
            auto inst_list = bb->GetInstList();
            if (!check_inst_range(inst_list.begin(), inst_list.end(), target)) return false;
          }

          // std::cout << 3 << std::endl;
          return true;
        }
      };

      // NOTE: reverse find 保证找到最新的一个
      auto vec_it = std::find_if(exp_val_vec.rbegin(), exp_val_vec.rend(), find_if_cmp);
      if (vec_it == exp_val_vec.rend()) {
        exp_val_vec.push_back({exp, src_inst});
        ++it;
      } else {
        // check决定能否replace if check true, perform replace. otherwise add exp to exp_val_vec
        if (check((*vec_it).first.inst_, src_inst)) {
          replace(src_inst, (*vec_it).second);
        } else {
          exp_val_vec.push_back({exp, src_inst});
          ++it;
        }
      }
    }
    // Store语句 可以看成一条load语句 同时或许可以kill掉该基本块内的对同一块内存操作的load语句
    else if (auto src_inst = dynamic_cast<StoreInst*>(inst)) {
      exp.op_ = Expression::LOAD;
      for (int i = 1; i < src_inst->GetNumOperands(); ++i) {
        exp.operands_.push_back(src_inst->GetOperand(i));
      }

      // 不管有没有 直接加进去即可 之后再找相同的load exp 保证找到最新(靠后)的一个就行
      exp_val_vec.push_back({exp, src_inst->GetOperand(0)});
      ++it;
    }
    // 其他语句
    else {
      ++it;
    }
  }

  // traverse dom tree
  for (auto dom : bb->GetDoms()) {
    CommenExpressionEliminate(dom);
  }

  // erase now bb exps from exp_val_vec
  exp_val_vec.erase(exp_val_vec.begin() + src_vec_size, exp_val_vec.end());
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x278, %rsp            # imm = 0x278
leaq 0xd8(%rsp), %rax
movq %rsi, (%rax)
leaq 0xa8(%rdi), %rax
movq %rax, 0x20(%rsp)
movq 0xa8(%rdi), %rax
movq %rax, 0x108(%rsp)
movq 0xb0(%rdi), %rax
movq %rax, 0x110(%rsp)
movq 0x28(%rsi), %rbp
leaq 0x8(%rsp), %rax
movq %rbp, (%rax)
leaq 0x58(%rsp), %r12
leaq 0x38(%rdi), %rax
movq %rax, 0x118(%rsp)
movq %rdi, 0x30(%rsp)
leaq 0x70(%rdi), %rax
movq %rax, 0x100(%rsp)
leaq 0x28(%rsi), %rax
cmpq %rax, %rbp
je 0x42617
movq 0x10(%rbp), %r13
andq $0x0, 0x10(%r12)
xorps %xmm0, %xmm0
movups %xmm0, (%r12)
movq %r13, 0x70(%rsp)
leaq 0x50(%rsp), %rcx
movq %rcx, 0xd0(%rsp)
leaq 0xd8(%rsp), %rax
movq %rax, 0x120(%rsp)
leaq 0x8(%rsp), %rax
movq %rax, 0x128(%rsp)
movq %rcx, 0x158(%rsp)
movq %rax, 0x160(%rsp)
leaq 0xd0(%rsp), %rax
movq %rax, 0x168(%rsp)
leaq 0x120(%rsp), %rax
movq %rax, 0x170(%rsp)
movq 0x30(%rsp), %rax
movq %rax, 0x178(%rsp)
testq %r13, %r13
je 0x42068
movq %r13, %rdi
leaq 0x3e6e6(%rip), %rbx     # 0x803c8
movq %rbx, %rsi
leaq 0x3e914(%rip), %rdx     # 0x80600
xorl %ecx, %ecx
callq 0x82c0
testq %rax, %rax
je 0x41d27
movq %rax, %r15
movl 0x68(%rax), %eax
cmpq $0x4, %rax
ja 0x426d5
leaq 0x17b41(%rip), %rcx     # 0x59850
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
leaq 0x78(%rsp), %rbx
jmpq *%rax
andl $0x0, 0x50(%rsp)
jmp 0x41e6e
movq %r13, %rdi
movq %rbx, %rsi
leaq 0x3e90c(%rip), %rdx     # 0x80640
xorl %ecx, %ecx
callq 0x82c0
testq %rax, %rax
je 0x41d91
movq %rax, %r15
movl 0x68(%rax), %ecx
pushq $0x5
popq %rax
testl %ecx, %ecx
leaq 0x78(%rsp), %rbx
je 0x41d5e
cmpl $0x1, %ecx
jne 0x4271d
pushq $0x6
popq %rax
movl %eax, 0x50(%rsp)
movq %r15, %rdi
xorl %esi, %esi
callq 0x269a6
movq %rax, 0x78(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x43dec
leaq 0x158(%rsp), %rdi
movq %r15, %rsi
callq 0x42868
jmp 0x42071
movq %r13, %rdi
movq %rbx, %rsi
leaq 0x3e922(%rip), %rdx     # 0x806c0
xorl %ecx, %ecx
callq 0x82c0
testq %rax, %rax
je 0x41ecd
movq %rax, %r15
movq %rax, %rdi
xorl %esi, %esi
callq 0x269a6
leaq 0x78(%rsp), %rbx
testq %rax, %rax
je 0x4268a
movq %rax, %rdi
leaq 0x3e6ad(%rip), %rsi     # 0x80480
leaq 0x3e6fe(%rip), %rdx     # 0x804d8
xorl %ecx, %ecx
callq 0x82c0
testq %rax, %rax
je 0x4268a
movq 0x60(%rax), %rax
movq %rax, 0x78(%rsp)
movq 0x118(%rsp), %rdi
movq %rbx, %rsi
callq 0x3a44c
testq %rax, %rax
je 0x425ec
movl $0x7, 0x50(%rsp)
xorl %ebp, %ebp
movq 0x50(%r15), %rax
subq 0x48(%r15), %rax
shrq $0x4, %rax
cmpl %eax, %ebp
jae 0x41eb8
movq %r15, %rdi
movl %ebp, %esi
callq 0x269a6
movq %rax, 0x78(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x43dec
incl %ebp
jmp 0x41e16
movl $0x4, 0x50(%rsp)
jmp 0x41e6e
movl $0x2, 0x50(%rsp)
jmp 0x41e6e
movl $0x3, 0x50(%rsp)
jmp 0x41e6e
movl $0x1, 0x50(%rsp)
movq %r15, %rdi
xorl %esi, %esi
callq 0x269a6
movq %rax, 0x78(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x43dec
movq %r15, %rdi
pushq $0x1
popq %rsi
callq 0x269a6
movq %rax, 0x78(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x43dec
leaq 0x158(%rsp), %rdi
movq %r15, %rsi
callq 0x42868
jmp 0x42071
leaq 0x158(%rsp), %rdi
movq %r15, %rsi
callq 0x42868
jmp 0x42071
movq %r13, %rdi
movq %rbx, %rsi
leaq 0x3e8a6(%rip), %rdx     # 0x80780
xorl %ecx, %ecx
callq 0x82c0
testq %rax, %rax
je 0x4200e
movq %rax, %r15
movl $0x8, 0x50(%rsp)
xorl %ebp, %ebp
leaq 0x78(%rsp), %rbx
movq 0x50(%r15), %rax
subq 0x48(%r15), %rax
shrq $0x4, %rax
cmpl %eax, %ebp
jae 0x41f2a
movq %r15, %rdi
movl %ebp, %esi
callq 0x269a6
movq %rax, 0x78(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x43dec
incl %ebp
jmp 0x41efc
movq 0x30(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0xa8(%rax), %rcx
movq 0xb0(%rax), %r12
movq 0xd0(%rsp), %rax
movq %rax, 0x78(%rsp)
movq %r12, %rax
movq %rcx, 0xc8(%rsp)
subq %rcx, %rax
movq %rax, 0x48(%rsp)
cqto
pushq $0x30
popq %rcx
idivq %rcx
movq %rax, %rbp
sarq $0x2, %rbp
incq %rbp
xorl %ebx, %ebx
movq %r15, 0x10(%rsp)
decq %rbp
jle 0x420bf
leaq (%r12,%rbx), %r13
addq $-0x30, %r13
leaq 0x78(%rsp), %r15
movq %r15, %rdi
movq %r13, %rsi
callq 0x42d72
testb %al, %al
jne 0x420f2
leaq (%r12,%rbx), %rsi
addq $-0x60, %rsi
movq %r15, %rdi
movq %rsi, %r14
callq 0x42d72
testb %al, %al
jne 0x420f8
leaq (%r12,%rbx), %rsi
addq $-0x90, %rsi
movq %r15, %rdi
callq 0x42d72
testb %al, %al
jne 0x420ff
leaq (%r12,%rbx), %rsi
addq $-0xc0, %rsi
addq $-0xc0, %rbx
movq %r15, %rdi
callq 0x42d72
testb %al, %al
movq 0x10(%rsp), %r15
je 0x41f7b
leaq (%r12,%rbx), %r13
addq $0x30, %r13
jmp 0x42167
movq %r13, %rdi
movq %rbx, %rsi
leaq 0x3e7a5(%rip), %rdx     # 0x807c0
xorl %ecx, %ecx
callq 0x82c0
testq %rax, %rax
leaq 0x78(%rsp), %rbx
je 0x42068
movq %rax, %r15
movl $0x8, 0x50(%rsp)
pushq $0x1
popq %rbp
movq 0x50(%r15), %rax
subq 0x48(%r15), %rax
shrq $0x4, %rax
cmpl %eax, %ebp
jae 0x4208b
movq %r15, %rdi
movl %ebp, %esi
callq 0x269a6
movq %rax, 0x78(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x43dec
incl %ebp
jmp 0x4203a
movq (%rbp), %rax
movq %rax, 0x8(%rsp)
movq %r12, %rdi
callq 0x43250
movq 0xd8(%rsp), %rsi
movq 0x8(%rsp), %rbp
jmp 0x41c44
movq %r15, %rdi
xorl %esi, %esi
callq 0x269a6
movq %rax, %r15
movq %rbx, %rdi
leaq 0x50(%rsp), %rsi
callq 0x431d6
movq %r15, 0xa0(%rsp)
movq 0x20(%rsp), %rdi
movq %rbx, %rsi
callq 0x43b2e
jmp 0x425df
leaq (%r12,%rbx), %r14
movq 0x48(%rsp), %rax
addq %rbx, %rax
cqto
pushq $0x30
popq %rcx
idivq %rcx
cmpq $0x1, %rax
je 0x42148
cmpq $0x3, %rax
je 0x42109
movq %r14, %rbp
movq 0xc8(%rsp), %r13
cmpq $0x2, %rax
je 0x4212d
jmp 0x42167
addq %rbx, %r12
movq %r12, %r13
movq 0x10(%rsp), %r15
jmp 0x42167
movq 0x10(%rsp), %r15
movq %r14, %r13
jmp 0x42167
leaq (%r12,%rbx), %rbp
addq $-0x30, %rbp
leaq 0x78(%rsp), %rdi
movq %rbp, %rsi
callq 0x42d72
movq %r14, %r13
testb %al, %al
jne 0x42167
leaq (%r12,%rbx), %r14
addq $-0x30, %r14
movq %r14, %r13
movq %rbp, %r14
addq $-0x30, %r14
leaq 0x78(%rsp), %rdi
movq %r14, %rsi
callq 0x42d72
testb %al, %al
jne 0x42167
movq %r14, %rsi
addq $-0x30, %rsi
leaq 0x78(%rsp), %rdi
callq 0x42d72
testb %al, %al
movq 0xc8(%rsp), %r13
cmovneq %r14, %r13
movq 0x20(%rsp), %rax
cmpq %r13, (%rax)
je 0x423f8
movq %r13, 0x48(%rsp)
movq -0x10(%r13), %rax
movq %rax, 0xe0(%rsp)
movq %r15, 0x18(%rsp)
movq 0x60(%rax), %rax
movq %rax, 0x40(%rsp)
movq 0x60(%r15), %rcx
movq %rcx, 0x28(%rsp)
leaq 0x28(%rax), %rsi
cmpq %rcx, %rax
leaq 0x58(%rsp), %r12
leaq 0x78(%rsp), %rbx
je 0x42429
leaq 0xe8(%rsp), %rdi
callq 0x432e6
movq 0xe8(%rsp), %rdi
leaq 0xe8(%rsp), %r15
movq %r15, %rsi
leaq 0xe0(%rsp), %rdx
callq 0x29bb9
movq (%rax), %rsi
movq 0x18(%rsp), %rcx
leaq 0x38(%rsp), %rdi
movq %r15, %rdx
callq 0x42eac
testb %al, %al
je 0x42486
movq 0x28(%rsp), %rsi
addq $0x28, %rsi
leaq 0x140(%rsp), %r15
movq %r15, %rdi
callq 0x432e6
movq 0x140(%rsp), %r13
movq %r13, %rdi
movq %r15, %rsi
leaq 0x18(%rsp), %rdx
callq 0x43363
movq 0x18(%rsp), %rcx
leaq 0x38(%rsp), %rdi
movq %r13, %rsi
movq %rax, %rdx
callq 0x42eac
testb %al, %al
movq 0x10(%rsp), %r15
je 0x4249d
leaq 0x238(%rsp), %rax
movq %rax, 0x208(%rsp)
pushq $0x1
popq %rdx
movq %rdx, 0x210(%rsp)
leaq 0x218(%rsp), %rcx
xorps %xmm0, %xmm0
movups %xmm0, (%rcx)
movl $0x3f800000, %ecx       # imm = 0x3F800000
movl %ecx, 0x228(%rsp)
movups %xmm0, -0x8(%rax)
leaq 0x270(%rsp), %rax
movq %rax, 0x240(%rsp)
movq %rdx, 0x248(%rsp)
movups %xmm0, -0x20(%rax)
movl %ecx, 0x260(%rsp)
movups %xmm0, -0x8(%rax)
movq %rbx, %rdi
callq 0x430fc
leaq 0x1b8(%rsp), %r14
leaq 0x200(%rsp), %rax
movq %rax, 0x1d0(%rsp)
movq $0x1, 0x1d8(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, -0x20(%rax)
movl $0x3f800000, 0x1f0(%rsp) # imm = 0x3F800000
movups %xmm0, -0x8(%rax)
movq %rbx, 0x130(%rsp)
leaq 0x1d0(%rsp), %rax
movq %rax, 0x138(%rsp)
movq %rbx, %rdi
leaq 0x40(%rsp), %rsi
callq 0x43806
leaq 0x1d0(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x28e4c
leaq 0x130(%rsp), %rdi
leaq 0x208(%rsp), %rsi
pushq $0x1
popq %rdx
callq 0x4304c
movq %rbx, %rdi
leaq 0x28(%rsp), %rsi
callq 0x43806
leaq 0x1d0(%rsp), %rdi
leaq 0x28(%rsp), %rsi
callq 0x28e4c
leaq 0x130(%rsp), %rdi
leaq 0x240(%rsp), %rsi
xorl %edx, %edx
callq 0x4304c
leaq 0x1b0(%rsp), %rax
movq %rax, 0x180(%rsp)
movq $0x1, 0x188(%rsp)
xorps %xmm0, %xmm0
leaq 0x190(%rsp), %rcx
movups %xmm0, (%rcx)
movl $0x3f800000, 0x1a0(%rsp) # imm = 0x3F800000
movups %xmm0, -0x8(%rax)
leaq 0x218(%rsp), %rbx
movq (%rbx), %rbx
testq %rbx, %rbx
je 0x424bc
movq 0x8(%rbx), %rax
movq %rax, 0x1b8(%rsp)
leaq 0x240(%rsp), %rdi
movq %r14, %rsi
callq 0x4347c
testq %rax, %rax
je 0x423b9
leaq 0x180(%rsp), %rdi
movq %r14, %rsi
callq 0x28e4c
jmp 0x423b9
leaq 0x78(%rsp), %rbx
movq %rbx, %rdi
leaq 0x50(%rsp), %rsi
leaq 0x58(%rsp), %r12
callq 0x431d6
movq %r15, 0xa0(%rsp)
movq 0x20(%rsp), %rdi
movq %rbx, %rsi
callq 0x43b2e
jmp 0x425df
movq %rbx, %rdi
callq 0x432e6
movq 0x78(%rsp), %rdi
movq %rbx, %rsi
leaq 0xe0(%rsp), %rdx
callq 0x29bb9
movq (%rax), %r13
movq %r13, %rdi
movq %rbx, %rsi
leaq 0x18(%rsp), %rdx
callq 0x43363
movq 0x18(%rsp), %rcx
leaq 0x38(%rsp), %rdi
movq %r13, %rsi
movq %rax, %rdx
callq 0x42eac
movl %eax, %ebp
movq %rbx, %rdi
callq 0x28cf8
testb %bpl, %bpl
je 0x425bd
jmp 0x425f9
leaq 0xe8(%rsp), %rdi
callq 0x28cf8
movq 0x10(%rsp), %r15
jmp 0x425bd
leaq 0x140(%rsp), %rdi
callq 0x28cf8
leaq 0xe8(%rsp), %rdi
callq 0x28cf8
jmp 0x425bd
movq 0x100(%rsp), %rbx
movq %rbx, %rdi
leaq 0x40(%rsp), %rsi
callq 0x4347c
testq %rax, %rax
jne 0x424e8
leaq 0x180(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x4337a
movq %rbx, %rdi
leaq 0x28(%rsp), %rsi
callq 0x4347c
testq %rax, %rax
jne 0x4250c
leaq 0x180(%rsp), %rdi
leaq 0x28(%rsp), %rsi
callq 0x4337a
leaq 0x190(%rsp), %rbx
movq (%rbx), %rbx
testq %rbx, %rbx
je 0x42555
movq 0x8(%rbx), %rsi
addq $0x28, %rsi
movq %r14, %rdi
callq 0x432e6
movq 0x1b8(%rsp), %rsi
movq 0x18(%rsp), %rcx
leaq 0x38(%rsp), %rdi
movq %r14, %rdx
callq 0x42eac
movl %eax, %ebp
movq %r14, %rdi
callq 0x28cf8
testb %bpl, %bpl
jne 0x42514
leaq 0x180(%rsp), %rdi
callq 0x28c50
leaq 0x1d0(%rsp), %rdi
callq 0x28c50
leaq 0x78(%rsp), %r15
movq %r15, %rdi
callq 0x43126
leaq 0x240(%rsp), %rdi
callq 0x28c50
leaq 0x208(%rsp), %rdi
callq 0x28c50
leaq 0x140(%rsp), %rdi
callq 0x28cf8
leaq 0xe8(%rsp), %rdi
callq 0x28cf8
testq %rbx, %rbx
movq %r15, %rbx
movq 0x10(%rsp), %r15
je 0x425f9
movq %rbx, %rdi
leaq 0x50(%rsp), %rsi
callq 0x431d6
movq %r15, 0xa0(%rsp)
movq 0x20(%rsp), %rdi
movq %rbx, %rsi
callq 0x43b2e
leaq 0x80(%rsp), %rdi
callq 0x43250
movq 0x8(%rsp), %rax
movq (%rax), %rax
jmp 0x4206c
movq 0x48(%rsp), %rax
movq -0x8(%rax), %rdx
leaq 0x120(%rsp), %rdi
movq %r15, %rsi
callq 0x42a5e
jmp 0x42071
movq 0x20(%rsp), %r12
movq 0x78(%rsi), %rbx
movq 0x80(%rsi), %r15
cmpq %r15, %rbx
je 0x4263f
movq (%rbx), %rsi
movq 0x30(%rsp), %rdi
callq 0x41bd0
addq $0x8, %rbx
jmp 0x42627
movq 0x110(%rsp), %rax
subq 0x108(%rsp), %rax
cqto
pushq $0x30
popq %rcx
idivq %rcx
cltq
imulq $0x30, %rax, %rsi
movq 0x30(%rsp), %rax
addq 0xa8(%rax), %rsi
movq 0xb0(%rax), %rdx
movq %r12, %rdi
callq 0x43120
addq $0x278, %rsp            # imm = 0x278
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x3e957(%rip), %rdi     # 0x80fe8
leaq 0x13a50(%rip), %rsi     # 0x560e8
callq 0x8240
leaq 0x171d7(%rip), %rsi     # 0x5987b
movq %rax, %rdi
callq 0x8240
leaq 0x14c6d(%rip), %rsi     # 0x57320
movq %rax, %rdi
callq 0x8240
movq %rax, %rdi
movl $0xc1, %esi
callq 0x84b0
movq %rax, %rdi
callq 0x8170
jmp 0x42763
movq 0x3e90c(%rip), %rdi     # 0x80fe8
leaq 0x13a05(%rip), %rsi     # 0x560e8
callq 0x8240
leaq 0x1718c(%rip), %rsi     # 0x5987b
movq %rax, %rdi
callq 0x8240
leaq 0x14c22(%rip), %rsi     # 0x57320
movq %rax, %rdi
callq 0x8240
movq %rax, %rdi
movl $0xa5, %esi
callq 0x84b0
movq %rax, %rdi
callq 0x8170
jmp 0x42763
movq 0x3e8c4(%rip), %rdi     # 0x80fe8
leaq 0x139bd(%rip), %rsi     # 0x560e8
callq 0x8240
leaq 0x17144(%rip), %rsi     # 0x5987b
movq %rax, %rdi
callq 0x8240
leaq 0x14bda(%rip), %rsi     # 0x57320
movq %rax, %rdi
callq 0x8240
movq %rax, %rdi
movl $0xb7, %esi
callq 0x84b0
movq %rax, %rdi
callq 0x8170
movl $0xff, %edi
callq 0x8300
movq %rax, %r14
jmp 0x4280a
jmp 0x427c2
jmp 0x4278c
jmp 0x427e3
jmp 0x42799
jmp 0x42799
jmp 0x42855
movq %rax, %r14
jmp 0x42824
movq %rax, %r14
leaq 0x78(%rsp), %rdi
jmp 0x42839
movq %rax, %r14
leaq 0x80(%rsp), %rdi
callq 0x43250
jmp 0x42858
jmp 0x42855
movq %rax, %r14
jmp 0x427f3
jmp 0x42855
jmp 0x42855
movq %rax, %r14
jmp 0x42831
movq %rax, %r14
leaq 0x1b8(%rsp), %rdi
callq 0x28cf8
jmp 0x427e6
jmp 0x427e3
jmp 0x42855
jmp 0x42855
jmp 0x42855
jmp 0x42855
movq %rax, %r14
leaq 0x180(%rsp), %rdi
callq 0x28c50
leaq 0x1d0(%rsp), %rdi
callq 0x28c50
leaq 0x78(%rsp), %rdi
callq 0x43126
leaq 0x240(%rsp), %rdi
callq 0x28c50
leaq 0x208(%rsp), %rdi
callq 0x28c50
leaq 0x140(%rsp), %rdi
callq 0x28cf8
leaq 0xe8(%rsp), %rdi
callq 0x28cf8
leaq 0x58(%rsp), %r12
jmp 0x42858
jmp 0x42855
jmp 0x42855
jmp 0x42855
jmp 0x42855
jmp 0x42855
jmp 0x42855
jmp 0x42855
jmp 0x42855
movq %rax, %r14
movq %r12, %rdi
callq 0x43250
movq %r14, %rdi
callq 0x84d0