每日Pass简介——MachineInstrBundle
MachineInstrBundle
这是一个工具类 Pass,它主要处理 Machine Instruction Bundles(机器指令捆绑) 的构造、解析与分析。换句话说,它负责在 LLVM 后端的代码生成阶段,对一系列底层机器指令进行组合、打包与拆包,从而支持目标平台(尤其是 VLIW、压缩指令等架构)对“指令包(bundle)”的要求。
该 Pass 涉及一些 VLIW 相关的概念:
概念 | 说明 |
---|---|
Instruction Bundling | 某些架构(如 VLIW、Itanium)要求将多个指令打包为一个单元调度或发射,称为指令捆绑 |
Dead/Kill/Undef Flags | 注册使用的生命周期属性分析,用于设置寄存器是否已失效或终止使用等优化标记 |
Subregisters / Lane Masks | 对支持 SIMD/SVE 等子寄存器体系结构,lane mask 用于追踪特定位宽的寄存器使用 |
支持 VLIW 架构的处理器如 Hexagon/Itanium/AArch64 都会触发这个 Pass:
- LLVM 后端生成的指令流中,若某些指令被标记为 InsideBundle
- 在调度/选择指令阶段调用 finalizeBundles:
- 自动插入一个 BUNDLE 指令
- 设置寄存器之间的 IsInternalRead、Dead 等标志位
- 在稍后的阶段(如 MachineVerifier 或 Emit)通过 UnpackMachineBundles 还原为原始指令流进行进一步优化或发射
原始:
%r1 = ADD %r2, %r3
%r4 = MUL %r1, %r5
最终 bundle:
BUNDLE
%r1 = ADD %r2, %r3 <-- 被标记为内部定义
%r4 = MUL %r1, %r5 <-- %r1 是 InternalRead
Pass 仅仅三百多行,主要实现下面两个逻辑:
1. finalizeBundle/finalizeBundles
功能:构造 BUNDLE 指令包围一组指令 + 更新相关寄存器信息
核心逻辑:
- 插入一个新的 BUNDLE 指令(使用 BuildMI(…) 构造)
- 扫描包内所有指令,分析其 MachineOperand:
- 寄存器若在 bundle 中定义且被其他指令使用 → 标记为 IsInternalRead
- 若使用了 bundle 外部的寄存器 → 加入到 BUNDLE 的 use 集中
- 死/杀/undef 标记也被统一合并到 bundle 头指令
- 还会设置 FrameSetup 等函数调用相关标志(在 prologue/epilogue 场景下)
2. UnpackMachineBundles
功能:恢复为原始指令流,去掉 BUNDLE 和 InsideBundle 标记
实现步骤:
- 遍历所有指令,遇到 isBundle() 类型的指令
- 将之后所有带 isBundledWithPred() 标记的指令解除捆绑
- 移除 IsInternalRead
- 删除 BUNDLE 指令本身
评论