|
Message-ID: <alpine.LRH.2.02.1902261023110.27472@key0.esi.com.au> Date: Tue, 26 Feb 2019 14:55:24 +1100 (AEDT) From: Damian McGuckin <damianm@....com.au> To: musl@...ts.openwall.com Subject: Re: FE Exception triggered by comparison Hi Markus, Thanks for taking the time to reply in depth. Where I am coming from is some research writing low level routines for a language other than C/C++, learning lessons from that, and then wanting to contribute that back some of what I have learnt in a fashion that can be used in MUSL. The metrics/goals/style in that other programming language are somewhat different to MUSL so I only want to give back what integrates well into MUSL's metrics/goals/style. That way, I do not waste anyone's time. On Mon, 25 Feb 2019, Markus Wichmann wrote: > On Mon, Feb 25, 2019 at 08:50:52AM +1100, Damian McGuckin wrote: >> The context of this is that I want a coding style which means I can >> compare numbers without affecting the exception state. And it must have >> zero overhead, and not affect the readability of the code, i.e. no >> function calls. > > Yet another problem brought to you by premature optimization. What you > want to know is if a certain number is NaN. There's a perfectly > acceptable idiom for that: > > if (isnan(x)) { > } I understand this. But, at least on an X86 architecture, that involves a write-to+read-from memory and I want to avoid that. > This (the exception stuff) is the reason why the special cases are > always front-loaded in musl. So they can be sorted out without raising > spurious exceptions. Front-loading often results in more lines of code and regularly, less lines of code means faster execution so with careful avoidance of the front-loading is feasible, I prefer it. > The only reason the above may not be acceptable to you is that it looks > like a function call. But it isn't. isnan() is a macro that doesn't > always revert to a function call. All of the fpclassify() and friends routines are quite heavy, even if they are macros and are done in line so I avoid them. That is just my opinion. Do I have a better solution for usage by the masses - No, well not in C/C++. See my later comments on builtins. >> I want to know that >> >> x != x >> >> will always detect any NaN with affecting the exception status and that >> comparisons like >> >> if (x == x) { ... } >> else if (x > y) { .... } >> else if (x < y) { .... } >> else { x or y are NaN } >> >> will similarly also not modify the exception status, and in the last >> section let me process how I interpret the NaNs. > Well, sorry, but these instructions do not work that way. Any operation > on a NaN, including comparison, even comparison for equality, will raise > IE, at least if it is an sNaN. Table 5.1 of the 20X8 standard, as I read it, and as confirmed by Kahan's lecture notes, says that neither equality nor inequality is supposed to raise an IE on a qNaN. As you rightly say, Kahan's lecture notes, the 1985 standard and Table 5.2 in the 2008 and the 2018(draft) standards says that any comparison with a '<' or '>' as part (or all) of the predicate should raise IE. However, on experiments on GCC, the if/else/else/else above does not raise an IE. Is this an optimizer bug? For a while there, I questioned my whole understanding of the standard in terms of comparison until I went back to it and re-read it. Something is weird with GCC. And either you or I has the wrong understanding of what Table 5.1 implies for both an equality and an inequality comparison. And at least mine agrees with Kahan's lecture notes. It is not the latest GCC but one that I, and clients, need to use. Note that if I manually create an sNaN and use it in the comparisons, then GCC behaves as the standard says. I wish I knew what creates an sNaN. The only optimization I use is -O3. > Honestly, though, I wonder what the big deal is. In most cases, if you > see a NaN, someone probably just made an invalid operation, or chose to > start another invalid operation with your function. In which case > raising IE is not spurious at all. I agree that in most cases it is not a big deal. And the raising of an IE is not spurious in most cases. But there are cases where it is. I tried to rewrite frexp so it can be done in line but I get an IE which is a no-no for this routine. I know that frexp is supposed to be builtin in GCC/G++ but I kept seeing the function call in the assembler so I have no idea why GCC says it is builtin. Hence my original reason for doing frexp. >> Otherwise, avoidance of creating spurious exceptions forces you to >> start working at the IEEE 754 encoding level. > > Or you could just use the interface provided by the C standard: > > if (!isnormal(x) || !isnormal(y)) { > guard clause here; > return; > } Again, memory access is the killer. Also, there is a lot of duplication in those macros that does not always get optimized away unless you rely on a built-in. And I try and stay away from things that one or another compiler thinks is a built-in. I do need to deal with subnormals but I can handle that. Besides, any comparison of subnormals does not trigger an exception unless there are arithmetic expressions as either a LHS or RHS of the comparison operator. Mind you, I once saw some code where it looks like the author did think that an underflow exception got triggered during the comparison of a possibly subnormal number against a constant which was not subnormal. > Musl strives to minimize the numeric error while also delivering good > performance, and that means that often a lot of boundary conditions can > be detected at the same time with a single comparison (e.g. you can > detect "x < 0 || x > 2**limit || isinf(x)" by detecting if the exponent > and sign bit together exceed a certain limit.) What MUSL's strives to do is indeed what I also seek. That said, I have found that you often get less lines of code and better performance if you can postpone the inspection of the IEEE 754 encoding as late as possible within a routine. It is only at that point do you think about extracting the exponent and sign cheaply. Just my 2c. Regards - Damian Pacific Engineering Systems International, 277-279 Broadway, Glebe NSW 2037 Ph:+61-2-8571-0847 .. Fx:+61-2-9692-9623 | unsolicited email not wanted here Views & opinions here are mine and not those of any past or present employer
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.