I am trying to calculate a motor position from an encoder, however that does not really matter. I just checked godbolt.org to see if my inline function compiled into a single multiplication and was pretty disappointed that it didn’t. I used -O3 for maximum optimization.
Does somebody know why it does not compile into a single function, or what I had to change to achieve that? You can find my code here: https://godbolt.org/z/qT9srfPT1 .
I know that it does not really matter, but I am curious.
Use
-ffast-math
… if you dare. Or just useinline double position_from_steps(int steps) { return (2.0 * PI / 4096.0) * steps; };
The reason it doesn’t optimise it into one multiplication is because that isn’t actually the same calculation. Floating point numbers aren’t real numbers, so it isn’t true that
(a * b) / c == (a / c) * b
. Since the “optimisation” would actually change the semantics, compilers don’t do it by default.-ffast-math
says “hey I don’t care about reliable semantics; just do whatever to make it fast”. But it also does a load of stuff that you may find surprising. so you really shouldn’t use it. Much better just to reorganise your code.You can also use
-funsafe-math-optimizations
which is the more specific subset of-ffast-math
that does this particular optimisation. See https://gcc.gnu.org/wiki/FloatingPointMathAlso I would question if it matters. This micro-optimisation will make zero difference on x86. On a microcontroller (I assume what you’re actually using if you’re encoding motor positions) it might matter a bit more but double check your microcontroller even has an FPU. Lots don’t. Even if it does, doing it in integer space will probably be faster (though not necessarily).
Very interesting comment. Thanks.
The compiler can’t replace every floating point division with a multiplication with the reciprocal. And it can’t assume associativity. See also
-ffast-math
.You can do this:
return (double)steps * (2.0 * PI / 4096.0);