CMOV a Bad Idea on Out-of-Order CPUs
ondioline.org
ondioline.org
Assembly/Compiler Coding Rule 2. (M impact, ML generality): Use the SETCC and CMOV instructions to eliminate unpredictable conditional branches where possible.
* Do not do this for predictable branches.
* Do not use these instructions to eliminate all unpredictable conditional branches (because using these instructions will incur execution overhead due to the requirement for executing both paths of a conditional branch).
* In addition, converting a conditional branch to SETCC or CMOV trades off control flow dependence for data dependence and restricts the capability of the out-of-order engine.
* When tuning, note that all Intel 64 and IA-32 processors usually have very high branch prediction rates. Consistently mispredicted branches are generally rare. Use these instructions only if the increase in computation time is less than the expected cost of a mispredicted branch.
Also setcc is abysmally stupid in leaving the high 3/7 bytes of the register unmodified - what were Intel's engineers smoking?
See: http://newsgroups.derkeiler.com/Archive/Comp/comp.arch/2013-....
It makes sense in context. When the instruction was introduced, it made sense to have 8-bit flags instead of overwriting a whole register (remember you only have 7, and we're usually optimizing things for size at this point). You can also do SETcc of the upper 8 bits of a 16-bit register, e.g. SETNZ AH.
It doesn't make sense now, true, but I've never seen it as a large annoyance; you can avoid using SETcc in favor of full-register instructions (excluding CMOV) most of the time anyway.
The link doesn't show what the context of the discussion is, but its intended application is the case where Linus says it does work:
" - if you KNOW the branch is totally unpredictable, cmov is often good for performance."
You see this kind of data dependent branches in eg. compression code where the unpredictability is inherent.
CMOV on current CPUs is quite fine— when it doesn't make a dependency mess, when the alternative is a poorly predicted branch, and when the dual execution is cheap / can be hidden.