This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix real_maxval for IBM long double (PR target/36904)


Hi!

The following testcase as well as gcc.dg/torture/type-generic-1.c
and g++.dg/torture/type-generic-1.C fail on powerpc-linux.

The problem is mismatch in what is actually the largest representable
normal value in the IBM long double format.  In GCC there are two routines
to query that, get_max_float which generates a string and is used for
e.g. the __LDBL_MAX__ define, and then real_maxval, which is used
by fold_inf_compare and OpenMP reductions.
The former gives a number with memory representation:
0x7fefffffffffffff, 0x7c8ffffffffffffe
and struct real_value
{.cl = 1, .decimal = 0, .sign = 0, .signalling = 0, .canonical = 0, .uexp = 0x400, .sig = {0x0, 0xffffffffffc00000, 0xfffffffffffffbff}}
the latter:
0x7fefffffffffffff, 0xf950000000000000
{.cl = 1, .decimal = 0, .sign = 0, .signalling = 0, .canonical = 0, .uexp = 0x400, .sig = {0x0, 0xffffffffffc00000, 0xfffffffffffffbff}}
Due to the mismatch, __LONG_DOUBLE_MAX__ == __builtin_infl ()
runtime comparison is folded into
__LONG_DOUBLE_MAX__ > ((union { long long a[2]; long double ld; }) { .a[0] = 0x7fefffffffffffff, .a[1] = 0xf950000000000000 } ).ld

The following patch fixes that by using the same value in real_maxval
as in get_max_float.  Ok for trunk/4.3?

2008-09-01  Jakub Jelinek  <jakub@redhat.com>

	PR target/36332
	* real.c (real_maxval): Clear a lower bit to make real_maxval
	match get_max_float for IBM long double format.

	* gcc.c-torture/execute/ieee/pr36332.c: New test.

--- gcc/real.c.jj	2008-08-19 14:20:31.000000000 +0200
+++ gcc/real.c	2008-09-01 19:15:51.000000000 +0200
@@ -2417,7 +2417,7 @@ real_maxval (REAL_VALUE_TYPE *r, int sig
 	   required to be the value of the long double rounded to the
 	   nearest double.  Rounding means we need a slightly smaller
 	   value for LDBL_MAX.  */
-        clear_significand_bit (r, SIGNIFICAND_BITS - fmt->pnan);
+	clear_significand_bit (r, SIGNIFICAND_BITS - fmt->pnan - 1);
     }
 }
 
--- gcc/testsuite/gcc.c-torture/execute/ieee/pr36332.c.jj	2008-09-01 19:28:03.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/execute/ieee/pr36332.c	2008-09-01 19:27:48.000000000 +0200
@@ -0,0 +1,15 @@
+/* PR target/36332 */
+
+int __attribute__((noinline, used))
+foo (long double ld)
+{
+  return ld == __builtin_infl ();
+}
+
+int
+main ()
+{
+  if (foo (__LDBL_MAX__))
+    __builtin_abort ();
+  return 0;
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]