// File: /workspace/github_cpp_makefile_star2_O2/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %rbx
testl %r8d, %r8d
je 0x3d092
movl %r8d, %r12d
movq %rcx, %r13
movq %rdi, %r14
leal -0x1(%r12), %ebp
testl %ebp, %r8d
jne 0x3d0d6
movq %rdx, (%rsp)
pushq $0x18
popq %rdi
callq 0x8250
movq %rax, %r15
movq %r14, %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq 0x3d242
movq %rax, %r14
pushq $0x18
popq %rdi
callq 0x8250
movq %rax, %r13
movl %r12d, %edi
callq 0x3d4a0
movl $0x1, (%r13)
movb $0x1, 0x4(%r13)
movl %eax, 0x8(%r13)
andq $0x0, 0x10(%r13)
movb $0x0, (%r15)
andl $0x0, 0x4(%r15)
movq %r14, 0x8(%r15)
movq %r13, 0x10(%r15)
pushq $0x28
popq %rdi
callq 0x8250
movq %rax, %r14
movb $0x1, %bpl
pushq $0x1
popq %r9
movq %rax, %rdi
movq (%rsp), %rsi
movq %r15, %rdx
movq %rbx, %rcx
xorl %r8d, %r8d
callq 0x3fbc8
jmp 0x3d1fc
movq %rdx, %r14
pushq $0x28
popq %rdi
callq 0x8250
movq %rax, %r15
pushq $0x18
popq %rdi
callq 0x8250
movb $0x1, (%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x4(%rax)
andl $0x0, 0x14(%rax)
movb $0x1, %bpl
pushq $0x1
popq %r9
movq %r15, %rdi
movq %r14, %rsi
movq %rax, %rdx
movq %rbx, %rcx
xorl %r8d, %r8d
callq 0x3fbc8
jmp 0x3d1fc
leal -0x2(%r12), %eax
testl %eax, %ebp
je 0x3d0f4
leal 0x1(%r12), %ebp
testl %r12d, %ebp
je 0x3d17a
xorl %ebp, %ebp
jmp 0x3d1fc
movq %rdx, (%rsp)
movq %r14, %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq 0x3d242
movq %rax, %r12
pushq $0x18
popq %r14
movq %r14, %rdi
callq 0x8250
movq %rax, %r15
movq %r14, %rdi
callq 0x8250
movq %rax, %r14
movl %ebp, %edi
callq 0x3d4a0
movl $0x1, (%r14)
movb $0x1, 0x4(%r14)
movl %eax, 0x8(%r14)
andq $0x0, 0x10(%r14)
movb $0x0, (%r15)
andl $0x0, 0x4(%r15)
movq %r12, 0x8(%r15)
movq %r14, 0x10(%r15)
pushq $0x38
popq %rdi
callq 0x8250
movq %rax, %r14
movb $0x1, %bpl
movq %rax, %rdi
xorl %esi, %esi
movq (%rsp), %rdx
movq %r12, %rcx
movq %r15, %r8
movq %rbx, %r9
callq 0x3fd3c
jmp 0x3d1fc
movq %rdx, (%rsp)
movq %r14, %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq 0x3d242
movq %rax, %r12
pushq $0x18
popq %r14
movq %r14, %rdi
callq 0x8250
movq %rax, %r15
movq %r14, %rdi
callq 0x8250
movq %rax, %r14
movl %ebp, %edi
callq 0x3d4a0
movl $0x1, (%r14)
movb $0x1, 0x4(%r14)
movl %eax, 0x8(%r14)
andq $0x0, 0x10(%r14)
movb $0x0, (%r15)
andl $0x0, 0x4(%r15)
movq %r12, 0x8(%r15)
movq %r14, 0x10(%r15)
pushq $0x38
popq %rdi
callq 0x8250
movq %rax, %r14
movb $0x1, %bpl
pushq $0x2
popq %rsi
movq %rax, %rdi
movq (%rsp), %rdx
movq %r12, %rcx
movq %r15, %r8
movq %rbx, %r9
callq 0x3fd3c
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x3d211
jmp 0x3d225
movq %rax, %rbx
pushq $0x38
jmp 0x3d21f
jmp 0x3d225
movq %rax, %rbx
pushq $0x28
popq %rsi
movq %r14, %rdi
jmp 0x3d235
movq %rax, %rbx
pushq $0x18
jmp 0x3d231
movq %rax, %rbx
pushq $0x28
popq %rsi
movq %r15, %rdi
callq 0x8260
movq %rbx, %rdi
callq 0x84d0