// File: /workspace/github_cpp_makefile_star2_O3/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 %rdx, %rbx
movq %rsi, %r14
testl %r8d, %r8d
je 0x4c7d4
movl %r8d, %r15d
movq %rcx, %r13
movq %rdi, %rbp
movq %rbx, (%rsp)
leal -0x1(%r15), %ebx
testl %ebx, %r8d
jne 0x4c839
movl $0x18, %edi
callq 0x8290
movq %rax, %r12
movq %rbp, %rdi
movq %r14, %rsi
movq %r13, %rdx
callq 0x4ca18
movq %rax, %r13
movl $0x18, %edi
callq 0x8290
xorl %ecx, %ecx
cmpl $0x2, %r15d
movq (%rsp), %rbx
jl 0x4c760
xorl %ecx, %ecx
movl %r15d, %edx
shrl %edx
incl %ecx
cmpl $0x3, %r15d
movl %edx, %r15d
ja 0x4c753
movl $0x1, (%rax)
movb $0x1, 0x4(%rax)
movl %ecx, 0x8(%rax)
movq $0x0, 0x10(%rax)
movb $0x0, (%r12)
movl $0x0, 0x4(%r12)
movq %r13, 0x8(%r12)
movq %rax, 0x10(%r12)
movl $0x28, %edi
callq 0x8290
movq %rax, %r15
movq %rax, %rdi
movq %r14, %rsi
movl $0x1, %edx
callq 0xa41e
leaq 0x40d3f(%rip), %rax     # 0x8d4f0
leaq 0x10(%rax), %rcx
movq %rcx, (%r15)
movw $0x0, 0x14(%r15)
movq %rbx, 0x18(%r15)
movq %r12, 0x20(%r15)
movb $0x1, %bl
movq %r15, %rdi
callq *0x28(%rax)
jmp 0x4c9cf
movl $0x28, %edi
callq 0x8290
movq %rax, %r15
movl $0x18, %edi
callq 0x8290
movq %rax, %r12
movb $0x1, (%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x4(%rax)
movl $0x0, 0x14(%rax)
movq %r15, %rdi
movq %r14, %rsi
movl $0x1, %edx
callq 0xa41e
leaq 0x40cda(%rip), %rax     # 0x8d4f0
leaq 0x10(%rax), %rcx
movq %rcx, (%r15)
movw $0x0, 0x14(%r15)
movq %rbx, 0x18(%r15)
movq %r12, 0x20(%r15)
movb $0x1, %bl
movq %r15, %rdi
callq *0x28(%rax)
jmp 0x4c9cf
leal -0x2(%r15), %eax
testl %eax, %ebx
je 0x4c855
leal 0x1(%r15), %ebx
testl %r15d, %ebx
je 0x4c916
xorl %ebx, %ebx
jmp 0x4c9cf
movq %rbp, %rdi
movq %r14, %rsi
movq %r13, %rdx
callq 0x4ca18
movq %rax, %r13
movl $0x18, %edi
callq 0x8290
movq %rax, %r12
movl $0x18, %edi
callq 0x8290
xorl %ecx, %ecx
cmpl $0x3, %r15d
jl 0x4c894
xorl %ecx, %ecx
movl %ebx, %edx
shrl %edx
incl %ecx
cmpl $0x3, %ebx
movl %edx, %ebx
ja 0x4c889
movl $0x1, (%rax)
movb $0x1, 0x4(%rax)
movl %ecx, 0x8(%rax)
movq $0x0, 0x10(%rax)
movb $0x0, (%r12)
movl $0x0, 0x4(%r12)
movq %r13, 0x8(%r12)
movq %rax, 0x10(%r12)
movl $0x38, %edi
callq 0x8290
movq %rax, %r15
movq %rax, %rdi
movq %r14, %rsi
movl $0x1, %edx
callq 0xa41e
movq (%rsp), %rdx
leaq 0x40ba7(%rip), %rax     # 0x8d490
leaq 0x10(%rax), %rcx
movq %rcx, (%r15)
movl $0x0, 0x14(%r15)
movb $0x0, 0x18(%r15)
movq %rdx, 0x20(%r15)
movq %r13, 0x28(%r15)
movq %r12, 0x30(%r15)
movb $0x1, %bl
movq %r15, %rdi
callq *0x28(%rax)
jmp 0x4c9cf
movq %rbp, %rdi
movq %r14, %rsi
movq %r13, %rdx
callq 0x4ca18
movq %rax, %r13
movl $0x18, %edi
callq 0x8290
movq %rax, %r12
movl $0x18, %edi
callq 0x8290
xorl %ecx, %ecx
testl %r15d, %r15d
jle 0x4c952
movl %ebx, %edx
shrl %edx
incl %ecx
cmpl $0x3, %ebx
movl %edx, %ebx
ja 0x4c947
movl $0x1, (%rax)
movb $0x1, 0x4(%rax)
movl %ecx, 0x8(%rax)
movq $0x0, 0x10(%rax)
movb $0x0, (%r12)
movl $0x0, 0x4(%r12)
movq %r13, 0x8(%r12)
movq %rax, 0x10(%r12)
movl $0x38, %edi
callq 0x8290
movq %rax, %r15
movq %rax, %rdi
movq %r14, %rsi
movl $0x1, %edx
callq 0xa41e
movq (%rsp), %rdx
leaq 0x40ae9(%rip), %rax     # 0x8d490
leaq 0x10(%rax), %rcx
movq %rcx, (%r15)
movl $0x2, 0x14(%r15)
movb $0x0, 0x18(%r15)
movq %rdx, 0x20(%r15)
movq %r13, 0x28(%r15)
movq %r12, 0x30(%r15)
movb $0x1, %bl
movq %r15, %rdi
callq *0x28(%rax)
movl %ebx, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x4c9f2
jmp 0x4c9f2
jmp 0x4c9e6
movq %rax, %rbx
movl $0x38, %esi
jmp 0x4ca07
jmp 0x4c9ff
movq %rax, %rbx
movl $0x18, %esi
movq %r12, %rdi
jmp 0x4ca0a
movq %rax, %rbx
movl $0x28, %esi
movq %r15, %rdi
callq 0x82a0
movq %rbx, %rdi
callq 0x8540
nop