When refracting a particular piece of C++ code that converted radians to degrees, it was suggested by a friend that I swap the order of the operations in the function as it would increase performance. I thought it would be interesting to actually see if this was the case, consider;

define PI 3.1415 double torad1(double n) { return n * 180 / PI; }

The assembler code produced by g++ 4.8 looks like this:

.LCPI0_0: .quad 4640537203540230144 # double 180 .LCPI0_1: .quad 4614256447914709615 # double 3.1415 torad1(double): mulsd .LCPI0_0(%rip), %xmm0 divsd .LCPI0_1(%rip), %xmm0 ret

Notice the presence of a division operation. The compiler has conformed with what it has been taught, that floating point maths is not associative. The interesting part is that by swapping the order of the operations, the two constants can be folded;

define PI 3.1415 double torad2(double n) { return 180 / PI * n; }

Which produces assembler like this;

.LCPI1_0: .quad 4633260719236591239 # double 57.29746936176985 torad2(double): mulsd .LCPI1_0(%rip), %xmm0 ret

Notice how it has converted the division into a single multiplication of n by 180 / PI ? This is an interesting subtlety that I will be paying more attention to when I write code from now on.

If you’re using gcc/clang and would like to see how much faster your code would be if floating point operations were associative, but you’d rather not rewrite any code, you can compile using the -ffast-math flag, which disables this behaviour. For full documentation on the flag, see here.