Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!
On 2018-08-03 14:00, Houder wrote: On 2018-08-03 12:39, Corinna Vinschen wrote: On Aug 3 11:27, Houder wrote: On 2018-08-03 09:36, Corinna Vinschen wrote: [snip] > In terms of x86_64, do we have to change the fenv stuff completely > to use only SSE opcodes? Does that make sense at all? Ho! I have to disappoint you here! I am not an expert at all. Thanks all the same for your detailed description. A quick search in glibc shows that x86_64 FP exceptions in fact work somewhat different in that it additionally reads and writes from the SSE control register, e.g. sysdeps/x86_64/fpu/fesetenv.c: __asm__ ("fnstenv %0\n" "stmxcsr %1" : "=m" (*), "=m" (*__mxcsr)); [...] __asm__ ("fldenv %0\n" "ldmxcsr %1" : : "m" (temp), "m" (temp.__mxcsr)); ? ... uhm, this also happens in Korn's implementation (Cygwin). Only Dave Korn verifies if SSE is present (does the machine have SSE?). Both implementations both manage SSE and x87 FPU simultaneously. For instance fetestexcept(), i.e. show me the status flags, return status flag in SSE | status flag in x87 FPU (bit-wise "OR" of both "status registers") Both Korn and Jaeger try to hide that there are in fact two devices that do "floating-point". Can gcc generate code for both devices at the same time? Possibly! Did it in case of my _tiny_ STC? ("double d = 1.0; long l = d + 0.4") No (as far as I tell). On Linux and Cygwin 64-bits, the SSE was used. On WoW the x87 FPU was used. As far as I tell, it is neither the machine nor "fenv" that devices to switch from x87 FPU to SSE ... Why gcc prefers x87 FPU in case of WoW, I cannot tell (Yes, I a bit outspoken here; though that is my hypothesis). As a last note on this topic: My hypothesis was correct. By default gcc "uses" the x87 FPU on WoW (32-bits) and SSE on x86_64. It is NOT even possible to force gcc to use SSE on WoW (32-bits): @@ gcc -Wall -mfpmath=sse -o STC-FENV STC-FENV.c cc1: warning: SSE instruction set disabled, using 387 arithmetics It is however possible to instruct gcc to use the x87 FPU on x86_64, ... resulting in an exception where one is not expected (on x86_64): 64-@@ gcc -Wall -mfpmath=387 -o stc-last stc-last.c 64-@@ ./stc-last INITIALIZING ! Initializing fe_dfl_env Initializing fe_nomask_env Exception created! < exceptions STILL DISabled obj->_fpu._fpu_cw= 037f obj->_fpu._fpu_sw= 0004 <=== "zero-divide" flag set! obj->_fpu._fpu_tagw = obj->_fpu._fpu_ipoff = 40186f obj->_fpu._fpu_ipsel = 0 obj->_fpu._fpu_opcde = 0 obj->_fpu._fpu_dpoff = cc10 obj->_fpu._fpu_dpsel = obj->_sse_mxcsr = 1f80 Exceptions ENABLED! Floating point exception (core dumped) <=== Whao! (when SSE is used, an exception is not triggered in this case) Regards, Henri
Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!
On Aug 3 14:00, Houder wrote: > On 2018-08-03 12:39, Corinna Vinschen wrote: > > On Aug 3 11:27, Houder wrote: > > > On 2018-08-03 09:36, Corinna Vinschen wrote: > [snip] > > > > > In terms of x86_64, do we have to change the fenv stuff completely > > > > to use only SSE opcodes? Does that make sense at all? > > > > > > Ho! I have to disappoint you here! I am not an expert at all. > > > > Thanks all the same for your detailed description. A quick search in > > glibc shows that x86_64 FP exceptions in fact work somewhat different in > > that it additionally reads and writes from the SSE control register, > > e.g. sysdeps/x86_64/fpu/fesetenv.c: > > > > __asm__ ("fnstenv %0\n" > >"stmxcsr %1" : "=m" (*), "=m" (*__mxcsr)); > > [...] > > __asm__ ("fldenv %0\n" > >"ldmxcsr %1" : : "m" (temp), "m" (temp.__mxcsr)); > > ? ... uhm, this also happens in Korn's implementation (Cygwin). Only > Dave Korn verifies if SSE is present (does the machine have SSE?). Oops. Next time I check our code first. Promised :} Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat signature.asc Description: PGP signature
Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!
On 2018-08-03 14:00, Houder wrote: [snip] As far as I tell, it is neither the machine nor "fenv" that devices to switch from x87 FPU to SSE ... s/devices/decides/ Sorry.
Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!
On 2018-08-03 12:39, Corinna Vinschen wrote: On Aug 3 11:27, Houder wrote: On 2018-08-03 09:36, Corinna Vinschen wrote: [snip] > In terms of x86_64, do we have to change the fenv stuff completely > to use only SSE opcodes? Does that make sense at all? Ho! I have to disappoint you here! I am not an expert at all. Thanks all the same for your detailed description. A quick search in glibc shows that x86_64 FP exceptions in fact work somewhat different in that it additionally reads and writes from the SSE control register, e.g. sysdeps/x86_64/fpu/fesetenv.c: __asm__ ("fnstenv %0\n" "stmxcsr %1" : "=m" (*), "=m" (*__mxcsr)); [...] __asm__ ("fldenv %0\n" "ldmxcsr %1" : : "m" (temp), "m" (temp.__mxcsr)); ? ... uhm, this also happens in Korn's implementation (Cygwin). Only Dave Korn verifies if SSE is present (does the machine have SSE?). Both implementations both manage SSE and x87 FPU simultaneously. For instance fetestexcept(), i.e. show me the status flags, return status flag in SSE | status flag in x87 FPU (bit-wise "OR" of both "status registers") Both Korn and Jaeger try to hide that there are in fact two devices that do "floating-point". Can gcc generate code for both devices at the same time? Possibly! Did it in case of my _tiny_ STC? ("double d = 1.0; long l = d + 0.4") No (as far as I tell). On Linux and Cygwin 64-bits, the SSE was used. On WoW the x87 FPU was used. As far as I tell, it is neither the machine nor "fenv" that devices to switch from x87 FPU to SSE ... Why gcc prefers x87 FPU in case of WoW, I cannot tell (Yes, I a bit outspoken here; though that is my hypothesis). Regards, Henri If you're still interested in this stuff, feel free to create more patches :) Thanks, Corinna
Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!
On Aug 3 11:27, Houder wrote: > On 2018-08-03 09:36, Corinna Vinschen wrote: > > Hi J.H., > > > > Pushed with tweaks. The string in __asm__ statements works a > > Bah! Must be the heat! I did a compare (sdiff), but missed it. You > are correct: the '\n' is required. > > > bit different and I made a slight change to the commit message. > > No problem! (you could have gone even further; your command of the > English language is far better than mine). > > > In terms of x86_64, do we have to change the fenv stuff completely > > to use only SSE opcodes? Does that make sense at all? > > Ho! I have to disappoint you here! I am not an expert at all. Thanks all the same for your detailed description. A quick search in glibc shows that x86_64 FP exceptions in fact work somewhat different in that it additionally reads and writes from the SSE control register, e.g. sysdeps/x86_64/fpu/fesetenv.c: __asm__ ("fnstenv %0\n" "stmxcsr %1" : "=m" (*), "=m" (*__mxcsr)); [...] __asm__ ("fldenv %0\n" "ldmxcsr %1" : : "m" (temp), "m" (temp.__mxcsr)); If you're still interested in this stuff, feel free to create more patches :) Thanks, Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat signature.asc Description: PGP signature
Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!
On 2018-08-03 11:27, Houder wrote: I discovered a difference in behaviour between the x87 FPU and SSE. When an exception is masked, a "default action" is carried out when an exception occurs. At the same time the associated status flag is set. (the manual speaks about a "reasonable" default action, an action that is "sufficient" most of the times) When the exception is enabled again, SSE is not bothered. However the next _FPU_ statement will notice the status flag set, and will set the "Exception Summary Bit" (in the FPU's status register). To clarify: SSE has a "control and status register". The x87 FPU has a control register and a status register. Flags are only set in x87 FPU's status register when FPU statements are executed. (the FPU is not "interested" in SSE's control and status register) Henri
Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!
On 2018-08-03 09:36, Corinna Vinschen wrote: Hi J.H., Pushed with tweaks. The string in __asm__ statements works a Bah! Must be the heat! I did a compare (sdiff), but missed it. You are correct: the '\n' is required. bit different and I made a slight change to the commit message. No problem! (you could have gone even further; your command of the English language is far better than mine). In terms of x86_64, do we have to change the fenv stuff completely to use only SSE opcodes? Does that make sense at all? Ho! I have to disappoint you here! I am not an expert at all. Basically, it was Anton Lavrentiev (Cygwin ML, July 9 2018) who got me interested. I created my little STC: feenableexcept() fegetenv() fegetenv(FE_DFL_ENV) // to be switched on and off operation to provoke exception fesetenv() I could not make "head or tail" of what was happening; especially when I expected to see the exception triggered. On WoW, but also on x86_64. The standard (and manual page) that describe "fenv" is a disaster. (too me far too abstract). That is why I started comparing Cywgin with glibc. Comparing the implementation by Dave Korn (Cygwin, some 8 years ago), and that by Andreas Jaeger (glibc). Only then, I started studying the manuals written by Intel. But only as far as was required to get a grasp of what was going on. First "code-wise", next to understand the behaviour of my STC. Meaning, my focus of interest have been: fe{en,dis}ableexcept fe{get,set)env and after the repair of fegetenv(), _feinitialise(), as Dave Korn defines FE_ALL_EXCEPT different from Andreas Jaeger. (in my test environment I used Jaeger's definition, which required a slight modification of _feinitialise() ) ONLY after the above was "out of the way", I moved my attention to WoW: why did exceptions get triggered here, while they were NOT on x86_64 ? I discovered a difference in behaviour between the x87 FPU and SSE. When an exception is masked, a "default action" is carried out when an exception occurs. At the same time the associated status flag is set. (the manual speaks about a "reasonable" default action, an action that is "sufficient" most of the times) When the exception is enabled again, SSE is not bothered. However the next _FPU_ statement will notice the status flag set, and will set the "Exception Summary Bit" (in the FPU's status register). The next FPU statement after will trigger the exception! (Yes, the triggering of the exception is "delayed", deferred). You can read all this in Intel's manuals. Bottom-line, if the FPU is used, and exceptions are enabled again, one must _first_ clear all exceptions (again, not needed on SSE). Returning to your question ... From "a logical point of view", Korn's implementation is more or less the same as Jaeger's implementation. Why is there "a preference for the x87 FPU" on WoW, I cannot tell. Why does "using double d = 1.0; long l = d + 0.4" on WoW result in code that is executed on the x87 FPU ? (and why does the reverse occur on x86_64)? (Yes, that is my hypothesis!) I cannot tell. Perhaps it is gcc ... I did not investigate any further. Regards, Henri
Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!
Hi J.H., On Aug 3 01:45, J.H. van de Water wrote: > fegetenv() in winsup/cygwin/fenv.cc > > fnstenv MUST be followed by fldenv in fegetenv(), as the former disables all > exceptions in the x87 FPU, which is not appropriate here (fegetenv() ). > fldenv after fnstenv should reload the x87 FPU w/ the configuration that was > saved by fnstenv, i.e. a configuration that might have exceptions enabled. > > Note: x86_64 uses SSE for floating-point, not the x87 FPU. However, because > feraiseexcept() attempts to provoke an exception using the x87 FPU, the bug > in fegetenv() will make this attempt futile here (x86_64). > > Note: WoW uses the x87 FPU for floating-point, not SSE. Here anything that > would normally result in triggering an exception, not only feraiseexcept(), > will not be able to, as result of the bug in fegetenv(). > --- > winsup/cygwin/fenv.cc | 5 - > 1 file changed, 4 insertions(+), 1 deletion(-) > > diff --git a/winsup/cygwin/fenv.cc b/winsup/cygwin/fenv.cc > index bd3f904..eb5260c 100644 > --- a/winsup/cygwin/fenv.cc > +++ b/winsup/cygwin/fenv.cc > @@ -141,7 +141,10 @@ fegetexcept (void) > int > fegetenv (fenv_t *envp) > { > - __asm__ volatile ("fnstenv %0" : "=m" (envp->_fpu) : ); > + /* fnstenv disables all exceptions in the x87 FPU; as this is not what is > + desired here, reload the cfg saved from the x87 FPU, back to the FPU */ > + __asm__ volatile ("fnstenv %0" > +"fldenv %0" : "=m" (envp->_fpu) : ); >if (use_sse) > __asm__ volatile ("stmxcsr %0" : "=m" (envp->_sse_mxcsr) : ); >return 0; > -- > 2.7.5 Thank you! Pushed with tweaks. The string in __asm__ statements works a bit different and I made a slight change to the commit message. In terms of x86_64, do we have to change the fenv stuff completely to use only SSE opcodes? Does that make sense at all? Thanks, Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat signature.asc Description: PGP signature