最近发布的 Go 1.7 里面使用了一个新的基于 SSA 的编译后端(目前只有 amd64 可用)。SSA 使得编译出来的代码更加高效 SSA,主要是里面有包含了 BCE和公共子表达式消除。
这篇文章将会通过一些例子给大家展示 Go 1.7 里面BCE是如何工作的。
在 Go 1.7 里面我们可以通过这个命令 go build -gcflags="-d=ssa/check_bce/debug=1" 来展示我们的代码哪一行需要进行越界检查。
例子1
package mainfunc f1(s []int) {
_ = s[0]
_ = s[1]
_ = s[2] }func f2(s []int) {
_ = s[2]
_ = s[1]
_ = s[0] }func f3(s []int, index int) {
_ = s[index]
_ = s[index] }func f4(a [5]int) {
_ = a[4] }func main() {}
$ go build -gcflags="-d=ssa/check_bce/debug=1" example1.go
# command-line-arguments
./11.go:5: Found IsInBounds
./11.go:6: Found IsInBounds
./11.go:7: Found IsInBounds
./11.go:11: Found IsInBounds
./11.go:17: Found IsInBounds
我们可以看到这个f2函数里面的12行和13行不需要进行越界检查,因为在11行里面的越界检查可以保证12,13行的代码是不会越界的。
但是在f1里面必须每一行都逐一检查越界,因为第5行没办法保证第6、第7行是安全的,第6行没办法保证第7行是安全的。
函数f3里面,Go 1.7 编译器知道如果第一行是安全的情况下,那么第二行的s[index]是完全安全的
Go 1.7 的编辑器也正确的分析出来了f4函数里面的唯一的一行(22行)也是安全的。
例子2
// example2.go
package main
func f5(s []int) {
for i := range s {
_ = s[i]
_ = s[i:len(s)]
_ = s[:i 1]
}
}
func f6(s []int) {
for i := 0; i
|