Skip to content

Commit

Permalink
S/390: Do not raise inexact exception in lrint/lround. [BZ #19486]
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Stefan Liebler committed Jan 18, 2016
1 parent 4e58b64 commit c4d1746
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 4 deletions.
21 changes: 21 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
2 changes: 2 additions & 0 deletions sysdeps/arm/fix-fp-int-convert-overflow.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
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 */
2 changes: 2 additions & 0 deletions sysdeps/generic/fix-fp-int-convert-overflow.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
7 changes: 7 additions & 0 deletions sysdeps/ieee754/ldbl-128/s_llrintl.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <math.h>

#include <math_private.h>
#include <fix-fp-int-convert-overflow.h>

static const long double two112[2] =
{
Expand Down Expand Up @@ -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;
}
Expand Down
11 changes: 9 additions & 2 deletions sysdeps/ieee754/ldbl-128/s_llroundl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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". */
Expand Down
7 changes: 7 additions & 0 deletions sysdeps/ieee754/ldbl-128/s_lrintl.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <math.h>

#include <math_private.h>
#include <fix-fp-int-convert-overflow.h>

static const long double two112[2] =
{
Expand Down Expand Up @@ -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;
}
Expand Down
11 changes: 9 additions & 2 deletions sysdeps/ieee754/ldbl-128/s_lroundl.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include <math.h>

#include <math_private.h>

#include <fix-fp-int-convert-overflow.h>

long int
__lroundl (long double x)
Expand Down Expand Up @@ -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". */
Expand Down
2 changes: 2 additions & 0 deletions sysdeps/mips/mips32/fpu/fix-fp-int-convert-overflow.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@
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
types, and those macros save and restore the whole of FSCR and so
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 */
33 changes: 33 additions & 0 deletions sysdeps/s390/fix-fp-int-convert-overflow.h
Original file line number Diff line number Diff line change
@@ -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 */

0 comments on commit c4d1746

Please sign in to comment.