高级优化!编译器优化你试过没?分享给你一个完整的编译器编译规则的优化过程(附带动手实验)

本文介绍了如何通过优化编译规则提升Go编译器处理浮点变量与0比较的性能。通过分析编译过程,提出并实现了将两步比较指令合并为一步的优化策略,减少了不必要的寄存器操作。此外,文章还提供了动手实验的指导,帮助读者了解编译器优化的实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

所有的代码转化为可执行文件,都需要通过编译器将高级语言转化为计算器能够识别的低级语言。这个过程复杂且关键,很大程度上影响这门语言的性能。

关于编译器的优化工作也一直是人们研究的重点。但是,编译的过程涉及的知识过多,很多时候我们并不明白编译的过程中到底执行了什么操作。

本文通过分析Go编译器优化的完整案例,向大家分享编译器的编译规则的优化方法。

摘自OptimizeLab: https://github.com/OptimizeLab/docs 

作者:surechen


编译器的作用是将高级语言的源代码翻译为低级语言的目标代码。通常为了便于优化处理,编译器会将源代码转换为中间表示形式(Intermediate representation),很多编译优化过程都是作用在这个形式上,如下面将介绍的通过给编译器添加编译规则优化性能。

在编译Go语言代码时通常使用Go语言编译器,它包括语法分析AST变换静态单赋值SSA PASS、机器码生成等多个编译过程。其中在生成SSA中间表示形式后进行了多个编译优化过程PASS,每个PASS都会对SSA形式的函数做转换,比如deadcode elimination会检测并删除不会被执行的代码和无用的变量。在所有PASS中lower会根据编写好的优化规则将SSA中间表示从与体系结构(如X86ARM等)无关的转换为体系结构相关的,这是通过添加大量编译规则实现的,是本文的主要关注点。

1. 浮点变量比较场景

浮点数在应用开发中有广泛的应用,如用来表示一个带小数的金额或积分,经常会出现浮点数与0比较的情况,如向数据库录入一个商品时,为防止商品信息错误,可以检测录入的金额是否大于0,当用户购买产品时,可能需要先做一个验证,检测账户上金额是否大于0,如果满足再去查询商品信息、录入订单等,这样可以在交易的开始阶段排除一些无效或恶意的请求。

很多直播网站会举行年度活动,通过榜单展现用户活动期间累计送出礼物的金额,排名靠前的用户会登上榜单。经常用浮点数表示累计金额,活动刚开始时,需要屏蔽掉积分小于等于0的条目,可能会用到如下函数:

func comp(x float64, arr []int) {
    for i := 0; i < len(arr); i++ {
        if x > 0 {
            arr[i] = 1
        }
    }
}

使用Go compile工具查看该函数的汇编代码(为便于理解,省略了部分无用代码):

go tool compile -S main.go
"".comp STEXT size=80 args=0x20 locals=0x0 leaf
        0x0000 00000 (main.go:3)        TEXT    "".comp(SB), LEAF|NOFRAME|ABIInternal, $0-32
#-------------------------将栈上数据取到寄存器中------------------------------
..................................
        0x0000 00000 (main.go:4)        MOVD    "".arr+16(FP), R0         // 取数组arr长度信息到寄存器R0中
..................................
        0x0004 00004 (main.go:4)        MOVD    "".arr+8(FP), R1           // 取数组arr地址值到寄存器R1中
        0x0008 00008 (main.go:4)        FMOVD   "".x(FP), F0                 // 将参数x放入F0寄存器
        0x000c 00012 (main.go:4)        MOVD    ZR, R2                          // ZR表示0,此处R2 清零
#---------------------------for循环执行逻辑----------------------------------
        0x0010 00016 (main.go:4)        JMP     24                                   // 第一轮循环直接跳到条件比较 不增加i
        0x0014 00020 (main.go:4)        ADD     $1, R2, R2                       // i++
        0x0018 00024 (main.go:4)        CMP     R0, R2                            // i < len(arr) 比较
        0x001c 00028 (main.go:4)        BGE     68                                   // i == len(arr) 跳转到末尾
#--------if x > 0---------
        0x0020 00032 (main.go:5)        FMOVD   ZR, F1                         // 将0复制到浮点寄存器F1
        0x0024 00036
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值