C语言 GCC 编译器中的条件移动 (cmov)



我在某处看到GCC编译器在将我的代码转换为ASM时有时可能更喜欢不使用条件mov。

在哪些情况下,它可能会选择执行条件 mov 以外的操作?

当分支的两边都很短时,编译器通常倾向于将 if 转换为 cmov,尤其是对于三元,因此您始终分配一个 C 变量。 例如if(x) y=bar;有时不会针对 CMOV 进行优化,但y = x ? bar : y;确实更频繁地使用 CMOV。 特别是当y是一个否则不会被触及的数组条目时:引入它的非原子 RMW 可能会创建源中不存在的数据争用。 (编译器无法发明对可能共享的对象进行写入。

if转换合法但显然无利可图的明显例子是,if/else的双方都有很多工作。 例如,一些乘除、整个循环和/或表查找。 即使 gcc 可以证明运行两边并在最后选择一个结果是安全的,它也会看到做更多的工作不值得避免分支。

如果转换为数据依赖关系(无分支cmov(仅在有限的情况下才有可能。 例如,为什么允许 gcc 从结构体推测加载? 显示了可以/不能完成的情况。 其他情况包括执行 C 抽象机器不会的内存访问,编译器无法证明不会出错。 或者可能有副作用的非内联函数调用。

另请参阅有关gcc 使用 CMOV 的问题。

  • 让 GCC/Clang 使用 CMOV
  • 如何在 GCC 和 VS 中强制使用 CMOV
  • 使 gcc 使用条件移动

另请参阅在 gcc/g++ 中禁用谓词 - 显然gcc -fno-if-conversion -fno-if-conversion2将禁用 cmov 的使用。

对于 cmov 损害性能的情况,请参阅 gcc 优化标志 -O3 使代码比 -O2 慢 - GCC-O3需要按配置文件优化才能正确执行,并将分支用于高度可预测的ifGCC-O2一开始就没有做if转换,即使没有PGO分析数据。

另一个例子:GCC是否有充分的理由生成跳转跳到一个便宜的指令上?

GCC似乎错过了简单的优化,显示了三元在两半都有副作用的情况:三元不像CMOV:只有一侧甚至被评估为副作用。

AVX-512 和分支显示了一个 Fortran 示例,其中 GCC 需要源代码更改的帮助才能使用无分支 SIMD。 (相当于标量 CMOV(。 这是一个不发明写入的情况:它不能将读取/分支转换为源不会写入的元素的读取/可能修改/写入。如果转换通常是自动矢量化所必需的。

最新更新