Linux环境g++9.3.0 -O2编译导致程序运行耗时翻倍的异常问题咨询
问题根因分析
这是GCC 9.3.0版本的已知优化bug,仅触发于Linux x86_64平台的O2及更高优化等级,GCC 8、GCC 10及其他操作系统的GCC 9.3.0均未命中该问题,和各平台GCC后端的指令调度、优化策略差异有关。
核心触发点为优化器的别名分析模块出现误判:
- 当你保留
generate函数末尾的init()调用时,优化器错误判定strange_func中对s、r数组的写入操作,和后续init()里memset的写入操作存在地址重叠,因此没有对strange_func的循环体执行应有的寄存器分配优化,高频访问的数组元素、索引变量无法被缓存到寄存器中,每次访问都需要直接读写内存,最终导致运行耗时翻倍。 - 当你删除末尾的
init()调用后,优化器识别到没有后续对结构体成员的写入操作,正常执行寄存器分配优化,循环体的内存访问操作减少近一半,耗时恢复正常。
两次调用strange_func出现耗时差异的原因也一致:第一次调用前的init()没有被后续写入操作干扰,优化正常;第二次调用前的init()和调用后的写入操作被误判存在地址重叠,优化失效。
验证方案
你可以通过以下方式验证根因:
- 编译时添加
-fno-strict-aliasing参数关闭严格别名分析,两种场景的耗时都会回归到600ms左右的正常水平。 - 对比两种场景的汇编输出:保留
init()的版本中strange_func循环体内存在大量重复的mov内存读写指令,删除init()的版本中高频变量均被缓存到寄存器中,循环指令数大幅减少。
规避方案
如果需要在GCC 9.3.0环境下解决该问题,可选择以下任意一种方案:
- 升级编译器到GCC 10及以上版本,该bug已在后续版本中被官方修复。
- 若必须保留GCC 9.3.0版本,可在
generate函数声明上添加__attribute__((optimize("-fno-strict-aliasing")))属性,仅对该函数关闭严格别名分析,不影响全局编译优化效果。 - 调整代码结构,将
generate末尾的init()调用移动到函数外部执行,避开优化器的误判逻辑。
内容的提问来源于stack exchange,提问作者cht233
相关产品推荐
相关产品推荐

