BURG(自底向上重写生成器)

概述

BURG 是编译器后端指令选择的经典工具。

它的核心思想是:给定一棵 IR 表达式树和一组带代价的机器指令模式,用动态规划找到覆盖整棵树的最小代价方案。

BURG 要解决什么问题?

问题场景

假设我们有以下 IR 表达式树(表示 (a + 5) * b):

其中:

  • a 是内存中的变量
  • b 是内存中的变量
  • 5 是常量

机器提供以下指令(每条指令 = 一个模式 + 代价):

规则 模式 指令 代价
R1 add(reg, reg) ADD rd, rs1, rs2 1
R2 add(reg, imm) ADDI rd, rs1, imm 1
R3 mul(reg, reg) MUL rd, rs1, rs2 3
R4 load(addr) LOAD rd, addr 2
R5 const(imm) LOADI rd, imm 1

目标:用这些指令覆盖整棵树,总代价最小。

BURG 的两步算法

Label 阶段(自底向上)

从叶子到根,给每个节点标注"用哪条规则、代价是多少"。

节点 a(叶子,内存变量):

text 复制代码
规则 R4:load(addr)
代价 = 2

标注:a 的最优代价 = 2(用 LOAD)

节点 5(叶子,常量):

text 复制代码
规则 R5:const(imm)
代价 = 1

标注:5 的最优代价 = 1(用 LOADI)

节点 +(内部节点,子节点是 a 和 5):

text 复制代码
候选规则 1:R1(add(reg, reg))
  需要 a 在寄存器中,5 在寄存器中
  代价 = cost(a) + cost(5) + 1 = 2 + 1 + 1 = 4

候选规则 2:R2(add(reg, imm))
  需要 a 在寄存器中,5 作为立即数
  代价 = cost(a) + 1 = 2 + 1 = 3

取最小:代价 = 3(用 ADDI)
标注:+ 的最优代价 = 3

节点 b(叶子,内存变量):

text 复制代码
规则 R4:load(addr)
代价 = 2

标注:b 的最优代价 = 2

节点 * (根节点,子节点是 + 和 b):

text 复制代码
候选规则:R3(mul(reg, reg))
  需要 + 的结果在寄存器中,b 在寄存器中
  代价 = cost(+) + cost(b) + 3 = 3 + 2 + 3 = 8

标注:* 的最优代价 = 8

Label 阶段结果汇总:

节点 最优规则 代价
a LOAD 2
5 LOADI 1
+ ADDI 3
b LOAD 2
* MUL 8

Select 阶段(自顶向下)

从根到叶,每步选择到达目标最便宜的路径。

根节点*:

text 复制代码
选择规则:R3(MUL)
需要:+ 的结果在寄存器中,b 在寄存器中

节点 +(被 * 需要,必须在寄存器中):

text 复制代码
选择规则:R2(ADDI)
需要:a 在寄存器中,5 作为立即数

节点 a(被 + 需要,必须在寄存器中):

text 复制代码
选择规则:R4(LOAD)
生成:LOAD r1, a

节点 5(被 + 作为立即数使用):

text 复制代码
不单独生成指令,直接作为 ADDI 的立即数

节点 b(被 * 需要,必须在寄存器中):

text 复制代码
选择规则:R4(LOAD)
生成:LOAD r2, b

节点 +(生成指令):

text 复制代码
生成:ADDI r1, r1, 5

节点 * (生成指令):

text 复制代码
生成:MUL r3, r1, r2

最终生成的汇编

assembly 复制代码
LOAD r1, a        ; 代价 2
ADDI r1, r1, 5    ; 代价 1
LOAD r2, b        ; 代价 2
MUL r3, r1, r2    ; 代价 3
; 总代价 = 8

验证:如果不用 ADDI 而用 ADD,需要额外加载 5 到寄存器:

assembly 复制代码
LOAD r1, a        ; 2
LOADI r4, 5       ; 1
ADD r1, r1, r4    ; 1
LOAD r2, b        ; 2
MUL r3, r1, r2    ; 3
; 总代价 = 9

BURG 选择了代价 8 的方案,比 9 更优。

BURG 与 Maximal Munch 的区别

算法 策略 最优性
Maximal Munch 从根到叶,每次选覆盖最多节点的瓦片 贪心,不一定最优
BURG 从叶到根计算代价,再从根到叶选择 动态规划,保证最优

Maximal Munch 可能错过的例子

假设树是 (a + 5) * b,但规则是:

规则 模式 代价
R1 mul(add(reg, imm), reg) 4(一条指令完成加法和乘法)
R2 add(reg, imm) 1
R3 mul(reg, reg) 3

Maximal Munch :从根 * 开始,最大瓦片是 R1(覆盖 * + + + 5),代价 4。

然后处理 a(LOAD,代价 2)和 b(LOAD,代价 2)。

总代价 = 4 + 2 + 2 = 8。

BURG:会计算所有可能组合,发现 R1 的总代价 8,而 R2 + R3 的总代价是 1 + 3 + 2 + 2 = 8。两者相同。

但如果 R1 的代价是 5,Maximal Munch 会选 R1(代价 5+2+2=9),而 BURG 会选 R2+R3(代价 8),更优。

结论:Maximal Munch 贪心,可能不是最优;BURG 用动态规划,保证最优。

BURG 的输入与输出

输入:模式描述

BURG 的输入是一个 .burg 文件,描述每条指令的模式和代价:

burg 复制代码
%term ADD=1 MUL=2 ADDI=3 LOAD=4 LOADI=5
%start reg

reg: ADD(reg, reg)    1
reg: ADDI(reg, imm)   1
reg: MUL(reg, reg)    3
reg: LOAD(addr)       2
reg: LOADI(imm)       1
  • %term:定义终结符(操作符)
  • %start reg:目标非终结符reg: ADD(reg, reg) 1:规则
  • "reg → ADD(reg, reg)",代价 1

输出:匹配器

BURG 生成一个 C/C++ 函数,输入是 IR 树,输出是最优覆盖方案:

c 复制代码
int burg_label(Node *node);   // Label 阶段
void burg_select(Node *node, int goal);  // Select 阶段

BURG 的完整工作流程

text 复制代码
输入:
  IR 树 + 模式描述(.burg 文件)

BURG 生成器:
  解析 .burg 文件
  生成状态机(自动机)
  生成 label() 和 select() 函数

编译器使用:
  ① 对 IR 树调用 label() → 每个节点标注最优规则和代价
  ② 对 IR 树调用 select() → 自顶向下选择规则,生成指令
  ③ 输出汇编代码

总结

概念 含义
BURG Bottom-Up Rewrite Generator,自底向上重写生成器
输入 模式描述(.burg 文件),每条模式有代价
输出 匹配器(label + select 函数)
Label 自底向上遍历,给每个节点标注最优规则和代价
Select 自顶向下遍历,每步选择到达目标最便宜的路径
核心算法 动态规划,保证找到最小代价覆盖
与 Maximal Munch 的区别 Maximal Munch 贪心,BURG 动态规划保证最优

一句话:BURG 是编译器指令选择的经典工具。

它把"用机器指令覆盖 IR 树"转化为"动态规划求最小代价覆盖",通过 Label(自底向上计算代价)和 Select(自顶向下选择规则)两步,保证生成的指令序列总代价最小。

相关推荐
灵动的艺术20 小时前
如一 Agent 架构解读(二十四):Agent 高效率低成本思考
人工智能·agent·如一
Xxtaoaooo21 小时前
双11避坑:我用 WorkBuddy + TextIn xParse 做了个「避坑对比台」,商品详情图丢进去,参数矛盾自动现形
人工智能·1024程序员节·textin·workbuddy·ai数据层基础设施
昵称画21 小时前
交接班记录电子化:三班之间的信息不漏
开发语言·数据库·人工智能·低代码·php
老歌老听老掉牙21 小时前
WorkBuddy 如何接入 PrePoMax 的 MCP 服务器
服务器·ai·mcp
Navicat中国21 小时前
将 Navicat 的 AI 助手连接到本地 LLM
人工智能·chatgpt
“AI国潮设计-小江”21 小时前
【AIGC实战】Python+SDXL批量生成“潮汕英歌舞不倒翁”IP | 角色一致性与多场景融合方案,附完整代码
开发语言·人工智能·python·prompt·aigc
点PY21 小时前
WeDetect论文精读
人工智能
CCC:CarCrazeCurator1 天前
稀疏奖励 vs 稠密奖励:强化学习中的反馈带宽权衡
人工智能·深度学习·机器人
Linux_cy1 天前
服务器管理工具哪个好用?我用了七八个
运维·服务器·javascript·python·ssh·面板·gmssh
骑着蜗牛撵大象3271 天前
语音变分录、规则挡幻觉:拆解开源 AI 记账系统 Smart Ledger 的全栈设计
人工智能·ai·架构·js·数据校验