LLVM中XXXISelDAGToDAG与XXXISelLowering的核心区别
[Target]ISelLowering.cpp 与 [Target]ISelDAGToDAG.cpp 的分工边界 两个文件同属LLVM后端SelectionDAG指令选择流程,但对应完全独立的先后环节,核心差异是处理的DAG抽象层级、工作目标完全不同,不存在功能重叠。
[Target]ISelLowering.cpp 核心职责
这个文件运行在DAG合法化阶段,位于正式指令匹配流程之前,负责把前端生成的目标无关通用SelectionDAG,调整为目标架构可支持的合法形态,核心工作包括:
- 操作合法化:替换、拆分目标硬件原生不支持的通用操作,比如目标无原生浮点除法单元时,将通用
FDIV节点替换为软浮点除法调用序列;无原生64位加法时,将i64 ADD拆分为两个32位加法加进位处理的节点序列 - 类型合法化:转换目标寄存器文件不支持的数据类型,比如将i64值拆分为两个i32寄存器承载,将超过单寄存器宽度的内存访问拆分为多次小宽度访存操作
- 自定义DAG合并优化:在合法化阶段提前组合符合目标特性的操作,比如将独立的乘法、加法节点合并为乘加(MAC)操作节点,匹配目标的特殊寻址模式生成对应地址计算节点
- ABI相关处理:实现函数调用参数传递、返回值处理、栈帧操作相关的DAG节点生成,所有和平台调用约定相关的DAG调整基本都在这个文件完成
这个阶段输出的DAG,所有节点的操作类型、数据类型都是目标硬件可支持的,但还没有绑定到任何具体的目标机器指令。
[Target]ISelDAGToDAG.cpp 核心职责
这个文件运行在指令选择阶段,位于DAG合法化全流程完成之后,负责把合法形态的DAG节点映射为目标真实存在的机器指令,核心工作包括:
- 自定义指令选择:将合法DAG上的通用SDNode、目标自定义SDNode,匹配转换为对应具体机器指令的
MachineSDNode - 覆盖TableGen无法处理的复杂匹配场景:比如需要跨多个节点匹配的特殊指令、带运行时谓词判断的指令选择、复杂基址+变址+偏移寻址模式的匹配
- 指令选择阶段的局部调整:匹配到特殊指令时,按需插入必要的寄存器拷贝、标志位设置、操作数调整节点,保证匹配出的指令符合硬件的操作数约束
这个阶段输出的DAG,所有节点都已经和目标架构的具体机器指令一一对应,后续会直接进入指令调度、寄存器分配流程。
核心差异总结
- 执行顺序:
ISelLowering.cpp逻辑先执行,属于DAG合法化环节;ISelDAGToDAG.cpp逻辑后执行,属于指令选择环节 - 工作目标:前者的核心是把DAG"改成目标能支持的形态",不需要关心具体指令的编码、寄存器约束;后者的核心是把合法DAG"翻译成真实的目标指令",必须严格遵循指令的操作数、寄存器要求
- 处理对象:前者处理的是未绑定机器指令的通用/半通用SDNode,以拆分、替换、合并节点为主要操作;后者处理的是已经合法的SDNode,以模式匹配、映射指令为主要操作
内容的提问来源于stack exchange,提问作者Mannar Amuthan
相关产品推荐
相关产品推荐

