Re: Float values are wrong in union
On Monday, 22 August 2016 at 18:19:52 UTC, Engine Machine wrote: On Monday, 22 August 2016 at 05:02:41 UTC, jkpl wrote: On Monday, 22 August 2016 at 04:52:40 UTC, Cauterite wrote: [...] That's a 32 bit codegen issue then because DMD64 's disasm shows that SSE regs are used: x86 give 7FF and x64 gives 7FB in win. You can hack the ABI this way: void loadInScratchReg(float[1] f...) {} and pass a single float value. However when you'll start to use the param (f[0]), loading in ST(0) will happen so you must write in iasm. (Not to mention an aggressive optimizer that would be able, I think, to replace the param type if no iasm is present). example, usage of a tagged union to perform a safe bit cast: https://github.com/BBasile/iz/blob/master/import/iz/sugar.d#L1176 Not tested yet...
Re: Float values are wrong in union
On Monday, 22 August 2016 at 05:02:41 UTC, jkpl wrote: On Monday, 22 August 2016 at 04:52:40 UTC, Cauterite wrote: [...] That's a 32 bit codegen issue then because DMD64 's disasm shows that SSE regs are used: void foo() { union test { int i; float f; } test t = { i : 0x7fb0}; float t2 = t.f; test t3 = { f : t2 }; } === yields to === 004586D0h push rbp 004586D1h mov rbp, rsp 004586D4h sub rsp, 10h 004586D8h mov dword ptr [rbp-10h], 7FB0h 004586DFh movss xmm0, dword ptr [rbp-10h] 004586E4h movss dword ptr [rbp-0Ch], xmm0 004586E9h movss xmm1, dword ptr [rbp-0Ch] 004586EEh movss dword ptr [rbp-08h], xmm1 004586F3h leave 004586F4h ret === x86 give 7FF and x64 gives 7FB in win.
Re: Float values are wrong in union
On Monday, 22 August 2016 at 04:52:40 UTC, Cauterite wrote: On Monday, 22 August 2016 at 04:37:50 UTC, stunaep wrote: I made a union to convert between int bits and floats, but the values are coming out wrong sometimes. I can already tell what this is going to be... The problem is almost certainly nothing to do with your union, it's this line: float t2 = t.f; This will load 0x7fb0 into ST(0), which instantly converts it to 7FF0 because it's a signalling NaN, then store ST(0) in your float `t2`. Signalling NaNs are an ongoing problem in D's codegen. See Don's remarks at this page: https://issues.dlang.org/show_bug.cgi?id=16105#c2 The reason it works in other languages is because they don't place floats in the floating point registers for non-arithmetic operations. I've been trying to patch DMD's backend to behave this way too, but it's much harder than I expected (difficult codebase to understand/navigate). That's a 32 bit codegen issue then because DMD64 's disasm shows that SSE regs are used: void foo() { union test { int i; float f; } test t = { i : 0x7fb0}; float t2 = t.f; test t3 = { f : t2 }; } === yields to === 004586D0h push rbp 004586D1h mov rbp, rsp 004586D4h sub rsp, 10h 004586D8h mov dword ptr [rbp-10h], 7FB0h 004586DFh movss xmm0, dword ptr [rbp-10h] 004586E4h movss dword ptr [rbp-0Ch], xmm0 004586E9h movss xmm1, dword ptr [rbp-0Ch] 004586EEh movss dword ptr [rbp-08h], xmm1 004586F3h leave 004586F4h ret ===
Re: Float values are wrong in union
On Monday, 22 August 2016 at 04:37:50 UTC, stunaep wrote: I made a union to convert between int bits and floats, but the values are coming out wrong sometimes. I can already tell what this is going to be... The problem is almost certainly nothing to do with your union, it's this line: float t2 = t.f; This will load 0x7fb0 into ST(0), which instantly converts it to 7FF0 because it's a signalling NaN, then store ST(0) in your float `t2`. Signalling NaNs are an ongoing problem in D's codegen. See Don's remarks at this page: https://issues.dlang.org/show_bug.cgi?id=16105#c2 The reason it works in other languages is because they don't place floats in the floating point registers for non-arithmetic operations. I've been trying to patch DMD's backend to behave this way too, but it's much harder than I expected (difficult codebase to understand/navigate).
Re: Float values are wrong in union
On Monday, 22 August 2016 at 04:37:50 UTC, stunaep wrote: I made a union to convert between int bits and floats, but the values are coming out wrong sometimes. This is working without issue in other languages so I'm really stumped. Here's an example: union test { int i; float f; } test t = { i : 0x7fb0}; float t2 = t.f;//int bits 0x7fb0 as float test t3 = { f : t2 }; writefln("%x", t3.i);//prints 7ff0 NOT 0x7fb0 Ok on linux, 0x7fb0 is written, I tested under linux x86_64 with latest dmd beta, ldc and also gdc. Which compiler and version do you use ? Which OS and archi ?
Float values are wrong in union
I made a union to convert between int bits and floats, but the values are coming out wrong sometimes. This is working without issue in other languages so I'm really stumped. Here's an example: union test { int i; float f; } test t = { i : 0x7fb0}; float t2 = t.f;//int bits 0x7fb0 as float test t3 = { f : t2 }; writefln("%x", t3.i);//prints 7ff0 NOT 0x7fb0