Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Clang\LLVM has some heuristics where it will convert cmovs generated by earlier passes back in to jumps https://reviews.llvm.org/D34769. Also the compilers can't always prove its safe to evaluate both sides of a ternary operator which would be needed to use a cmov. Here's a compiler explorer sample for clang and GCC that shows all these problems https://godbolt.org/z/IpZfZv, you change the -x86-cmov-converter option to true re-enable clangs cmov converter which will disable cmov in the last function.


Yeah I have spent a long time fighting to get cmov into code that wants it.

The cmov1 case in your example ends up getting a cmov1 because the compiler was able to apply the cmov to the pointer rather than to the read value (essentially transforming it to `return (cond ? v1 : v2)->i`).

It's fragile though, if you change it a bit it stops working:

https://godbolt.org/z/hs71Jb

It isn't clear if it stops because the heuristics aren't in favor any more (you'd need 2 cmov-y things to handle the +1), or because the compiler no longer sees the transformation is possible at all.

gcc even fails if you add +1 to both sides which should be almost as simple as the original:

https://godbolt.org/z/y7PIcU

I have tried to use the "unconditionally deference" trick many times to convince a cmov, but it seems it doesn't always work because the compiler might re-optimize it back to only doing the read inside the branch/conditional, so later phases don't see the read as safe.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: