优化器
RedScript 会在写出最终 datapack 之前执行多轮编译期优化。目标很直接:减少命令数量、删掉不可达 helper、并在不改变语义的前提下压缩热路径。
优化等级
可以用下面这些 CLI 参数控制优化器强度:
| 参数 | 含义 |
|---|---|
--no-dce | 只关闭死代码消除。其他仍然启用的优化照常运行。 |
-O0 | 关闭优化。最适合调试生成结果。 |
-O1 | 开启标准、安全的优化集合。开发期的默认推荐。 |
-O2 | 开启完整优化流水线,包括更激进的内联与循环清理。 |
典型用法:
redscript compile main.mcrs -O0
redscript compile main.mcrs -O1 --stats
redscript compile main.mcrs -O2 --no-dceDCE
死代码消除会移除从任何公共入口都无法到达的函数。
高层规则:
- 名称不以下划线
_开头的函数会被视为 public,并生成到输出中。 - 以下划线开头的函数会被视为 private helper;如果不可达就可能被删除。
@load、@tick、@on(...)、@coroutine等装饰过的函数会自动保留。@keep可以覆盖 DCE,强制保留函数。
fn start() {
_helper()
}
fn _helper() {
say("reachable")
}
fn _dead() {
say("removed by DCE")
}
@keep
fn _manual_entry() {
say("kept for manual /function use")
}当你想检查所有 helper 是否被输出,或在调试可达性问题时,可以使用 --no-dce。
常量折叠
常量折叠会在所有输入都已知时,于编译期直接计算表达式。
典型例子:
let ticks_per_minute: int = 20 * 60
let doubled: int = 8 + 8
let ready: bool = 3 > 1折叠后,生成代码会直接使用计算好的常量,而不是在运行时重复计算。
它最适合:
- 字面量算术
- 简单布尔条件
- 固定大小的循环边界
- 编译期可确定的配置值
@inline
@inline 是给热路径上极小 helper 的性能提示。
@inline
fn clamp_zero(x: int) -> int {
if (x < 0) {
return 0
}
return x
}当优化器接受这个提示时,它会在后续清理阶段之前把函数体直接替换到调用点。这样通常能进一步触发常量折叠、复制传播和死分支删除。
使用建议:
- 只给很小的 helper 用
- 主要用于热循环
- 不要拿它替代清晰的结构
复制传播
复制传播会在安全时,用原值替换临时别名。
fn award(points: int) {
let p = points
let value = p
scoreboard_add(@s, "score", value)
}传播完成后,优化器通常能把这串别名折叠掉,让生成代码直接使用 points。
这很重要,因为 RedScript 把高层表达式 lowering 成命令时,经常会产生短生命周期临时值。先把这些副本传播掉,后续优化会更容易。
循环展开
循环展开会把小而固定次数的循环复制成直线代码,让运行时不必每轮都付出分支成本。
let i: int = 0
while (i < 4) {
say("tick")
i = i + 1
}在 -O2 下,如果循环次数是很小的编译期常量,优化器可能会直接展开循环体。它最适合:
- 循环上界是很小的常量
- 循环体本身很短
- 去掉循环控制开销后,后续优化会更简单
很大或依赖运行时数据的循环一般不会展开。
基本块合并
基本块合并会在控制流是线性的情况下,把相邻基本块拼接起来,不再保留多余的跳转边界。
实际效果通常是:
- 生成 helper 之间的跳转更少
- 内联后的控制流链更短
- 常量条件折叠后,输出更干净
这个 pass 一般会在常量折叠、复制传播之后收益最大,因为前面的简化很容易制造出只有单一路径的 trivial block。
这些 Pass 如何配合
从高层看,优化器流水线大致会这样工作:
- 先简化常量和复制
- 再按条件内联热路径小函数
- 清理循环,并合并直线型 block
- 最后用 DCE 删除不可达代码
你通常不需要记住精确顺序。真正重要的是:写小而清晰的 helper、谨慎使用装饰器,并为当前任务选对优化等级。
实用建议
- 对照源码和生成结果时,用
-O0。 - 日常开发用
-O1。 - 发布大型 datapack 或热路径密集逻辑前,用
-O2。 - 需要保留所有 helper 以便检查时,用
--no-dce。 - 想快速评估优化器效果时,用
--stats。