← Back to context

Comment by xxpor

4 years ago

the original version had branches too, in fact a majority of the lines had them! ? is just shorthand for if.

This isn't true, this form of conditionals can be compiled into cmov type of instructions, which is faster than regular jump if condition.

  • Both ?: and if-else have cases where they can be compiled into cmov type instructions and where they cannot. Given int max(int a, int b) { if (a > b) return a; else return b; }, a decent compiler for X86 will avoid conditional branches even though ?: wasn't used. Given int f(int x) { return x ? g() : h(); }, avoiding conditional branches is more costly than just using them, even though ?: was used.

  • > This isn't true, this form of conditionals can be compiled into cmov type of instructions, which is faster than regular jump if condition.

    IIRC cmov is actually quite slow. It's just faster than an unpredictable branch. Most branches have predictability so you generally don't want a cmov.

    Speaking of which, a couple questions regarding this for anyone who might know:

    1. Can you disable cmov on x64 on any compiler? How?

    2. Why is cmov so slow? Does it kill register renaming or something like that?

    • cmov itself isn't slow, it has a latency of 2 cycles on Intel; and only 1 cycle on AMD (same speed as an add). However, cmov has to wait until all three inputs (condition flag, old value of target register, value of source register) are available, even though one of those inputs ends up going unused.

      A correctly predicted branch allows the subsequent computation (using of the result of the ?: operator) to start speculatively after waiting only for the relevant input value, without having to wait for the condition or the value on the unused branch. This could sometimes save hundreds of cycles if an unused input is slow due to a cache miss.

      4 replies →

  • If the if/else is simple the compiler should be able to optimize that anyway.