Go 编译器中的寄存器分配 | Red Hat 开发者

主要观点:作为 GCC 寄存器分配器的维护者,对各种工业编译器的寄存器分配器感兴趣,而 Go 编译器的寄存器分配器文档不足,需深入研究其源代码。Go 的寄存器分配器基于 SSA,包含多个组件,如关键边消除、Flagalloc、Live 分析、regalloc 和 stackalloc 等。regalloc 是最大最复杂的部分,通过多种策略处理 SSA 值、Phis 等,还涉及栈槽分配等。Go RA 利用大量数据,采用特定算法,存在一些优势如代码量小、速度快、栈槽共享较好等,也有缺乏全局视图、Phi 处理复杂、分配单元精细、RA 后 SSA 无效等缺点。

关键信息:

  • Go 寄存器分配器基于 SSA,包含多个组件及操作,如关键边消除时创建特定基本块等。
  • regalloc 以 SSA 值为最小分配单元,按 CFG 预序处理基本块,跟踪值位置等。
  • 处理 Phis 时要确保值在同一位置,可能创建值副本等。
  • 栈槽分配考虑值生命周期,利用冲突图优化。
  • Go RA 利用多种数据结构,有特定指令描述和属性。
  • 处理 SSA 时采用多种技术保留 SSA,如使用特殊操作等,但 RA 后 SSA 非纯 SSA。
  • RA 算法总结及与线性扫描等的关系。
  • Go RA 假设所有寄存器在调用中被破坏,使用调用 ABI 会影响代码生成。

重要细节:

  • 关键边消除时在控制流图边缘插入指令,确保结果代码正确。
  • Flagalloc 处理条件代码值分配,Live 分析基于寄存器分配结果为垃圾收集生成数据。
  • regalloc 处理基本块时考虑多种因素,如选择前驱、分配寄存器等,还处理值溢出等情况。
  • 栈槽分配可共享不同 SSA 值的栈槽,利用冲突图优化。
  • Go RA 数据结构及指令描述的特点,如 64 位寄存器掩码等。
  • 处理 SSA 后 SSA 非纯 SSA 及相关示例。
  • RA 算法的具体步骤及各部分的作用。
  • 调用 ABI 对代码生成的影响及相关示例。
阅读 10
0 条评论