2

I am reading code from here:

 template<typename T> T Math::AngRound(T x) {
    static const T z = 1/T(16);
    if (x == 0) return 0;
    GEOGRAPHICLIB_VOLATILE T y = abs(x);
    // The compiler mustn't "simplify" z - (z - y) to y
    y = y < z ? z - (z - y) : y;
    return x < 0 ? -y : y;
  }

where T is double and GEOGRAPHICLIB_VOLATILE is volatile.

And I wonder, are compilers allowed to "simplify" z - (z - y) to y, and is that prevented by volatile or not? If it is relevant, I am interested in the C++17 standard.

Checking the assembly for clang showed that without volatile -O3 doesn't cause the simplification of z - (z - y) to y.

On the other hand, icc simplifies the code in both cases: https://godbolt.org/z/rz7erdhev . If volatile is used, it adds an extra read, but not any real calculations.

SuperStormer
  • 4,997
  • 5
  • 25
  • 35
user1244932
  • 7,352
  • 5
  • 46
  • 103

2 Answers2

0

You're looking for -ffast-math. Here is a simple demo:

$ cat main.c
int main(int argc, char **argv)
{
    double x=argc+0.5;
    return x-(x-27.5);
}

First compile it with default floating point support:

$ gcc -g -O3 main.c -o main
$ objdump -S -D main > main.default
$ sed -n "296,310p;311q" main.default
int main(int argc, char **argv)
{
    double x=argc+0.5;
 4f0:   66 0f ef c0             pxor   %xmm0,%xmm0
 4f4:   f2 0f 2a c7             cvtsi2sd %edi,%xmm0
 4f8:   f2 0f 58 05 b8 01 00    addsd  0x1b8(%rip),%xmm0        # 6b8 <_IO_stdin_used+0x8>
 4ff:   00 
    return x-(x-27.5);
 500:   66 0f 28 c8             movapd %xmm0,%xmm1
 504:   f2 0f 5c 0d b4 01 00    subsd  0x1b4(%rip),%xmm1        # 6c0 <_IO_stdin_used+0x10>
 50b:   00 
 50c:   f2 0f 5c c1             subsd  %xmm1,%xmm0
 510:   f2 0f 2c c0             cvttsd2si %xmm0,%eax
}
 514:   c3                      retq   

Now compile it with floating point fast support:

$ gcc -g -O3 -ffast-math main.c -o main
$ objdump -S -D main > main.opt
$ sed -n "308,314p;315q" main.opt
int main(int argc, char **argv)
{
    double x=argc+0.5;
    return x-(x-27.5);
}
 510:   b8 1b 00 00 00          mov    $0x1b,%eax
 515:   c3                      retq   
OrenIshShalom
  • 5,974
  • 9
  • 37
  • 87
  • 1
    I am not sure whether this answers the question. OP asks if such optimization is allowed, not which option causes it. – Daniel Langr May 11 '21 at 04:07
0

The C++ standard imposes no requirements whatsoever on the accuracy of floating-point operations. Practical compilers, however, are aware of the significance of such code and provide options to control behavior-changing transformations to it. GCC in particular defaults to preserving the code and provides -funsafe-math-optimizations for the alternative.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76