InstructionSelect

此Pass将通用机器指令转换为等效的目标特定指令。它自底向上遍历 MachineFunction,在定义之前选择使用,从而实现简单的死代码消除。

API: InstructionSelector

目标实现了 InstructionSelector 类,其中包含目标特定的选择逻辑。

实例由子目标提供,以便它可以根据子目标特性专门化选择器(例如,向量选择器覆盖通用公共选择器的部分)。我们可能还希望通过 MachineFunction 对其进行参数化,以根据函数属性(如 optsize)启用选择器变体。

简单的 API 包括

virtual bool select(MachineInstr &MI)

此目标提供的方法负责将可能通用的 MI 转换为完全目标特定的等效指令(通过修改或替换)。它还负责将 gvregs 约束到适当的寄存器类别,以及将 COPY 指令传递给寄存器分配器。

InstructionSelector 可以通过遍历 vreg 操作数的使用-定义链,将其他指令折叠到选定的 MI 中。由于 GlobalISel 是全局的,因此这种折叠可以跨基本块发生。

SelectionDAG 规则导入

TableGen 将导入 SelectionDAG 规则并提供以下函数来执行它们

bool selectImpl(MachineInstr &MI)

可以使用 --stats 选项来确定成功导入的规则的比例。最简单的方法是从 ninja -v 复制 -gen-globalisel tablegen 命令并对其进行修改。

同样,可以使用 --warn-on-skipped-patterns 选项来获取规则未导入的原因。这可以用于关注最重要的拒绝原因。

PatLeaf 谓词

PatLeafs 无法导入,因为它们的 C++ 是用 SDNode 对象实现的。处理立即数谓词的 PatLeafs 应根据需要替换为 ImmLeafIntImmLeafFPImmLeaf

对于其他 PatLeafs,没有标准答案。一些标准谓词已被烘焙到 TableGen 中,但这通常不应该这样做。

自定义 SDNodes

自定义 SDNodes 应使用 GINodeEquiv 映射到目标伪指令。这将导致指令选择器导入它们,但您还需要确保在指令选择器之前将目标伪指令引入到 MIR 中。任何先前的 Pass 都是合适的,但 legalizer 将是一个特别常见的选择。

ComplexPatterns

ComplexPatterns 无法导入,因为它们的 C++ 是用 SDNode 对象实现的。GlobalISel 版本应使用 GIComplexOperandMatcher 定义,并使用 GIComplexPatternEquiv 映射到 ComplexPattern。

以下谓词对于移植 ComplexPattern 非常有用

  • isBaseWithConstantOffset() - 检查 base+offset 结构

  • isOperandImmEqual() - 检查特定常量

  • isObviouslySafeToFold() - 检查指令无法下沉并折叠到另一个指令的原因。

C++ 实现有一些重要的要点

  • 不要在谓词中修改 MIR

  • Renderer lambda 应该按值捕获,以避免 use-after-free。它们将在谓词返回后使用。

  • 仅在 renderer lambda 中创建指令。GlobalISel 不会清理您创建但未使用的内容。