GCC编译器中的条件移动(cmov) [英] Conditional move (cmov) in GCC compiler

查看:86
本文介绍了GCC编译器中的条件移动(cmov)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I saw somewhere that the GCC compiler might prefer sometimes not using conditional mov when converting my code into ASM.

在哪些情况下,它可能会选择执行有条件移动以外的其他操作?

What are the cases where it might choose to do something other than conditional mov?

推荐答案

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

Compilers often favour if-conversion to cmov when both sides of the branch are short, especially with a ternary so you always assign a C variable. e.g. if(x) y=bar; sometimes doesn't optimize to CMOV but y = x ? bar : y; does use CMOV more often. Especially when y is an array entry that otherwise wouldn't be touched: introducing a non-atomic RMW of it could create a data-race not present in the source. (Compilers can't invent writes to possibly-shared objects.)

当if/else转换的两面都有大量工作时,if转换何时合法但显然不赚钱的一个明显例子.例如一些乘法和除法,整个循环和/或表查找.即使gcc可以证明运行双方并在最后选择一个结果是安全的,它仍会发现做更多的工作不值得避免创建分支.

The obvious example of when if-conversion would be legal but obviously not profitable would be when there's a lot of work on both sides of an if/else. e.g. some multiplies and divides, a whole loop, and/or table lookups. Even if gcc can prove that it's safe to run both sides and select one result at the end, it would see that doing that much more work isn't worth avoiding a branch.

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

If-conversion to a data-dependency (branchless cmov) is only even possible in limited circumstances. e.g. Why is gcc allowed to speculatively load from a struct? shows a case where it can/can't be done. Other cases include doing a memory access that the C abstract machine doesn't, which the compiler can't prove won't fault. Or a non-inline function call that might have side-effects.

另请参阅有关获取 gcc以使用CMOV的这些问题.

See also these questions about getting gcc to use CMOV.

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

See also Disabling predication in gcc/g++ - apparently gcc -fno-if-conversion -fno-if-conversion2 will disable use of cmov.

有关cmov会影响性能的情况,请参见 gcc优化标志-O3使代码的运行速度比-O2慢-GCC -O3 需要配置文件引导的优化才能正确处理,并为 if 使用分支,而事实证明该分支具有很高的可预测性.即使没有PGO分析数据,也不会首先进行if-conversion.

For a case where cmov hurts performance, see gcc optimization flag -O3 makes code slower than -O2 - GCC -O3 needs profile-guided optimization to get it right and use a branch for an if that turns out to be highly predictable. GCC -O2 didn't do if-conversion in the first place, even without PGO profiling data.

另一个示例:

An example the other way: Is there a good reason why GCC would generate jump to jump just over one cheap instruction?

GCC似乎错过了简单优化显示了三元有副作用的情况在这两个部分中:三元不像CMOV:甚至只评估了一侧的副作用.

GCC seemingly misses simple optimization shows a case where a ternary has side-effects in both halves: ternary isn't like CMOV: only one side is even evalutated for side effects.

AVX-512和分支机构显示了一个Fortran示例,其中GCC需要从源代码更改到能够使用无分支SIMD.(等效于标量CMOV).这是没有发明写的情况:它不能将源不会写的元素的读/分支转换为读/可能修改/写.如果通常需要进行转换,以实现自动矢量化.

AVX-512 and Branching shows a Fortran example where GCC needs help from source changes to be able to use branchless SIMD. (Equivalent of scalar CMOV). This is a case of not inventing writes: it can't turn a read/branch into read/maybe-modify/write for elements that source wouldn't have written. If-conversion is usually necessary for auto-vectorization.

这篇关于GCC编译器中的条件移动(cmov)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆