c语言O2优化开启优缺点,c – gcc优化标志-O3使代码慢于-O2

本文讨论了在C语言中使用GCC编译器时,-O2和-O3优化级别的差异,特别是在循环性能方面。-O3使用cmov指令可能导致循环依赖链延长,而-O2则使用分支,对于已排序数据,分支预测能有效提升性能。GCC的版本和优化策略选择对代码执行效率有显著影响,甚至在某些情况下,-O2比-O3更快。

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

gcc -O3使用cmov作为条件,所以它延长了循环携带的依赖链,包括一个cmov(根据Agner Fog’s instruction tables,你的英特尔Sandybridge CPU有2个uop和2个周期的延迟.另见x86标签维基) .这是one of the cases where cmov sucks.

如果数据甚至是中等不可预测的,那么cmov可能是一个胜利,所以这对编译器来说是一个相当明智的选择. (但是,compilers may sometimes use branchless code too much.)

我在put your code on the Godbolt compiler explorer看到asm(有很好的突出显示并过滤掉不相关的行.你仍然需要向下滚动所有的排序代码才能到达main()).

.L82: # the inner loop from gcc -O3

movsx rcx, DWORD PTR [rdx] # sign-extending load of data[c]

mov rsi, rcx

add rcx, rbx # rcx = sum+data[c]

cmp esi, 127

cmovg rbx, rcx # sum = data[c]>127 ? rcx : sum

add rdx, 4 # pointer-increment

cmp r12, rdx

jne .L82

gcc可以通过使用LEA而不是ADD来保存MOV.

ADD-> CMOV(3个周期)的延迟的循环瓶颈,因为循环的一次迭代将rbx写入CMO,并且下一次迭代使用ADD读取rbx.

该循环仅包含8个融合域uop,因此它可以每2个循环发出一次.执行端口压力也不像总和链的延迟那样是一个瓶颈,但它很接近(Sandybridge只有3个ALU端口,不像Haswell的4).

BTW,将

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值