Be aware of floating point optimizations introduced by constant folding in conformant code

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.

About these ads

4 thoughts on “Be aware of floating point optimizations introduced by constant folding in conformant code

  1. I kind of expected that. The compiler pre-calculates operations with constants such as something that contains PI / 180. But it’s pretty interesting that the optimization only works with this operation order.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s