This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
libgo patch committed: Return random number of hash of NaN
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org, gofrontend-dev at googlegroups dot com
- Date: Fri, 21 Sep 2012 23:06:55 -0700
- Subject: libgo patch committed: Return random number of hash of NaN
It is valid to store a NaN in a Go hash table. However, the result can
not be looked up, because NaN never equals NaN. The only way to see the
result is to range over the map. This means that the hash code used for
a NaN is irrelevant. In general it's better to not hash all NaN values
to the same bucket, so this patch simply uses a random number.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline and 4.7 branch.
Ian
diff -r 895a5e834a7b libgo/runtime/go-type-complex.c
--- a/libgo/runtime/go-type-complex.c Fri Sep 21 23:01:55 2012 -0700
+++ b/libgo/runtime/go-type-complex.c Fri Sep 21 23:03:04 2012 -0700
@@ -32,10 +32,14 @@
cf = ucf.cf;
cfr = __builtin_crealf (cf);
cfi = __builtin_cimagf (cf);
- if (__builtin_isinff (cfr) || __builtin_isinff (cfi)
- || __builtin_isnanf (cfr) || __builtin_isnanf (cfi))
+ if (__builtin_isinff (cfr) || __builtin_isinff (cfi))
return 0;
+ /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it
+ random so that not all NaNs wind up in the same place. */
+ if (__builtin_isnanf (cfr) || __builtin_isnanf (cfi))
+ return runtime_fastrand1 ();
+
/* Avoid negative zero. */
if (cfr == 0 && cfi == 0)
return 0;
@@ -62,10 +66,12 @@
cd = ucd.cd;
cdr = __builtin_crealf (cd);
cdi = __builtin_cimagf (cd);
- if (__builtin_isinf (cdr) || __builtin_isinf (cdi)
- || __builtin_isnan (cdr) || __builtin_isnan (cdi))
+ if (__builtin_isinf (cdr) || __builtin_isinf (cdi))
return 0;
+ if (__builtin_isnan (cdr) || __builtin_isnan (cdi))
+ return runtime_fastrand1 ();
+
/* Avoid negative zero. */
if (cdr == 0 && cdi == 0)
return 0;
diff -r 895a5e834a7b libgo/runtime/go-type-float.c
--- a/libgo/runtime/go-type-float.c Fri Sep 21 23:01:55 2012 -0700
+++ b/libgo/runtime/go-type-float.c Fri Sep 21 23:03:04 2012 -0700
@@ -29,8 +29,14 @@
__builtin_memcpy (uf.a, vkey, 4);
f = uf.f;
- if (__builtin_isinff (f) || __builtin_isnanf (f) || f == 0)
+ if (__builtin_isinff (f) || f == 0)
return 0;
+
+ /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it
+ random so that not all NaNs wind up in the same place. */
+ if (__builtin_isnanf (f))
+ return runtime_fastrand1 ();
+
return (uintptr_t) uf.si;
}
else if (key_size == 8)
@@ -45,8 +51,12 @@
__builtin_memcpy (ud.a, vkey, 8);
d = ud.d;
- if (__builtin_isinf (d) || __builtin_isnan (d) || d == 0)
+ if (__builtin_isinf (d) || d == 0)
return 0;
+
+ if (__builtin_isnan (d))
+ return runtime_fastrand1 ();
+
return (uintptr_t) ud.di;
}
else