LLVM目标无关代码生成器(下)(译)
内容提要
本文介绍了LLVM目标无关代码生成器的工作原理,包括指令选择的过程和使用的SelectionDAG。还讨论了寄存器分配、指令解析和指令别名处理等内容。
延伸解读
指令选择:从IR到机器指令的关键步骤
LLVM使用基于SelectionDAG的指令选择器,将LLVM IR转换为目标机器指令。该过程包括构建初始DAG、优化、类型合法化、操作合法化等步骤,最终生成机器指令DAG。SelectionDAG是一种有向无环图,节点表示操作,边表示数据或控制依赖。合法化确保只使用目标机支持的操作和类型。这一阶段是代码生成的核心,直接影响生成代码的质量。
寄存器分配:虚拟寄存器到物理寄存器的映射
寄存器分配将无限虚拟寄存器映射到有限物理寄存器,可能引起溢出。LLVM提供多种分配器:Fast用于调试,Basic用于基准,Greedy为默认,PBQP基于数学模型。分配前需计算活跃区间,确定变量冲突。物理寄存器用整数表示,虚拟寄存器由createVirtualRegister创建。分配器需处理pre-colored寄存器约束,并支持二地址指令转换和SSA销毁。
指令别名处理:简化汇编器实现
LLVM支持独立汇编器,指令别名处理是关键。别名将不同文本形式的指令标准化,包括助记符别名和指令别名。助记符别名无条件重映射助记符,可依赖子目标;指令别名在匹配时根据操作数生成特定指令,支持操作数重排和固定操作数。别名可简化汇编代码编写,提高可读性。指令打印器可自动输出别名,但需注意别名可能改变指令语义。
Q&A
LLVM的指令选择过程具体包含哪些步骤?
LLVM的指令选择过程包含以下步骤:构建初始DAG、优化SelectionDAG、类型合法化、再次优化SelectionDAG、操作合法化、再次优化SelectionDAG、从DAG做指令选择、SelectionDAG调度和指令序列化。
SelectionDAG中的合法化是什么意思?
合法化是指将只使用目标机支持的操作和类型的DAG转换为合法DAG的过程。类型合法化清除不支持的类型,操作合法化清除不支持的操作。
LLVM中有哪些寄存器分配器?
LLVM提供了四种寄存器分配器:Fast(debug构建默认,基本块级别)、Basic(增量式,启发式)、Greedy(默认,高度调优,全局活跃范围分割)、PBQP(基于PBQP模型)。
LLVM如何处理二地址指令?
LLVM使用TwoAddressInstructionPass将三地址指令转化为二地址指令,该Pass在寄存器分配前调用。例如,%a = ADD %b %c 会被转化为 %a = MOVE %b; %a = ADD %a %c。
指令别名处理有哪些类型?
指令别名处理包括助记符别名和指令别名。助记符别名是无条件重映射助记符,指令别名在匹配时提供新形式来匹配特定指令生成。
LLVM中物理寄存器和虚拟寄存器有什么区别?
物理寄存器用1~1023的整数表示,在TargetRegisterInfo.td中预定义,不能由开发者创建;虚拟寄存器用整数表示,不同虚拟寄存器从不共享编号,可通过MachineRegisterInfo::createVirtualRegister()创建。