最近有计划给组内的同事做一个关于 moonbit 的分享也因此想介绍一下编译优化这部分。所以想请问一下 moonbit compiler 尝试了哪些优化?
我自己着手看了一下,应该是有类似 LTO 的全局 DCE以及 closure 的逃逸分析。想问一下还有哪些~,谢谢
目前编译器大概十个pass左右。
常见的优化都是有的,high level IR 主要缺失的是CSE, autovec, 比较有特色的是控制流优化,Moonbit整个项目立项昨天刚好一年整,后面这些都会补上的
感谢 hongbo 老师回复。
我自己写了一些 example 然后 compile to wat,观察 wat,似乎暂时没找到类似 constant propagation/folding、function inlining、tco 的痕迹。
还是实际上有优化开关 ?
constant propagation/folding、tco 有的,你可以写下例子试下。
当然这些主要取决于inline做的怎么样,我们暂时把inline关了,好的inliner需要点时间
func bazz() -> Int {
x := 20
y := 22
x + y
}
func sum(n: Int) -> Int {
if n == 0 {
0
} else {
sum(n - 1) + n
}
}
func init {
println(sum(100) + bazz())
}
wat 中似乎没有看到 tco 和 constant propagation 的痕迹,是我姿势不对么 orz,还是 regression 了
(func $bazz.fn/6 (result i32) (local $x/21 i32) (local $y/22 i32)
(i32.const 20) (local.set $x/21) (i32.const 22) (local.set $y/22)
(local.get $x/21) (local.get $y/22) (i32.add))
(func $sum.fn/5 (param $n/23 i32) (result i32) (local.get $n/23)
(i32.const 0) (i32.eq)
(if (result i32) (then (i32.const 0))
(else (local.get $n/23) (i32.const 1) (i32.sub) (call $sum.fn/5)
(local.get $n/23) (i32.add))))
另一个 demo 里 folding 看到了~
https://try.moonbitlang.com/ 里面的 002_fib.mbt 可以看出来做了一些 tco
(func $fib2.aux.fn/6 (param $n/16 i32) (param $acc1/17 i32)
(param $acc2/18 i32) (result i32)
(block $join:19
(block $join:20
(block $join:21 (local.get $n/16) (i32.const 0) (i32.eq)
(if (result i32) (then (br $join:21))
(else (local.get $n/16) (i32.const 1) (i32.eq)
(if (result i32) (then (br $join:20)) (else (br $join:19)))))
(return))
(local.get $acc1/17) (return))
(local.get $acc2/18) (return))
(local.get $n/16) (i32.const 1) (i32.sub) (local.get $acc2/18)
(local.get $acc1/17) (local.get $acc2/18) (i32.add) (call $fib2.aux.fn/6))
你指的是这段么? 如果这段 wat 没理解错,block 相关是 pattern match 的跳转,好像没看出 tco,好像也没看出递归转循环部分…
还是说,是我 wasm 指令理解不到位 orz
我又看了一下,现在 web ide 上生成的 wat 文件里确实没有优化,之前是有的,会把整个 fib2.aux.fn 都优化掉,可能最近又有改动所以去掉了吧。不过我用本地 moon build 试了一下是有优化的,产出的代码:
(func $fib2.fn/5 (param $num/26 i32) (result i32) (local $n/23 i32)
(local $acc1/24 i32) (local $acc2/25 i32)
(block $join:22 (local.get $num/26) (i32.const 0) (i32.const 1)
(local.set $acc2/25) (local.set $acc1/24) (local.set $n/23) (br $join:22))
(loop $join:22 (result i32) (local.get $n/23) (i32.const 0) (i32.eq)
(if (result i32) (then (local.get $acc1/24))
(else (local.get $n/23) (i32.const 1) (i32.eq)
(if (result i32) (then (local.get $acc2/25))
(else (local.get $n/23) (i32.const 1) (i32.sub) (local.get $acc2/25)
(local.get $acc1/24) (local.get $acc2/25) (i32.add)
(local.set $acc2/25) (local.set $acc1/24) (local.set $n/23)
(br $join:22)))))))
Many thx!
这段就明显看出 recursion 被优化展开成循环了。
看来要不是开关被关了,要不是暂时 regression 了。感谢