[Top][All Lists]
[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