读<一例 Go 编译器代码优化 bug 定位和修复解析>

看到一例 Go 编译器代码优化 bug 定位和修复解析这样一篇文章,感觉有些意思. 在此复现和记录

在Go 1.16版本下,是没有这个bug的(已修复). 参照gvm:灵活的Go版本管理工具 将Go版本切至有问题的1.13.5(或1.14.6)

go 复制代码
➜  go version
go version go1.13.5 darwin/amd64
go 复制代码
package main

import "fmt"

func main() {

	sli := []int32{1, 2, 3, 4, 5, 6}

	// 如果是这种方式声明的sli, 依然会出bug
	//var sli []int32
	//sli = []int32{1, 2, 3, 4, 5, 6}

	// 如果是这种方式声明的sli, 则不会出bug
	//sli := make([]int32, 0)
	//sli = append(sli, 1, 2, 3, 4, 5, 6)

	for k, v := range sli { //如果把sli改为 []int32{1, 2, 3, 4, 5, 6},也不会出bug

		if k+1 < 1 { //去掉这个不会被执行进,没啥用的判断,则也不会出bug; 改为if k+2 < 2 {,也不会出bug
			panic("")
		}

		fmt.Println("=========")

		fmt.Println(k, v)
	}
}

执行结果:

go 复制代码
=========
0 1
=========
1 2
=========
2 3
=========
3 4
=========
4 5
=========
5 6
=========
6 622680
=========
7 192
=========
8 17477952
=========
9 0
=========
10 17733712
=========
11 0
=========
12 17475456
=========
13 0
=========
14 622792
=========
15 192
=========
16 17475584

...

在线 查看&比对 给定程序编译产出的汇编结果. 该网站好评!

其实 Go 的编译器的实现中规中矩,相比于 GCC/Clang 等老牌编译器甚至有些简陋,许多优化并未实现

"Go 编译器提供了非常方便的功能,可以查看各个优化 pass 前后的 SSA IR,只需要在编译时,增加一个 GOSSAFUNC=xxx 环境变量即可,xxx 即为想要分析的函数的名字,因为 Go 编译器内部的优化都是函数级别的。比如上图的例子,只需要运行 GOSSAFUNC=main go build ssaexample.go,编译器就会将 SSA IR 结果输出到当前目录的 ssa.html 中,用浏览器打开即可。"

用浏览器打开当前目录的 ssa.html:

执行 GOSSAFUNC=main go build 1.go

浏览器打开:

prove pass 的功能是对全局中 SSA 值的取值范围做一个推断,这样就可以消除掉许多不必要的分支判断

Go 是内存安全的语言,所以所有的 slice 取元素操作都需要做一个检查,来判断取元素用的下标是否超出了 slice 的范围,这个操作叫做 bound check。但是实际上,很多代码中在编译期就能确定这个下标是否越界,那么我们就可以将原本需要在运行期做 bound check 的检查给消除掉,这步优化叫做 bound check elimination (即 BCE)

如下 这样的写法在Go源码中非常多

可参考 Go 官方标准编译器中所做的优化 之 Bounds Check Elimination

通过日志中的关键字, 能找到只有 findIndVar 和 addLocalInductiveFacts 这两个函数中会打这条日志,结合上下文和相关注释不难看出实际上问题是出在 addLocalInductiveFacts 这个函数上。addLocalInductiveFacts 具体是什么功能呢?从注释中不难看出,这里的功能是匹配到一种特殊的代码 pattern,即类似 repeat until 的逻辑,在循环末尾判断某个条件是否成立

修复

详细

相关推荐
黑马程序员毕设8 小时前
基于微信小程序的节目活动报名与管理系统设计与实现
java·开发语言·spring boot·后端·电脑
掘金者阿豪8 小时前
Windows 部署 Papra:建立私有文档库、标签管理,再配置固定公网访问
后端
Bs_MoneyMagnet9 小时前
基于springboot+vue的会议室预约管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
Bs_MoneyMagnet9 小时前
基于springboot+vue的茶铺管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
她说..9 小时前
RabbitMQ 使用场景详解
java·spring boot·后端·spring·rabbitmq·java-rabbitmq
shengjk19 小时前
AI会让程序员失业吗?200年前的手工织工已经给出了答案
后端
盖伦发发9 小时前
MySQL InnoDB事务完整教程|ACID、MVCC、隔离级别、事务控制
经验分享·后端·spring·软件工程
一条泥憨鱼10 小时前
苍穹外卖【day09| 对订单的各种操作】
后端·苍穹外卖
前端snow10 小时前
ai agent --- AGUI 协议,流式渲染组件
人工智能·后端
用户81818706274610 小时前
第26章 Kafka vs RocketMQ vs RabbitMQ真实选型对比
java·后端