Bug 14452 – [REG2.067] Floating point invalid operation when returning a structure containing a float field

Status
RESOLVED
Resolution
WONTFIX
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2015-04-16T20:56:00Z
Last change time
2015-06-27T02:27:15Z
Keywords
wrong-code
Assigned to
nobody
Creator
rumbu

Comments

Comment #0 by rumbu — 2015-04-16T20:56:44Z
//D 2.067 regression from D 2.066 import std.math; import std.stdio; struct S { float f; this(float f) { this.f = f; } } S foo() { FloatingPointControl fpCtrl; fpCtrl.enableExceptions(FloatingPointControl.severeExceptions); return S(0f); //exception thrown //workaround: //auto s = S(0f); //return s; } void main(string[] args) { auto s = foo(); }
Comment #1 by rumbu — 2015-04-16T21:00:11Z
Reported on Windows (8.1, 32 & 64 bit) Do not throw on OSX Not tested on Linux
Comment #2 by mk — 2015-04-16T21:09:20Z
I get Floating point exception on Linux x86, but not x86_64
Comment #3 by gassa — 2015-04-17T08:08:38Z
I also get the exception with this code on Windows with dmd 2.067.0 compiling to 32-bit. When compiling to 64-bit or using dmd 2.066.1, everything is fine.
Comment #4 by k.hara.pg — 2015-04-22T14:48:39Z
This is a side effect of https://github.com/D-Programming-Language/dmd/pull/3885 . Currently, dmd backend uses FLD and FSTP x87 instructions to initialize a float variable with NaN. It could raise Invalid Floating Point exception. int main() { import std.math : FloatingPointControl; FloatingPointControl fpCtrl; fpCtrl.enableExceptions(FloatingPointControl.severeExceptions); float x; // raises Invalid FP Op exception struct S { float f; } auto s = S(); // ditto } B the pull 3885, a struct constructor call had changed to a struct literal expression with constructor member function call. When the object image is initialized with the default values before ctor call, the NaN setting will raise exception. It's a behavior change in 2.067, but I'm not sure it's a wrong-code bug.
Comment #5 by code — 2015-04-23T12:47:39Z
(In reply to Kenji Hara from comment #4) > When the object image is initialized with the default values before ctor call, the NaN setting will raise exception. Related, but OT, could we avoid to initialize S.f twice?
Comment #6 by code — 2015-04-23T12:49:48Z
As a workaround you can set f to 0. struct S { float f = 0; this(float f) { this.f = f; } }
Comment #7 by k.hara.pg — 2015-04-23T13:21:43Z
(In reply to Martin Nowak from comment #5) > (In reply to Kenji Hara from comment #4) > > When the object image is initialized with the default values before ctor call, the NaN setting will raise exception. > > Related, but OT, could we avoid to initialize S.f twice? If the default initialization is done in the called constructor function, it could be optimized.
Comment #8 by temtaime — 2015-04-23T20:10:20Z
Why fpu instructions are used for init of fp variables ? It can be done with only one mov with nan value isn't it ?
Comment #9 by bugzilla — 2015-06-27T02:27:15Z
Whether the exception happens or not depends on whether the compiler uses XMM operations or X87 operations. The programming world has largely abandoned the X87, and the notion of throwing exceptions based on NaNs. I suggest abandoning such code as well, it is always going to be subject to the vagaries of code generations. We also had to give on supporting signaling NaNs for similar reasons. Another problematic issue is floating point constant folding - exceptions aren't thrown at compile time, so depending on optimization settings the runtime exception can come and go in rather arbitrary ways. And lastly, the X87 control word tends to wreak havoc with pure functions because it is a global setting. However, NaN tracking is consistent and works well. I recommend changing your code to simply test for NaN in the final result. I'm marking this as "won't fix". I have no idea how to fix it in a consistent manner, I suspect it is not possible.