www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Optimizing with dmd disables floating point exceptions

reply Jens Mueller <jens.k.mueller gmx.de> writes:
Hi,

checking whether a floating point exception occurred is good coding
practice for me.

I discovered a strange behavior using dmd.
divByZero.d:
import std.math;
unittest {
    auto a = 1.0L;
    assert(!ieeeFlags.divByZero);
    a /= 0.0L;
    assert(ieeeFlags.divByZero);
}

$ rdmd --main -unittest divByZero.d
passes, but
$ rdmd -O --main -unittest divByZero.d
makes the second assert fail.

Similar behavior if I enable floating point exceptions
    FloatingPointControl fpctrl;
    fpctrl.enableExceptions(FloatingPointControl.severeExceptions);

Without optimization I get a floating point exception. With
optimization the code passes even though it shouldn't.
In sum neither floating point exceptions nor status flags are working
when optimizations are turned on.
$ dmd | head -1
Digital Mars D Compiler v2.052

Jens
Apr 28 2011
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/28/2011 3:02 PM, Jens Mueller wrote:
 Hi,

 checking whether a floating point exception occurred is good coding
 practice for me.

 I discovered a strange behavior using dmd.
 divByZero.d:
 import std.math;
 unittest {
      auto a = 1.0L;
      assert(!ieeeFlags.divByZero);
      a /= 0.0L;
      assert(ieeeFlags.divByZero);
 }

 $ rdmd --main -unittest divByZero.d
 passes, but
 $ rdmd -O --main -unittest divByZero.d
 makes the second assert fail.

 Similar behavior if I enable floating point exceptions
      FloatingPointControl fpctrl;
      fpctrl.enableExceptions(FloatingPointControl.severeExceptions);

 Without optimization I get a floating point exception. With
 optimization the code passes even though it shouldn't.
 In sum neither floating point exceptions nor status flags are working
 when optimizations are turned on.
 $ dmd | head -1
 Digital Mars D Compiler v2.052

That's because the a/=1.0L; is a dead assignment and is removed by the optimizer.
Apr 28 2011
parent reply KennyTM~ <kennytm gmail.com> writes:
On Apr 29, 11 14:27, Walter Bright wrote:
 That's because the a/=1.0L; is a dead assignment and is removed by the
 optimizer.

I'd say it's a wrong-code bug. ------------------------------------- import std.math, std.stdio; void main() { auto a = 1.0, b = 0.0; writeln(a); writeln(ieeeFlags.divByZero); auto c = a / b; // <-- this is no longer dead right? writeln(c); writeln(ieeeFlags.divByZero); } ------------------------------------- 1 false 9.50035e-306 false -------------------------------------
Apr 28 2011
parent KennyTM~ <kennytm gmail.com> writes:
(It seems the message is lost. Let me try again.)

On Apr 29, 11 15:10, Jens Mueller wrote:
 KennyTM~ wrote:

 I think the compiler performs that floating point division at compile
 time. I should look at the assembly. So the floating point exception
 happens at that point. Shouldn't the compiler tell me this somehow? Ask
 differently how do I get to know when my compile time function causes
 floating point exceptions?
 Interestingly the results are not the same. Shouldn't in both cases
 assert(a == real.infinity, to!(string)(a));
 hold.
 Without optimization it holds. Why does it not hold with optimizations?

 Jens

The compiler (optimizer) recognizes you have provided only constants and try to do constant folding. But the backend (evalu8.c) did not treat the divide-by-zero case correctly and yields a garbage value. See bug 5908 (http://d.puremagic.com/issues/show_bug.cgi?id=5908).
Apr 29 2011
prev sibling next sibling parent Jens Mueller <jens.k.mueller gmx.de> writes:
KennyTM~ wrote:
 On Apr 29, 11 14:27, Walter Bright wrote:
That's because the a/=1.0L; is a dead assignment and is removed by the
optimizer.

I'd say it's a wrong-code bug. ------------------------------------- import std.math, std.stdio; void main() { auto a = 1.0, b = 0.0; writeln(a); writeln(ieeeFlags.divByZero); auto c = a / b; // <-- this is no longer dead right? writeln(c); writeln(ieeeFlags.divByZero); } ------------------------------------- 1 false 9.50035e-306 false -------------------------------------

I think the compiler performs that floating point division at compile time. I should look at the assembly. So the floating point exception happens at that point. Shouldn't the compiler tell me this somehow? Ask differently how do I get to know when my compile time function causes floating point exceptions? Interestingly the results are not the same. Shouldn't in both cases assert(a == real.infinity, to!(string)(a)); hold. Without optimization it holds. Why does it not hold with optimizations? Jens
Apr 29 2011
prev sibling parent Jens Mueller <jens.k.mueller gmx.de> writes:
KennyTM~ wrote:
 (It seems the message is lost. Let me try again.)
 
 On Apr 29, 11 15:10, Jens Mueller wrote:
 KennyTM~ wrote:

 I think the compiler performs that floating point division at compile
 time. I should look at the assembly. So the floating point exception
 happens at that point. Shouldn't the compiler tell me this somehow? Ask
 differently how do I get to know when my compile time function causes
 floating point exceptions?
 Interestingly the results are not the same. Shouldn't in both cases
 assert(a == real.infinity, to!(string)(a));
 hold.
 Without optimization it holds. Why does it not hold with optimizations?

 Jens

The compiler (optimizer) recognizes you have provided only constants and try to do constant folding. But the backend (evalu8.c) did not treat the divide-by-zero case correctly and yields a garbage value. See bug 5908 (http://d.puremagic.com/issues/show_bug.cgi?id=5908).

Yeah. Looks like a bug to me as well. Jens
Apr 29 2011