LLVM后端只能将2个alloca升级到寄存器,即使存在未使用的物理寄存器
我在一个CPU仿真器项目中使用MCJIT,IR主要是使用IRBuilder生成的,它可以工作,但是性能比我们以前的JIT差。我比较了生成的代码,主要问题与寄存器的使用有关。在LLVM中,我通过将alloca放在IR函数的开头,将5个局部变量提升到寄存器,在运行createPromoteMemoryToRegisterPass后,所有5个变量都提升到优化IR中具有PHI节点的虚拟寄存器。但在最终的X64二进制代码中,只有2个变量升级到寄存器,其他3个变量溢出。代码中还有两个寄存器未使用R11、R12 我尝试使用llc用贪婪/pbqp编译优化的IR,结果是一样的,只有2个得到提升 我在这个问题上花了很多时间,任何建议都将不胜感激 代码段: 优化前的IR:LLVM后端只能将2个alloca升级到寄存器,即使存在未使用的物理寄存器,llvm,Llvm,我在一个CPU仿真器项目中使用MCJIT,IR主要是使用IRBuilder生成的,它可以工作,但是性能比我们以前的JIT差。我比较了生成的代码,主要问题与寄存器的使用有关。在LLVM中,我通过将alloca放在IR函数的开头,将5个局部变量提升到寄存器,在运行createPromoteMemoryToRegisterPass后,所有5个变量都提升到优化IR中具有PHI节点的虚拟寄存器。但在最终的X64二进制代码中,只有2个变量升级到寄存器,其他3个变量溢出。代码中还有两个寄存器未使用R11、R1
define void @emulate(%struct.fpga_cpu* %pcpu, i64 %pc_arg, i64 %r0_arg, i64 %r1_arg, i64 %r2_arg, i64 %r3_arg) {
entry:
%0 = alloca i64
%1 = alloca i64
%2 = alloca i64
%3 = alloca i64
%4 = alloca i64
%5 = alloca i64
store i64 %r0_arg, i64* %2
store i64 %r1_arg, i64* %3
store i64 %r2_arg, i64* %4
store i64 %r3_arg, i64* %5
store i64 %pc_arg, i64* %0
....
}
define void @emulate(%struct.fpga_cpu* %pcpu, i64 %pc_arg, i64 %r0_arg, i64 %r1_arg, i64 %r2_arg, i64 %r3_arg) {
....
%.01662 = phi i64 [ %r2_arg, %entry ], [ %.21664, %cmp ]
%.01648 = phi i64 [ %r1_arg, %entry ], [ %.21650, %cmp ]
%.01640 = phi i64 [ %r0_arg, %entry ], [ %.21642, %cmp ]
%.01636 = phi i64 [ %r3_arg, %entry ], [ %.21638, %cmp ]
%.0 = phi i64 [ %pc_arg, %entry ], [ %.2, %cmp ]
....
}
优化后的IR:
define void @emulate(%struct.fpga_cpu* %pcpu, i64 %pc_arg, i64 %r0_arg, i64 %r1_arg, i64 %r2_arg, i64 %r3_arg) {
entry:
%0 = alloca i64
%1 = alloca i64
%2 = alloca i64
%3 = alloca i64
%4 = alloca i64
%5 = alloca i64
store i64 %r0_arg, i64* %2
store i64 %r1_arg, i64* %3
store i64 %r2_arg, i64* %4
store i64 %r3_arg, i64* %5
store i64 %pc_arg, i64* %0
....
}
define void @emulate(%struct.fpga_cpu* %pcpu, i64 %pc_arg, i64 %r0_arg, i64 %r1_arg, i64 %r2_arg, i64 %r3_arg) {
....
%.01662 = phi i64 [ %r2_arg, %entry ], [ %.21664, %cmp ]
%.01648 = phi i64 [ %r1_arg, %entry ], [ %.21650, %cmp ]
%.01640 = phi i64 [ %r0_arg, %entry ], [ %.21642, %cmp ]
%.01636 = phi i64 [ %r3_arg, %entry ], [ %.21638, %cmp ]
%.0 = phi i64 [ %pc_arg, %entry ], [ %.2, %cmp ]
....
}
X64代码:
emulate:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $72, %rsp
movq %r9, 56(%rsp) # 8-byte Spill
movq %r8, 64(%rsp) # 8-byte Spill
movq %rcx, %r15
movq %rdx, %r13
movq %rdi, %r14
....
r2_arg, r3_arg spill, but R11,R12 are never used.
....
retq
我相信一个小的可复制的例子可以让你的问题更容易理解。很抱歉我的问题含糊不清,由于公司的政策,我不能在这里发布工作代码。这里的基本思想是让模拟CPU的寄存器变量存在于X64寄存器中。