// File: luooofan[P]hblzbd_compiler/src/Pass/generate_arm_from_ssa.cpp
// Function: GenerateArmFromSSA::ConvertMul2Shift(ArmBasicBlock*, arm::Reg*, Value*, int)
bool GenerateArmFromSSA::ConvertMul2Shift(ArmBasicBlock* armbb, Reg* rd, Value* val, int imm) {
  // 如果乘数是0 生成一条mov rd 0的指令
  if (0 == imm) {
    new Move(rd, new Operand2(0), armbb);
    return true;
  }
  auto eval_n = [](int imm) {
    int n = 0;
    while (imm > 1) {
      imm >>= 1;
      ++n;
    }
    return n;
  };
  // 如果乘数是2的幂次方 生成一条mov rd rm LSL n的指令 LSL允许0-31位
  if (0 == (imm & (imm - 1))) {
    auto op2 = new Operand2(ResolveValue2Reg(armbb, val), new Shift(Shift::OpCode::LSL, eval_n(imm)));
    new Move(rd, op2, armbb);
    return true;
  }
  // 如果乘数是2的幂次方+1 生成一条add rd, rn, rn LSL n
  if (0 == ((imm - 1) & (imm - 2))) {
    // std::cout << 1 << std::endl;
    auto vreg = ResolveValue2Reg(armbb, val);
    auto op2 = new Operand2(vreg, new Shift(Shift::OpCode::LSL, eval_n(imm - 1)));
    new BinaryInst(BiOp::ADD, rd, vreg, op2, armbb);
    return true;
  }
  // 如果乘数是2的幂次方-1 生成一条rsb rd, rn, rn LSL n
  if (0 == ((imm + 1) & (imm))) {
    // std::cout << 2 << std::endl;
    auto vreg = ResolveValue2Reg(armbb, val);
    auto op2 = new Operand2(vreg, new Shift(Shift::OpCode::LSL, eval_n(imm + 1)));
    new BinaryInst(BiOp::RSB, rd, vreg, op2, armbb);
    return true;
  }
  return false;
}

// Assembly:
subq $0x118, %rsp            # imm = 0x118
movq %rdi, 0x108(%rsp)
movq %rsi, 0x100(%rsp)
movq %rdx, 0xf8(%rsp)
movq %rcx, 0xf0(%rsp)
movl %r8d, 0xec(%rsp)
movq 0x108(%rsp), %rax
movq %rax, 0xa8(%rsp)
xorl %eax, %eax
cmpl 0xec(%rsp), %eax
jne 0xabac5
movl $0x28, %edi
callq 0x8340
movq %rax, 0x90(%rsp)
movq 0xf8(%rsp), %rax
movq %rax, 0x98(%rsp)
movl $0x18, %edi
callq 0x8340
movq %rax, 0xa0(%rsp)
jmp 0xaba24
movq 0xa0(%rsp), %rdi
xorl %esi, %esi
callq 0x77f00
jmp 0xaba35
movq 0xa0(%rsp), %rdx
movq 0x98(%rsp), %rsi
movq 0x90(%rsp), %rdi
movq 0x100(%rsp), %rcx
xorl %r8d, %r8d
movl $0x1, %r9d
callq 0xb2060
jmp 0xaba65
movb $0x1, 0x117(%rsp)
jmp 0xabf5c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
jmp 0xabaae
movq 0xa0(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
movl $0x18, %esi
callq 0x8350
movq 0x90(%rsp), %rdi
movl $0x28, %esi
callq 0x8350
jmp 0xabf6d
movl 0xec(%rsp), %ecx
movl 0xec(%rsp), %eax
subl $0x1, %eax
andl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
jne 0xabc49
movl $0x18, %edi
callq 0x8340
movq 0xa8(%rsp), %rdi
movq %rax, 0x80(%rsp)
movq 0x100(%rsp), %rsi
movq 0xf0(%rsp), %rdx
callq 0xabf80
movq %rax, 0x88(%rsp)
jmp 0xabb1b
movl $0x18, %edi
callq 0x8340
movq %rax, 0x78(%rsp)
jmp 0xabb2c
movl 0xec(%rsp), %esi
leaq 0xdb(%rsp), %rdi
callq 0xac540
movl %eax, 0x74(%rsp)
jmp 0xabb46
movl 0x74(%rsp), %edx
movq 0x78(%rsp), %rdi
movl $0x1, %esi
callq 0xb2340
jmp 0xabb5b
movq 0x78(%rsp), %rdx
movq 0x88(%rsp), %rsi
movq 0x80(%rsp), %rdi
callq 0xb2370
jmp 0xabb77
movq 0x80(%rsp), %rax
movq %rax, 0xd0(%rsp)
movl $0x28, %edi
callq 0x8340
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x68(%rsp)
movq 0xf8(%rsp), %rsi
movq 0xd0(%rsp), %rdx
movq 0x100(%rsp), %rcx
xorl %r8d, %r8d
movl $0x1, %r9d
callq 0xb2060
jmp 0xabbc4
movb $0x1, 0x117(%rsp)
jmp 0xabf5c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
jmp 0xabc0a
movq 0x78(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
movl $0x18, %esi
callq 0x8350
movq 0x80(%rsp), %rdi
movl $0x18, %esi
callq 0x8350
jmp 0xabf6d
movq 0x68(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
movl $0x28, %esi
callq 0x8350
jmp 0xabf6d
movl 0xec(%rsp), %ecx
subl $0x1, %ecx
movl 0xec(%rsp), %eax
subl $0x2, %eax
andl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
jne 0xabdd4
movq 0xa8(%rsp), %rdi
movq 0x100(%rsp), %rsi
movq 0xf0(%rsp), %rdx
callq 0xabf80
movq %rax, 0xc8(%rsp)
movl $0x18, %edi
movq %rdi, 0x48(%rsp)
callq 0x8340
movq 0x48(%rsp), %rdi
movq %rax, 0x50(%rsp)
movq 0xc8(%rsp), %rax
movq %rax, 0x58(%rsp)
callq 0x8340
movq %rax, 0x60(%rsp)
jmp 0xabcc0
movl 0xec(%rsp), %esi
decl %esi
leaq 0xdb(%rsp), %rdi
callq 0xac540
movl %eax, 0x44(%rsp)
jmp 0xabcdc
movl 0x44(%rsp), %edx
movq 0x60(%rsp), %rdi
movl $0x1, %esi
callq 0xb2340
jmp 0xabcf1
movq 0x60(%rsp), %rdx
movq 0x58(%rsp), %rsi
movq 0x50(%rsp), %rdi
callq 0xb2370
jmp 0xabd07
movq 0x50(%rsp), %rax
movq %rax, 0xc0(%rsp)
movl $0x38, %edi
callq 0x8340
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x38(%rsp)
movq 0xf8(%rsp), %rdx
movq 0xc8(%rsp), %rcx
movq 0xc0(%rsp), %r8
movq 0x100(%rsp), %r9
xorl %esi, %esi
callq 0xb23b0
jmp 0xabd52
movb $0x1, 0x117(%rsp)
jmp 0xabf5c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
jmp 0xabd98
movq 0x60(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
movl $0x18, %esi
callq 0x8350
movq 0x50(%rsp), %rdi
movl $0x18, %esi
callq 0x8350
jmp 0xabf6d
movq 0x38(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
movl $0x38, %esi
callq 0x8350
jmp 0xabf6d
movl 0xec(%rsp), %ecx
addl $0x1, %ecx
andl 0xec(%rsp), %ecx
xorl %eax, %eax
cmpl %ecx, %eax
jne 0xabf54
movq 0xa8(%rsp), %rdi
movq 0x100(%rsp), %rsi
movq 0xf0(%rsp), %rdx
callq 0xabf80
movq %rax, 0xb8(%rsp)
movl $0x18, %edi
movq %rdi, 0x18(%rsp)
callq 0x8340
movq 0x18(%rsp), %rdi
movq %rax, 0x20(%rsp)
movq 0xb8(%rsp), %rax
movq %rax, 0x28(%rsp)
callq 0x8340
movq %rax, 0x30(%rsp)
jmp 0xabe46
movl 0xec(%rsp), %esi
incl %esi
leaq 0xdb(%rsp), %rdi
callq 0xac540
movl %eax, 0x14(%rsp)
jmp 0xabe62
movl 0x14(%rsp), %edx
movq 0x30(%rsp), %rdi
movl $0x1, %esi
callq 0xb2340
jmp 0xabe77
movq 0x30(%rsp), %rdx
movq 0x28(%rsp), %rsi
movq 0x20(%rsp), %rdi
callq 0xb2370
jmp 0xabe8d
movq 0x20(%rsp), %rax
movq %rax, 0xb0(%rsp)
movl $0x38, %edi
callq 0x8340
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x8(%rsp)
movq 0xf8(%rsp), %rdx
movq 0xb8(%rsp), %rcx
movq 0xb0(%rsp), %r8
movq 0x100(%rsp), %r9
movl $0x2, %esi
callq 0xb23b0
jmp 0xabedb
movb $0x1, 0x117(%rsp)
jmp 0xabf5c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
jmp 0xabf1e
movq 0x30(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
movl $0x18, %esi
callq 0x8350
movq 0x20(%rsp), %rdi
movl $0x18, %esi
callq 0x8350
jmp 0xabf6d
movq 0x8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
movl $0x38, %esi
callq 0x8350
jmp 0xabf6d
movb $0x0, 0x117(%rsp)
movb 0x117(%rsp), %al
andb $0x1, %al
addq $0x118, %rsp            # imm = 0x118
retq
movq 0xe0(%rsp), %rdi
callq 0x8670
nopw (%rax,%rax)