Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will C/C++ compiler do reorder for commutative operators (eg: +, *) to optimize constants

Will the 2nd line of the following code

int bar;
int foo = bar * 3 * 5;

be optimized to

int bar;
int foo = bar * 15;

Or even more:

int foo = 3 * bar * 5;

can be optimized?

The purpose is actually to ask if I can just write

int foo = bar * 3 * 5;

instead of

int foo = bar * (3 * 5);

to save the parentheses. (and the relieve the need to manually manipulate those constant ordering => and in many case grouping constants with related variables are more meaningful rather than grouping constants for optimization)

like image 817
Robin Hsu Avatar asked Oct 02 '15 03:10

Robin Hsu


2 Answers

Almost all compilers will do it for integers, because even if a constant collapse might overflow in a different way, overflow may be ignored by the standard, so they can do what they like.

It often will not work for floating point values if it's adhering to strict floating point math; the order of evaluation with floating point math can affect the outcome, so strict compliance can't reorder floating point math.

5.1.2.3 Program execution

[#1] The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant.

[#3] In the abstract machine, all expressions are evaluated as specified by the semantics.

[#13] EXAMPLE 5 Rearrangement for floating-point expressions is often restricted because of limitations in precision as well as range. The implementation cannot generally apply the mathematical associative rules for addition or multiplication, nor the distributive rule, because of roundoff error, even in the absence of overflow and underflow. (Source)

It's not describing the use with constants precisely, but it's clearly noting that seemingly equivalent operations are not actually equivalent in the bizarro world that is floating point arithmetic (e.g. x / 5.0 cannot be translated to x * 0.2 with complete equivalence, x + x * y cannot be equivalently represented as x * (1.0 + y)).

like image 170
ShadowRanger Avatar answered Oct 10 '22 16:10

ShadowRanger


Here's an example of what an optimizer will do. Compiling this code with g++ 4.9.2 using -O2:

int calculate(int bar)     
{
    return bar*3*5;
}

is translated into this assembly code:

movl    %edi, %eax        # copy argument into eax
sall    $4, %eax          # shift eax left 4 bits
subl    %edi, %eax        # subtract original value from eax
ret                       # return (with eax as result)

Not only did it not do two multiplications, it didn't even do one. It converted the multipication by 15 into something equivalent to this:

int calculate(int bar)     
{
    return (bar<<4)-bar;
}
like image 23
Vaughn Cato Avatar answered Oct 10 '22 15:10

Vaughn Cato