3 ms·
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 abl
by BeeOnRope 7y ago
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 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 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.