MachineCombiner

一个基于机器级 trace 度量,将多条指令合并为更高效指令序列的 LLVM 机器指令合并优化 Pass。对应的中端 Pass 就是 InstCombiner。但是该 Pass 的逻辑比较简单,只有六百多行。
基本概念如下:

  • 目标:在不延长关键路径、不增加资源压力(或优化代码体积)的前提下,将可组合的指令序列(如 MUL+ADD)替换为单条复合指令(如 MADD),以提高生成代码的执行效率或减小代码体积。
  • 依赖分析:利用 MachineTraceMetrics 提供的“深度(Depth)”、“延迟(Latency)”和“Slack”信息,评估新旧指令序列对关键路径的影响。
  • 资源分析:基于调度模型(TSchedModel)和硬件资源模型,比较合并前后资源使用长度(Resource Length)。
  • 启发式:优先尝试减少关键路径深度,再尝试减少资源长度;在代码大小优化模式下,只要新序列短即替换;在循环中若检测到吞吐模式也可替换。
    最简单的例子就是一个 FMA 指令:
; 原始序列
MUL   r1, r2, r3       ; 乘法
ADD   r4, r1, r5       ; 加法(Root)

; 合并后
MADD  r4, r2, r3, r5   ; 乘加复合指令

这个 Pass 也是可以调参的:
是的,通过命令行选项控制:

  • -machine-combiner-inc-threshold=<N>:基本块指令数超过 N 时启用增量深度更新(默认为 500)。
  • -machine-combiner-dump-subst-intrs:打印被删除与插入的指令序列以便调试。
  • -machine-combiner-verify-pattern-order:开启后将验证所有模式按延迟改进程度升序排列,以检测子最优模式顺序。
// The motivating example is:  
//  
//     MUL  Other        MUL_op1 MUL_op2  Other  
//      \    /               \      |    /  
//      ADD/SUB      =>        MADD/MSUB  
//      (=Root)                (=NewRoot)

该 Pass 依赖的分析还是比较多的:

  • MachineLoopInfoWrapperPass
  • MachineTraceMetricsWrapperPass
  • ProfileSummaryInfoWrapperPass
  • LazyMachineBlockFrequencyInfoPass

这个 TraceMetrics 是一个用于在后端收集机器指令级“静态执行轨迹”信息的分析 Pass,为后续的 MachineCombiner 等优化提供关键路径、延迟、Slack 和资源压力等度量。

主函数是combineInstructions,逻辑如下,在给定 MBB(机器基本块)中,对每条机器指令:

  • 查询目标定义的指令组合模式;
  • 枚举每种组合方式;
  • 使用 TraceMetrics 判断是否可替换(不会恶化关键路径/资源);
  • 若合适,则插入优化指令,删除原始序列。