]> sourceware.org Git - glibc.git/commitdiff
S/390: Do not raise inexact exception in lrint/lround. [BZ #19486]
authorStefan Liebler <stli@de.ibm.com>
Mon, 18 Jan 2016 11:48:06 +0000 (12:48 +0100)
committerStefan Liebler <stli@de.ibm.com>
Mon, 18 Jan 2016 11:48:06 +0000 (12:48 +0100)
I get some math test-failures on s390 for float/double/ldouble for
various lrint/lround functions like:
lrint (0x1p64): Exception "Inexact" set
lrint (-0x1p64): Exception "Inexact" set
lround (0x1p64): Exception "Inexact" set
lround (-0x1p64): Exception "Inexact" set
...

GCC emits "convert to fixed" instructions for casting floating point
values to integer values. These instructions raise invalid and inexact
exceptions if the floating point value exceeds the integer type ranges.

This patch enables the various FIX_DBL_LONG_CONVERT_OVERFLOW macros in
order to avoid a cast from floating point to integer type and raise the
invalid exception with feraiseexcept.
The ldbl-128 rint/round functions are now using the same logic.

ChangeLog:

[BZ #19486]
* sysdeps/s390/fix-fp-int-convert-overflow.h: New File.
* sysdeps/generic/fix-fp-int-convert-overflow.h
(FIX_LDBL_LONG_CONVERT_OVERFLOW,
FIX_LDBL_LLONG_CONVERT_OVERFLOW): New define.
* sysdeps/arm/fix-fp-int-convert-overflow.h: Likewise.
* sysdeps/mips/mips32/fpu/fix-fp-int-convert-overflow.h:
Likewise.
* sysdeps/ieee754/ldbl-128/s_lrintl.c (__lrintl):
Avoid conversions to long int where inexact exceptions
could be raised.
* sysdeps/ieee754/ldbl-128/s_lroundl.c (__lroundl):
Likewise.
* sysdeps/ieee754/ldbl-128/s_llrintl.c (__llrintl):
Avoid conversions to long long int where inexact exceptions
could be raised.
* sysdeps/ieee754/ldbl-128/s_llroundl.c (__llroundl):
Likewise.

ChangeLog
sysdeps/arm/fix-fp-int-convert-overflow.h
sysdeps/generic/fix-fp-int-convert-overflow.h
sysdeps/ieee754/ldbl-128/s_llrintl.c
sysdeps/ieee754/ldbl-128/s_llroundl.c
sysdeps/ieee754/ldbl-128/s_lrintl.c
sysdeps/ieee754/ldbl-128/s_lroundl.c
sysdeps/mips/mips32/fpu/fix-fp-int-convert-overflow.h
sysdeps/s390/fix-fp-int-convert-overflow.h [new file with mode: 0644]

index eaadfbaae8e773b0d12c78d3da5a93935e1f057b..d42bb6d0e54f72dbe8acd89c1737d86218128aff 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2016-01-15  Stefan Liebler  <stli@linux.vnet.ibm.com>
+
+       [BZ #19486]
+       * sysdeps/s390/fix-fp-int-convert-overflow.h: New File.
+       * sysdeps/generic/fix-fp-int-convert-overflow.h
+       (FIX_LDBL_LONG_CONVERT_OVERFLOW,
+       FIX_LDBL_LLONG_CONVERT_OVERFLOW): New define.
+       * sysdeps/arm/fix-fp-int-convert-overflow.h: Likewise.
+       * sysdeps/mips/mips32/fpu/fix-fp-int-convert-overflow.h:
+       Likewise.
+       * sysdeps/ieee754/ldbl-128/s_lrintl.c (__lrintl):
+       Avoid conversions to long int where inexact exceptions
+       could be raised.
+       * sysdeps/ieee754/ldbl-128/s_lroundl.c (__lroundl):
+       Likewise.
+       * sysdeps/ieee754/ldbl-128/s_llrintl.c (__llrintl):
+       Avoid conversions to long long int where inexact exceptions
+       could be raised.
+       * sysdeps/ieee754/ldbl-128/s_llroundl.c (__llroundl):
+       Likewise.
+
 2016-01-17  Mike Frysinger  <vapier@gentoo.org>
 
        * configure.ac: Rewrite error comment and use AC_MSG_ERROR.
index fcc2199c04d83128ff692a73374ec6e77e0966a0..c5ec50a433cd78114dff8458239a1e511518eaa7 100644 (file)
    see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59412>).  */
 #define FIX_FLT_LLONG_CONVERT_OVERFLOW 1
 #define FIX_DBL_LLONG_CONVERT_OVERFLOW 1
+#define FIX_LDBL_LLONG_CONVERT_OVERFLOW 0
 
 #define FIX_FLT_LONG_CONVERT_OVERFLOW 0
 #define FIX_DBL_LONG_CONVERT_OVERFLOW 0
+#define FIX_LDBL_LONG_CONVERT_OVERFLOW 0
 
 #endif /* fix-fp-int-convert-overflow.h */
index 73884a61b31693a39eaf799fb4ca8ea60dd7f71b..fb681147c0a3c4c3b0925af4f7e0fed34409556e 100644 (file)
@@ -27,5 +27,7 @@
 #define FIX_FLT_LLONG_CONVERT_OVERFLOW 0
 #define FIX_DBL_LONG_CONVERT_OVERFLOW 0
 #define FIX_DBL_LLONG_CONVERT_OVERFLOW 0
+#define FIX_LDBL_LONG_CONVERT_OVERFLOW 0
+#define FIX_LDBL_LLONG_CONVERT_OVERFLOW 0
 
 #endif /* fix-fp-int-convert-overflow.h */
index 445cde5b2e285690e95d19dfa6d549501a4394eb..84fc576ab6f78fa495c0dd8ec6a61606815694c7 100644 (file)
@@ -24,6 +24,7 @@
 #include <math.h>
 
 #include <math_private.h>
+#include <fix-fp-int-convert-overflow.h>
 
 static const long double two112[2] =
 {
@@ -91,6 +92,12 @@ __llrintl (long double x)
          feraiseexcept (t == LLONG_MIN ? FE_INEXACT : FE_INVALID);
          return LLONG_MIN;
        }
+      else if (FIX_LDBL_LLONG_CONVERT_OVERFLOW && x != (long double) LLONG_MIN)
+       {
+         feraiseexcept (FE_INVALID);
+         return sx == 0 ? LLONG_MAX : LLONG_MIN;
+       }
+
 #endif
       return (long long int) x;
     }
index e5dd14533396ea5582e5c9062092f7e21ee12fe2..bfc81cc53448f26c4dbcfa6fb7364f64aef7afda 100644 (file)
@@ -23,7 +23,7 @@
 #include <math.h>
 
 #include <math_private.h>
-
+#include <fix-fp-int-convert-overflow.h>
 
 long long int
 __llroundl (long double x)
@@ -78,7 +78,14 @@ __llroundl (long double x)
         FE_INVALID must be raised and the return value is
         unspecified.  */
 #ifdef FE_INVALID
-      if (x <= (long double) LLONG_MIN - 0.5L)
+      if (FIX_LDBL_LLONG_CONVERT_OVERFLOW
+         && !(sign == -1 && x > (long double) LLONG_MIN - 0.5L))
+       {
+         feraiseexcept (FE_INVALID);
+         return sign == 1 ? LLONG_MAX : LLONG_MIN;
+       }
+      else if (!FIX_LDBL_LLONG_CONVERT_OVERFLOW
+              && x <= (long double) LLONG_MIN - 0.5L)
        {
          /* If truncation produces LLONG_MIN, the cast will not raise
             the exception, but may raise "inexact".  */
index ff4780a4666a8c74842c6ebfb007f6f8284df59f..23f828f8623bd9ba38efb07de7e0df216feedb61 100644 (file)
@@ -24,6 +24,7 @@
 #include <math.h>
 
 #include <math_private.h>
+#include <fix-fp-int-convert-overflow.h>
 
 static const long double two112[2] =
 {
@@ -120,6 +121,12 @@ __lrintl (long double x)
          feraiseexcept (t == LONG_MIN ? FE_INEXACT : FE_INVALID);
          return LONG_MIN;
        }
+      else if (FIX_LDBL_LONG_CONVERT_OVERFLOW && x != (long double) LONG_MIN)
+       {
+         feraiseexcept (FE_INVALID);
+         return sx == 0 ? LONG_MAX : LONG_MIN;
+       }
+
 #endif
       return (long int) x;
     }
index 34d226445f2c601f15449e33cd5443bb66d0d423..f03262543fb072dffe48f291e89ab0b8ce2c8a99 100644 (file)
@@ -23,7 +23,7 @@
 #include <math.h>
 
 #include <math_private.h>
-
+#include <fix-fp-int-convert-overflow.h>
 
 long int
 __lroundl (long double x)
@@ -87,7 +87,14 @@ __lroundl (long double x)
         FE_INVALID must be raised and the return value is
         unspecified.  */
 #ifdef FE_INVALID
-      if (x <= (long double) LONG_MIN - 0.5L)
+      if (FIX_LDBL_LONG_CONVERT_OVERFLOW
+         && !(sign == -1 && x > (long double) LONG_MIN - 0.5L))
+       {
+         feraiseexcept (FE_INVALID);
+         return sign == 1 ? LONG_MAX : LONG_MIN;
+       }
+      else if (!FIX_LDBL_LONG_CONVERT_OVERFLOW
+              && x <= (long double) LONG_MIN - 0.5L)
        {
          /* If truncation produces LONG_MIN, the cast will not raise
             the exception, but may raise "inexact".  */
index fb2ec69b2c200e294c5061a1991dbcff5a1223fa..b9f4aea488dbd23fae16406f9f32392de5857d45 100644 (file)
@@ -25,6 +25,7 @@
    see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59412>).  */
 #define FIX_FLT_LLONG_CONVERT_OVERFLOW 1
 #define FIX_DBL_LLONG_CONVERT_OVERFLOW 1
+#define FIX_LDBL_LLONG_CONVERT_OVERFLOW 0
 
 /* As of GCC 5 and binutils 2.25, for MIPS I GCC generates calls to
    assembler macros for conversions from floating point to integer
@@ -32,5 +33,6 @@
    lose exceptions.  */
 #define FIX_FLT_LONG_CONVERT_OVERFLOW (__mips == 1)
 #define FIX_DBL_LONG_CONVERT_OVERFLOW (__mips == 1)
+#define FIX_LDBL_LONG_CONVERT_OVERFLOW 0
 
 #endif /* fix-fp-int-convert-overflow.h */
diff --git a/sysdeps/s390/fix-fp-int-convert-overflow.h b/sysdeps/s390/fix-fp-int-convert-overflow.h
new file mode 100644 (file)
index 0000000..61279ed
--- /dev/null
@@ -0,0 +1,33 @@
+/* Fix for conversion of floating point to integer overflow.  S390 version.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef FIX_FP_INT_CONVERT_OVERFLOW_H
+#define FIX_FP_INT_CONVERT_OVERFLOW_H  1
+
+/* GCC emits "convert to fixed" instructions for casting floating point values
+   to integer values. These instructions raise invalid and inexact exceptions
+   if the floating point value exceeds the integer type ranges.  */
+#define FIX_FLT_LLONG_CONVERT_OVERFLOW 1
+#define FIX_DBL_LLONG_CONVERT_OVERFLOW 1
+#define FIX_LDBL_LLONG_CONVERT_OVERFLOW 1
+
+#define FIX_FLT_LONG_CONVERT_OVERFLOW 1
+#define FIX_DBL_LONG_CONVERT_OVERFLOW 1
+#define FIX_LDBL_LONG_CONVERT_OVERFLOW 1
+
+#endif /* fix-fp-int-convert-overflow.h */
This page took 0.188903 seconds and 5 git commands to generate.