bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: mingw isnanl-nolibm failure


From: Eric Blake
Subject: Re: mingw isnanl-nolibm failure
Date: Tue, 11 Dec 2007 18:40:49 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

Bruno Haible <bruno <at> clisp.org> writes:

> Ack. It's a bug in the isnanl module.
> 
> > I'm not sure how to fix this, but it seems like rpl_isnanl needs to check 
for 
> > invalid x86 long double bit patterns before falling back to ==.
> 
> Either this, or ensure that the "checking where to find the exponent" tests
> return the bit positions instead of "unknown".
> 
> But I don't see how to implement either of these two possible fixes for a
> cross-compiler, in a way that works also for other platforms than mingw.
> Any ideas?

Here's one idea.  Since it fixes the mingw cross-compilation failure of test-
isnanl-nolibm, I'm installing it; if we come up with something better or more 
efficient in the future, we can alter the test then.

The idea behind this patch is that = doesn't alter the bit pattern of an 
invalid representation that sneaks past the == check, but +0 will result in a 
normalized bit pattern, so that the memcmp can then filter out pseudo-
denormals.  For all valid bit patterns, the == already filtered out NaN, so 
adding +0.0 is a no-op to the bit pattern.  Here's a snippet of my gdb session 
on mingw that shows this point (where sizeof(long double) is 12):

142       if (x == x)
(gdb) n
149           m1.value = x;
(gdb) n
150           m2.value = x + 0;
(gdb) x/3w &x
0x22ff50:       0x00000000      0x83333333      0x00000000
(gdb) x/3w &m1
0x22ff30:       0x00000000      0x83333333      0x00000000
(gdb) x/3w &m2
0x22ff20:       0x00000000      0x83333333      0x00000001


From: Eric Blake <address@hidden>
Date: Tue, 11 Dec 2007 11:35:55 -0700
Subject: [PATCH] Detect pseudo-denormals on x86 even when cross-compiling.

* lib/isnan.c (rpl_isnanl) [!KNOWN_EXPBIT0_LOCATION
&& USE_LONG_DOUBLE && x86]: Add one more check to filter out
invalid bit patterns that happen to satisfy ==.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog   |    5 +++++
 lib/isnan.c |   14 +++++++++++++-
 2 files changed, 18 insertions(+), 1 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ed8799b..127f9a5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2007-12-11  Eric Blake  <address@hidden>
 
+       Detect pseudo-denormals on x86 even when cross-compiling.
+       * lib/isnan.c (rpl_isnanl) [!KNOWN_EXPBIT0_LOCATION
+       && USE_LONG_DOUBLE && x86]: Add one more check to filter out
+       invalid bit patterns that happen to satisfy ==.
+
        Avoid link failures with separate libtests.a.
        * gnulib-tool (func_emit_tests_Makefile_am): Also list local_ldadd
        last, to satisfy circular dependencies.
diff --git a/lib/isnan.c b/lib/isnan.c
index 4add6a2..182a7bd 100644
--- a/lib/isnan.c
+++ b/lib/isnan.c
@@ -140,7 +140,19 @@ FUNC (DOUBLE x)
   /* The configuration did not find sufficient information.  Give up about
      the signaling NaNs, handle only the quiet NaNs.  */
   if (x == x)
-    return 0;
+    {
+# if defined USE_LONG_DOUBLE && ((defined __ia64 && LDBL_MANT_DIG == 64) || 
(defined __x86_64__ || defined __amd64__) || (defined __i386 || defined 
__i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+      /* Detect any special bit patterns that pass ==; see comment above.  */
+      memory_double m1;
+      memory_double m2;
+
+      m1.value = x;
+      m2.value = x + 0;
+      if (memcmp (&m1.value, &m2.value, SIZE) != 0)
+        return 1;
+# endif
+      return 0;
+    }
   else
     return 1;
 #endif
-- 
1.5.3.5






reply via email to

[Prev in Thread] Current Thread [Next in Thread]