libgcc2.c: Correct DI/TI -> SF/DF conversions
authorH.J. Lu <hjl@gcc.gnu.org>
Wed, 23 Jan 2019 21:41:59 +0000 (13:41 -0800)
committerH.J. Lu <hjl@gcc.gnu.org>
Wed, 23 Jan 2019 21:41:59 +0000 (13:41 -0800)
FSTYPE FUNC (DWtype u) in libgcc2.c, which converts DI/TI to SF/DF, has

  /* No leading bits means u == minimum.  */
  if (count == 0)
    return -(Wtype_MAXp1_F * (Wtype_MAXp1_F / 2));

in the third case (where actually count == 0 only means the high part is
minimum).  It should be:

  /* No leading bits means u == minimum.  */
  if (count == 0)
    return Wtype_MAXp1_F * (FSTYPE) (hi | ((UWtype) u != 0));

instead.

gcc/testsuite/

2019-01-23  H.J. Lu  <hongjiu.lu@intel.com>

PR libgcc/88931
* gcc.dg/torture/fp-int-convert-timode-1.c: New test.
* gcc.dg/torture/fp-int-convert-timode-2.c: Likewise.
* gcc.dg/torture/fp-int-convert-timode-3.c: Likewise.
* gcc.dg/torture/fp-int-convert-timode-4.c: Likewise.

libgcc/

2019-01-23  Joseph Myers  <joseph@codesourcery.com>

PR libgcc/88931
* libgcc2.c (FSTYPE FUNC (DWtype u)): Correct no leading bits
case.

From-SVN: r268216

gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-4.c [new file with mode: 0644]
libgcc/ChangeLog
libgcc/libgcc2.c

index 977009dc7f7fbf4bddedd868da121edc2bfd6589..64cd7e2f33270502ec4ac619ddb6960862ed1006 100644 (file)
@@ -1,3 +1,11 @@
+2019-01-23  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR libgcc/88931
+       * gcc.dg/torture/fp-int-convert-timode-1.c: New test.
+       * gcc.dg/torture/fp-int-convert-timode-2.c: Likewise.
+       * gcc.dg/torture/fp-int-convert-timode-3.c: Likewise.
+       * gcc.dg/torture/fp-int-convert-timode-4.c: Likewise.
+
 2019-01-23  Uroš Bizjak  <ubizjak@gmail.com>
 
        PR target/88998
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-1.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-1.c
new file mode 100644 (file)
index 0000000..d6454fa
--- /dev/null
@@ -0,0 +1,25 @@
+/* Test for correct rounding of conversions from __int128 to
+   float.  */
+/* { dg-do run } */
+/* { dg-require-effective-target int128 } */
+/* { dg-options "-frounding-math" } */
+
+#include <fenv.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  volatile unsigned long long h = 0x8000000000000000LL;
+  volatile unsigned long long l = 0xdLL;
+  volatile unsigned __int128 u128 = (((unsigned __int128) h) << 64) | l;
+  volatile __int128 s128 = u128;
+  fesetround (FE_TONEAREST);
+  float fs = s128;
+  if (fs != -0x1p+127)
+    abort ();
+  double ds = s128;
+  if (ds != -0x1p+127)
+    abort ();
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-2.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-2.c
new file mode 100644 (file)
index 0000000..dbfa481
--- /dev/null
@@ -0,0 +1,27 @@
+/* Test for correct rounding of conversions from __int128 to
+   float.  */
+/* { dg-do run } */
+/* { dg-require-effective-target int128 } */
+/* { dg-options "-frounding-math" } */
+
+#include <fenv.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+#ifdef FE_DOWNWARD
+  volatile unsigned long long h = 0x8000000000000000LL;
+  volatile unsigned long long l = 0xdLL;
+  volatile unsigned __int128 u128 = (((unsigned __int128) h) << 64) | l;
+  volatile __int128 s128 = u128;
+  fesetround (FE_DOWNWARD);
+  float fs = s128;
+  if (fs != -0x1p+127)
+    abort ();
+  double ds = s128;
+  if (ds != -0x1p+127)
+    abort ();
+#endif
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-3.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-3.c
new file mode 100644 (file)
index 0000000..63a305e
--- /dev/null
@@ -0,0 +1,27 @@
+/* Test for correct rounding of conversions from __int128 to
+   float.  */
+/* { dg-do run } */
+/* { dg-require-effective-target int128 } */
+/* { dg-options "-frounding-math" } */
+
+#include <fenv.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+#ifdef FE_UPWARD
+  volatile unsigned long long h = 0x8000000000000000LL;
+  volatile unsigned long long l = 0xdLL;
+  volatile unsigned __int128 u128 = (((unsigned __int128) h) << 64) | l;
+  volatile __int128 s128 = u128;
+  fesetround (FE_UPWARD);
+  float fs = s128;
+  if (fs != -0x1.fffffep+126)
+    abort ();
+  double ds = s128;
+  if (ds != -0x1.fffffffffffffp+126)
+    abort ();
+#endif
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-4.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-4.c
new file mode 100644 (file)
index 0000000..e716109
--- /dev/null
@@ -0,0 +1,27 @@
+/* Test for correct rounding of conversions from __int128 to
+   float.  */
+/* { dg-do run } */
+/* { dg-require-effective-target int128 } */
+/* { dg-options "-frounding-math" } */
+
+#include <fenv.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+#ifdef FE_TOWARDZERO
+  volatile unsigned long long h = 0x8000000000000000LL;
+  volatile unsigned long long l = 0xdLL;
+  volatile unsigned __int128 u128 = (((unsigned __int128) h) << 64) | l;
+  volatile __int128 s128 = u128;
+  fesetround (FE_TOWARDZERO);
+  float fs = s128;
+  if (fs != -0x1.fffffep+126)
+    abort ();
+  double ds = s128;
+  if (ds != -0x1.fffffffffffffp+126)
+    abort ();
+#endif
+  exit (0);
+}
index 9d157c2afc30d5fb474fef758d9cfb678d995e4e..8f6f9ca831114cc0f96d83b062152e549c952307 100644 (file)
@@ -1,3 +1,9 @@
+2019-01-23  Joseph Myers  <joseph@codesourcery.com>
+
+       PR libgcc/88931
+       * libgcc2.c (FSTYPE FUNC (DWtype u)): Correct no leading bits
+       case.
+
 2019-01-18  Martin Liska  <mliska@suse.cz>
 
        * libgcov-profiler.c (__gcov_indirect_call_profiler_v2): Rename
index d84f25b07799e4832b74fe2acf3c2a3424687969..04d3185e8050977cf4e99c6dddc56579d2c96681 100644 (file)
@@ -1684,7 +1684,7 @@ FUNC (DWtype u)
 
   /* No leading bits means u == minimum.  */
   if (count == 0)
-    return -(Wtype_MAXp1_F * (Wtype_MAXp1_F / 2));
+    return Wtype_MAXp1_F * (FSTYPE) (hi | ((UWtype) u != 0));
 
   shift = 1 + W_TYPE_SIZE - count;