2

This is critical section of the program that cause problem, and program is completely sequential.

exist_ is a class bool private member, and dbl_num_ is a class double private member

exist_ = false;
dbl_num_ = 0;
std::cout << dbl_num_ << " " ;
if(exist_ == true)
{
  dbl_num_ = 5;
}else
{
  dbl_num_ = NAN;
}

std::cout << exist_ << " " << dbl_num_ << std::endl;

With option -ffast-math, I got printout "0 0 5"

Without option -ffast-math, I got printout "0 0 NAN"

Furthermore if I change the program to

exist_ = false;
dbl_num_ = 0;
std::cout << dbl_num_ << " " ;
if(exist_ == true)
{
  std::cout << exist_ << " " ;
  dbl_num_ = 5;
}else
{
  dbl_num_ = NAN;
}

std::cout << exist_ << " " << dbl_num_ << std::endl;

With option -ffast-math, I got "0 0 NAN"

Than I change the NAN to -5

exist_ = false;
dbl_num_ = 0;
std::cout << dbl_num_ << " " ;
if(exist_ == true)
{
  dbl_num_ = 5;
}else
{
  dbl_num_ = -5;
}

std::cout << exist_ << " " << dbl_num_ << std::endl;

With option -ffast-math, I got "0 0 -5"

I knew -ffast-math break IEEE standards, and it don't check NAN, but what is exactly the reason it break the above simple condition check?

einpoklum
  • 118,144
  • 57
  • 340
  • 684
Bryan Fok
  • 3,277
  • 2
  • 31
  • 59
  • 2
    what is `exist_` ? What is `exist` ? Please post a [MCVE](http://stackoverflow.com/help/mcve). Cannot reproduce. – M.M Dec 03 '15 at 02:57
  • 4
    If you want NaNs, don't use -ffast-math. Among other things, the compiler specifically assumes NaNs don't happen with that flag on. – user2357112 Dec 03 '15 at 03:02
  • @user2357112 so what exactly happen behind the scene? – Bryan Fok Dec 03 '15 at 03:04
  • 1
    @BryanFok - why not compile with the -S option and have a look at the generated assembly? _Perhaps_ better(easier) yet - throw the code at http://gcc.godbolt.org/ and see what it has to say (it shows the generated asm side by side with the entered c/c++ code) – enhzflep Dec 03 '15 at 03:24
  • @enhzflep Thanks , it is a very cool tool! But i cant replicate it using a simplified code. But i will definitely use it more. – Bryan Fok Dec 03 '15 at 03:44
  • Which compiler, and which version? – Cornstalks Dec 03 '15 at 03:47
  • @Cornstalks its gcc 2.6.3 – Bryan Fok Dec 03 '15 at 05:16

1 Answers1

3

-ffast-math instructs g++ to assume that NaNs never occur. Setting something to NaN, then, is a rough equivalent of undefined behavior, in that the compiler can safely assume it never happens. See this series of LLVM blog posts for information on how a compiler can eliminate branches that it 'knows' can't be executed, and how that can be surprising.

The short version: g++ goes "We're in fast math mode, so dbl_num_ is never set to NaN, so the else branch is never taken, so exist_ must be true, so I can optimize out everything other than that path".

EDIT: See also this gcc bug report.

James Picone
  • 1,509
  • 9
  • 18
  • I came up with the same hypotheses as yours, and since cout is not an optimal target for fast-math, branch would keep in assembly. But i could not prove it in the http://gcc.godbolt.org/ unfortunately. – Bryan Fok Dec 03 '15 at 05:15
  • I could. GCC version 4.47, flags -ffast-math -O3, and a function that takes a bool, returns NAN if the bool is true, 5 if the bool is false. Compiles to code that loads the value 5 into a register and then returns. Without optimization or without -ffast-math, the test is in there. – James Picone Dec 03 '15 at 05:28