Bryan Fok
Bryan Fok

Reputation: 3487

why -ffast-math option break my bool condition

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?

Upvotes: 2

Views: 159

Answers (1)

James Picone
James Picone

Reputation: 1600

-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.

Upvotes: 3

Related Questions