This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc 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]

GNU C Library master sources branch master updated. glibc-2.23-516-g30dcf95


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  30dcf959d2ab76f0bc8b5bc147c35319a6a2ba08 (commit)
       via  623629de066dc2f404470e76ff074fc5ba643c6c (commit)
       via  26b0bf96000a825ad3381be52ebd8adf2afc785f (commit)
      from  b87c1ec3fa398646f042a68f0ce0f7d09c1348c7 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=30dcf959d2ab76f0bc8b5bc147c35319a6a2ba08

commit 30dcf959d2ab76f0bc8b5bc147c35319a6a2ba08
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Mon Jun 27 17:26:52 2016 +0000

    Avoid "inexact" exceptions in i386/x86_64 trunc functions (bug 15479).
    
    As discussed in
    <https://sourceware.org/ml/libc-alpha/2016-05/msg00577.html>, TS
    18661-1 disallows ceil, floor, round and trunc functions from raising
    the "inexact" exception, in accordance with general IEEE 754 semantics
    for when that exception is raised.  Fixing this for x87 floating point
    is more complicated than for the other versions of these functions,
    because they use the frndint instruction that raises "inexact" and
    this can only be avoided by saving and restoring the whole
    floating-point environment.
    
    As I noted in
    <https://sourceware.org/ml/libc-alpha/2016-06/msg00128.html>, I have
    now implemented a GCC option -fno-fp-int-builtin-inexact for GCC 7,
    such that GCC will inline these functions on x86, without caring about
    "inexact", when the default -ffp-int-builtin-inexact is in effect.
    This allows users to get optimized code depending on the options they
    pass to the compiler, while making the out-of-line functions follow TS
    18661-1 semantics and avoid "inexact".
    
    This patch duly fixes the out-of-line trunc function implementations
    to avoid "inexact", in the same way as the nearbyint implementations.
    
    I do not know how the performance of implementations such as these
    based on saving the environment and changing the rounding mode
    temporarily compares to that of the C versions or SSE 4.1 versions (of
    course, for 32-bit x86 SSE implementations still need to get the
    return value in an x87 register); it's entirely possible other
    implementations could be faster in some cases.
    
    Tested for x86_64 and x86.
    
    	[BZ #15479]
    	* sysdeps/i386/fpu/s_trunc.S (__trunc): Save and restore
    	floating-point environment rather than just control word.
    	* sysdeps/i386/fpu/s_truncf.S (__truncf): Likewise.
    	* sysdeps/i386/fpu/s_truncl.S (__truncl): Save and restore
    	floating-point environment, with "invalid" exceptions merged in,
    	rather than just control word.
    	* sysdeps/x86_64/fpu/s_truncl.S (__truncl): Likewise.
    	* math/libm-test.inc (trunc_test_data): Do not allow spurious
    	"inexact" exceptions.

diff --git a/ChangeLog b/ChangeLog
index a67e532..47c12b4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,17 @@
 2016-06-27  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15479]
+	* sysdeps/i386/fpu/s_trunc.S (__trunc): Save and restore
+	floating-point environment rather than just control word.
+	* sysdeps/i386/fpu/s_truncf.S (__truncf): Likewise.
+	* sysdeps/i386/fpu/s_truncl.S (__truncl): Save and restore
+	floating-point environment, with "invalid" exceptions merged in,
+	rather than just control word.
+	* sysdeps/x86_64/fpu/s_truncl.S (__truncl): Likewise.
+	* math/libm-test.inc (trunc_test_data): Do not allow spurious
+	"inexact" exceptions.
+
+	[BZ #15479]
 	* sysdeps/i386/fpu/s_floor.S (__floor): Save and restore
 	floating-point environment rather than just control word.
 	* sysdeps/i386/fpu/s_floorf.S (__floorf): Likewise.
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 9f6e21d..4ac7a0c 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -12112,9 +12112,8 @@ static const struct test_f_f_data trunc_test_data[] =
 
     TEST_f_f (trunc, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (trunc, minus_zero, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
-    /* Bug 15479: spurious "inexact" exception may occur.  */
-    TEST_f_f (trunc, min_subnorm_value, 0.0, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, min_value, 0.0, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, min_subnorm_value, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, min_value, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (trunc, 1, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (trunc, 2, 2, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (trunc, 0x1p23, 0x1p23, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
@@ -12133,8 +12132,8 @@ static const struct test_f_f_data trunc_test_data[] =
     TEST_f_f (trunc, 0x1p113, 0x1p113, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (trunc, 0x1p114, 0x1p114, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (trunc, max_value, max_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -min_subnorm_value, minus_zero, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -min_value, minus_zero, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -min_subnorm_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -min_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (trunc, -1, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (trunc, -2, -2, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (trunc, -0x1p23, -0x1p23, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
@@ -12154,108 +12153,108 @@ static const struct test_f_f_data trunc_test_data[] =
     TEST_f_f (trunc, -0x1p114, -0x1p114, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (trunc, -max_value, -max_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
-    TEST_f_f (trunc, 0.1, 0, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 0.25, 0, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 0.625, 0, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -0.1, minus_zero, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -0.25, minus_zero, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -0.625, minus_zero, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 0.1, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 0.25, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 0.625, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -0.1, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -0.25, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -0.625, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (trunc, 1, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (trunc, -1, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 1.625, 1, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -1.625, -1, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 1.625, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -1.625, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
-    TEST_f_f (trunc, 1048580.625L, 1048580L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -1048580.625L, -1048580L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 1048580.625L, 1048580L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -1048580.625L, -1048580L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
-    TEST_f_f (trunc, 8388610.125L, 8388610.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -8388610.125L, -8388610.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 8388610.125L, 8388610.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -8388610.125L, -8388610.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
-    TEST_f_f (trunc, 4294967296.625L, 4294967296.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -4294967296.625L, -4294967296.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 4294967296.625L, 4294967296.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -4294967296.625L, -4294967296.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 #if MANT_DIG >= 64
     /* The result can only be represented in long double.  */
-    TEST_f_f (trunc, 4503599627370495.5L, 4503599627370495.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 4503599627370496.25L, 4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 4503599627370496.5L, 4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 4503599627370496.75L, 4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 4503599627370497.5L, 4503599627370497.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 4503599627370495.5L, 4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 4503599627370496.25L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 4503599627370496.5L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 4503599627370496.75L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 4503599627370497.5L, 4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 # if MANT_DIG > 100
-    TEST_f_f (trunc, 4503599627370494.5000000000001L, 4503599627370494.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 4503599627370495.5000000000001L, 4503599627370495.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 4503599627370496.5000000000001L, 4503599627370496.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 4503599627370494.5000000000001L, 4503599627370494.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 4503599627370495.5000000000001L, 4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 4503599627370496.5000000000001L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (trunc, -4503599627370495.5L, -4503599627370495.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -4503599627370496.25L, -4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -4503599627370496.5L, -4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -4503599627370496.75L, -4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -4503599627370497.5L, -4503599627370497.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -4503599627370495.5L, -4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -4503599627370496.25L, -4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -4503599627370496.5L, -4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -4503599627370496.75L, -4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -4503599627370497.5L, -4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 # if MANT_DIG > 100
-    TEST_f_f (trunc, -4503599627370494.5000000000001L, -4503599627370494.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -4503599627370495.5000000000001L, -4503599627370495.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -4503599627370496.5000000000001L, -4503599627370496.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -4503599627370494.5000000000001L, -4503599627370494.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -4503599627370495.5000000000001L, -4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -4503599627370496.5000000000001L, -4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (trunc, 9007199254740991.5L, 9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 9007199254740992.25L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 9007199254740992.5L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 9007199254740992.75L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 9007199254740993.5L, 9007199254740993.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 9007199254740991.5L, 9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 9007199254740992.25L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 9007199254740992.5L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 9007199254740992.75L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 9007199254740993.5L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 # if MANT_DIG > 100
-    TEST_f_f (trunc, 9007199254740991.0000000000001L, 9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 9007199254740992.0000000000001L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 9007199254740993.0000000000001L, 9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 9007199254740991.5000000000001L, 9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 9007199254740992.5000000000001L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 9007199254740993.5000000000001L, 9007199254740993.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 9007199254740991.0000000000001L, 9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 9007199254740992.0000000000001L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 9007199254740993.0000000000001L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 9007199254740991.5000000000001L, 9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 9007199254740992.5000000000001L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 9007199254740993.5000000000001L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (trunc, -9007199254740991.5L, -9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -9007199254740992.25L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -9007199254740992.5L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -9007199254740992.75L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -9007199254740993.5L, -9007199254740993.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -9007199254740991.5L, -9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -9007199254740992.25L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -9007199254740992.5L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -9007199254740992.75L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -9007199254740993.5L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 # if MANT_DIG > 100
-    TEST_f_f (trunc, -9007199254740991.0000000000001L, -9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -9007199254740992.0000000000001L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -9007199254740993.0000000000001L, -9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -9007199254740991.5000000000001L, -9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -9007199254740992.5000000000001L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -9007199254740993.5000000000001L, -9007199254740993.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -9007199254740991.0000000000001L, -9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -9007199254740992.0000000000001L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -9007199254740993.0000000000001L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -9007199254740991.5000000000001L, -9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -9007199254740992.5000000000001L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -9007199254740993.5000000000001L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (trunc, 72057594037927935.5L, 72057594037927935.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 72057594037927936.25L, 72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 72057594037927936.5L, 72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 72057594037927936.75L, 72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 72057594037927937.5L, 72057594037927937.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 72057594037927935.5L, 72057594037927935.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 72057594037927936.25L, 72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 72057594037927936.5L, 72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 72057594037927936.75L, 72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 72057594037927937.5L, 72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
-    TEST_f_f (trunc, -72057594037927935.5L, -72057594037927935.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -72057594037927936.25L, -72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -72057594037927936.5L, -72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -72057594037927936.75L, -72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -72057594037927937.5L, -72057594037927937.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -72057594037927935.5L, -72057594037927935.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -72057594037927936.25L, -72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -72057594037927936.5L, -72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -72057594037927936.75L, -72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -72057594037927937.5L, -72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
     /* Check cases where first double is a exact integer higher than 2^52 and
        the precision is determined by second long double for IBM long double.  */
-    TEST_f_f (trunc,  34503599627370498.515625L, 34503599627370498.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -34503599627370498.515625L, -34503599627370498.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc,  34503599627370498.515625L, 34503599627370498.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -34503599627370498.515625L, -34503599627370498.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # if MANT_DIG >= 106
-    TEST_f_f (trunc,  1192568192774434123539907640624.484375L, 1192568192774434123539907640624.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, -1192568192774434123539907640624.484375L, -1192568192774434123539907640624.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc,  1192568192774434123539907640624.484375L, 1192568192774434123539907640624.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -1192568192774434123539907640624.484375L, -1192568192774434123539907640624.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (trunc, 10141204801825835211973625643007.5L, 10141204801825835211973625643007.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 10141204801825835211973625643008.5L, 10141204801825835211973625643008.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 10141204801825835211973625643008.75L, 10141204801825835211973625643008.0L, ERRNO_UNCHANGED),
-    TEST_f_f (trunc, 10141204801825835211973625643009.5L, 10141204801825835211973625643009.0L, ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 10141204801825835211973625643007.5L, 10141204801825835211973625643007.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 10141204801825835211973625643008.5L, 10141204801825835211973625643008.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 10141204801825835211973625643008.75L, 10141204801825835211973625643008.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, 10141204801825835211973625643009.5L, 10141204801825835211973625643009.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 #endif
   };
 
diff --git a/sysdeps/i386/fpu/s_trunc.S b/sysdeps/i386/fpu/s_trunc.S
index a15e5e5..8d9a6df 100644
--- a/sysdeps/i386/fpu/s_trunc.S
+++ b/sysdeps/i386/fpu/s_trunc.S
@@ -21,17 +21,17 @@
 
 ENTRY(__trunc)
 	fldl	4(%esp)
-	subl	$8, %esp
-	cfi_adjust_cfa_offset (8)
-	fstcw	4(%esp)
+	subl	$32, %esp
+	cfi_adjust_cfa_offset (32)
+	fnstenv	4(%esp)
 	movl	$0xc00, %edx
 	orl	4(%esp), %edx
 	movl	%edx, (%esp)
 	fldcw	(%esp)
 	frndint
-	fldcw	4(%esp)
-	addl	$8, %esp
-	cfi_adjust_cfa_offset (-8)
+	fldenv	4(%esp)
+	addl	$32, %esp
+	cfi_adjust_cfa_offset (-32)
 	ret
 END(__trunc)
 weak_alias (__trunc, trunc)
diff --git a/sysdeps/i386/fpu/s_truncf.S b/sysdeps/i386/fpu/s_truncf.S
index cbf257a..d55a11d 100644
--- a/sysdeps/i386/fpu/s_truncf.S
+++ b/sysdeps/i386/fpu/s_truncf.S
@@ -21,17 +21,17 @@
 
 ENTRY(__truncf)
 	flds	4(%esp)
-	subl	$8, %esp
-	cfi_adjust_cfa_offset (8)
-	fstcw	4(%esp)
+	subl	$32, %esp
+	cfi_adjust_cfa_offset (32)
+	fnstenv	4(%esp)
 	movl	$0xc00, %edx
 	orl	4(%esp), %edx
 	movl	%edx, (%esp)
 	fldcw	(%esp)
 	frndint
-	fldcw	4(%esp)
-	addl	$8, %esp
-	cfi_adjust_cfa_offset (-8)
+	fldenv	4(%esp)
+	addl	$32, %esp
+	cfi_adjust_cfa_offset (-32)
 	ret
 END(__truncf)
 weak_alias (__truncf, truncf)
diff --git a/sysdeps/i386/fpu/s_truncl.S b/sysdeps/i386/fpu/s_truncl.S
index f92b474..f5ba372 100644
--- a/sysdeps/i386/fpu/s_truncl.S
+++ b/sysdeps/i386/fpu/s_truncl.S
@@ -21,17 +21,20 @@
 
 ENTRY(__truncl)
 	fldt	4(%esp)
-	subl	$8, %esp
-	cfi_adjust_cfa_offset (8)
-	fstcw	4(%esp)
+	subl	$32, %esp
+	cfi_adjust_cfa_offset (32)
+	fnstenv	4(%esp)
 	movl	$0xc00, %edx
 	orl	4(%esp), %edx
 	movl	%edx, (%esp)
 	fldcw	(%esp)
 	frndint
-	fldcw	4(%esp)
-	addl	$8, %esp
-	cfi_adjust_cfa_offset (-8)
+	fnstsw
+	andl	$0x1, %eax
+	orl	%eax, 8(%esp)
+	fldenv	4(%esp)
+	addl	$32, %esp
+	cfi_adjust_cfa_offset (-32)
 	ret
 END(__truncl)
 weak_alias (__truncl, truncl)
diff --git a/sysdeps/x86_64/fpu/s_truncl.S b/sysdeps/x86_64/fpu/s_truncl.S
index c37cf00..0b46efe 100644
--- a/sysdeps/x86_64/fpu/s_truncl.S
+++ b/sysdeps/x86_64/fpu/s_truncl.S
@@ -21,13 +21,16 @@
 
 ENTRY(__truncl)
 	fldt	8(%rsp)
-	fstcw	-4(%rsp)
+	fnstenv	-28(%rsp)
 	movl	$0xc00, %edx
-	orl	-4(%rsp), %edx
-	movl	%edx, -8(%rsp)
-	fldcw	-8(%rsp)
+	orl	-28(%rsp), %edx
+	movl	%edx, -32(%rsp)
+	fldcw	-32(%rsp)
 	frndint
-	fldcw	-4(%rsp)
+	fnstsw
+	andl	$0x1, %eax
+	orl	%eax, -24(%rsp)
+	fldenv	-28(%rsp)
 	ret
 END(__truncl)
 weak_alias (__truncl, truncl)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=623629de066dc2f404470e76ff074fc5ba643c6c

commit 623629de066dc2f404470e76ff074fc5ba643c6c
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Mon Jun 27 17:25:47 2016 +0000

    Avoid "inexact" exceptions in i386/x86_64 floor functions (bug 15479).
    
    As discussed in
    <https://sourceware.org/ml/libc-alpha/2016-05/msg00577.html>, TS
    18661-1 disallows ceil, floor, round and trunc functions from raising
    the "inexact" exception, in accordance with general IEEE 754 semantics
    for when that exception is raised.  Fixing this for x87 floating point
    is more complicated than for the other versions of these functions,
    because they use the frndint instruction that raises "inexact" and
    this can only be avoided by saving and restoring the whole
    floating-point environment.
    
    As I noted in
    <https://sourceware.org/ml/libc-alpha/2016-06/msg00128.html>, I have
    now implemented a GCC option -fno-fp-int-builtin-inexact for GCC 7,
    such that GCC will inline these functions on x86, without caring about
    "inexact", when the default -ffp-int-builtin-inexact is in effect.
    This allows users to get optimized code depending on the options they
    pass to the compiler, while making the out-of-line functions follow TS
    18661-1 semantics and avoid "inexact".
    
    This patch duly fixes the out-of-line floor function implementations
    to avoid "inexact", in the same way as the nearbyint implementations.
    
    I do not know how the performance of implementations such as these
    based on saving the environment and changing the rounding mode
    temporarily compares to that of the C versions or SSE 4.1 versions (of
    course, for 32-bit x86 SSE implementations still need to get the
    return value in an x87 register); it's entirely possible other
    implementations could be faster in some cases.
    
    Tested for x86_64 and x86.
    
    	[BZ #15479]
    	* sysdeps/i386/fpu/s_floor.S (__floor): Save and restore
    	floating-point environment rather than just control word.
    	* sysdeps/i386/fpu/s_floorf.S (__floorf): Likewise.
    	* sysdeps/i386/fpu/s_floorl.S (__floorl): Save and restore
    	floating-point environment, with "invalid" exceptions merged in,
    	rather than just control word.
    	* sysdeps/x86_64/fpu/s_floorl.S (__floorl): Likewise.
    	* math/libm-test.inc (floor_test_data): Do not allow spurious
    	"inexact" exceptions.

diff --git a/ChangeLog b/ChangeLog
index d9d93ed..a67e532 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,17 @@
 2016-06-27  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15479]
+	* sysdeps/i386/fpu/s_floor.S (__floor): Save and restore
+	floating-point environment rather than just control word.
+	* sysdeps/i386/fpu/s_floorf.S (__floorf): Likewise.
+	* sysdeps/i386/fpu/s_floorl.S (__floorl): Save and restore
+	floating-point environment, with "invalid" exceptions merged in,
+	rather than just control word.
+	* sysdeps/x86_64/fpu/s_floorl.S (__floorl): Likewise.
+	* math/libm-test.inc (floor_test_data): Do not allow spurious
+	"inexact" exceptions.
+
+	[BZ #15479]
 	* sysdeps/i386/fpu/s_ceil.S (__ceil): Save and restore
 	floating-point environment rather than just control word.
 	* sysdeps/i386/fpu/s_ceilf.S (__ceilf): Likewise.
diff --git a/math/libm-test.inc b/math/libm-test.inc
index ad97da1..9f6e21d 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -7308,14 +7308,13 @@ static const struct test_f_f_data floor_test_data[] =
     TEST_f_f (floor, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
     TEST_f_f (floor, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
 
-    /* Bug 15479: spurious "inexact" exception may occur.  */
-    TEST_f_f (floor, lit_pi, 3.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -lit_pi, -4.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, min_subnorm_value, 0.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, min_value, 0.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 0.1, 0.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 0.25, 0.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 0.625, 0.0, ERRNO_UNCHANGED),
+    TEST_f_f (floor, lit_pi, 3.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -lit_pi, -4.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, min_subnorm_value, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, min_value, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 0.1, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 0.25, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 0.625, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, 1, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, 2, 2, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, 0x1p23, 0x1p23, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
@@ -7334,11 +7333,11 @@ static const struct test_f_f_data floor_test_data[] =
     TEST_f_f (floor, 0x1p113, 0x1p113, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, 0x1p114, 0x1p114, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, max_value, max_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
-    TEST_f_f (floor, -min_subnorm_value, -1.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -min_value, -1.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -0.1, -1.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -0.25, -1.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -0.625, -1.0, ERRNO_UNCHANGED),
+    TEST_f_f (floor, -min_subnorm_value, -1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -min_value, -1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -0.1, -1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -0.25, -1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -0.625, -1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, -1, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, -2, -2, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, -0x1p23, -0x1p23, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
@@ -7360,78 +7359,78 @@ static const struct test_f_f_data floor_test_data[] =
 
 #if MANT_DIG >= 64
     /* The result can only be represented in long double.  */
-    TEST_f_f (floor, 4503599627370495.5L, 4503599627370495.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 4503599627370496.25L, 4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 4503599627370496.5L, 4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 4503599627370496.75L, 4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 4503599627370497.5L, 4503599627370497.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370495.5L, 4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370496.25L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370496.5L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370496.75L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370497.5L, 4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # if MANT_DIG > 100
-    TEST_f_f (floor, 4503599627370494.5000000000001L, 4503599627370494.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 4503599627370495.5000000000001L, 4503599627370495.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 4503599627370496.5000000000001L, 4503599627370496.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370494.5000000000001L, 4503599627370494.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370495.5000000000001L, 4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370496.5000000000001L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (floor, -4503599627370495.5L, -4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -4503599627370496.25L, -4503599627370497.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -4503599627370496.5L, -4503599627370497.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -4503599627370496.75L, -4503599627370497.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -4503599627370497.5L, -4503599627370498.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370495.5L, -4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370496.25L, -4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370496.5L, -4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370496.75L, -4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370497.5L, -4503599627370498.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # if MANT_DIG > 100
-    TEST_f_f (floor, -4503599627370494.5000000000001L, -4503599627370495.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -4503599627370495.5000000000001L, -4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -4503599627370496.5000000000001L, -4503599627370497.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370494.5000000000001L, -4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370495.5000000000001L, -4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370496.5000000000001L, -4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (floor, 9007199254740991.5L, 9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740992.25L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740992.5L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740992.75L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740993.5L, 9007199254740993.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740991.5L, 9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740992.25L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740992.5L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740992.75L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740993.5L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 # if MANT_DIG > 100
-    TEST_f_f (floor, 9007199254740991.0000000000001L, 9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740992.0000000000001L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740993.0000000000001L, 9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740991.5000000000001L, 9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740992.5000000000001L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740993.5000000000001L, 9007199254740993.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740991.0000000000001L, 9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740992.0000000000001L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740993.0000000000001L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740991.5000000000001L, 9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740992.5000000000001L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740993.5000000000001L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (floor, -9007199254740991.5L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740992.25L, -9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740992.5L, -9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740992.75L, -9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740993.5L, -9007199254740994.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740991.5L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740992.25L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740992.5L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740992.75L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740993.5L, -9007199254740994.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 # if MANT_DIG > 100
-    TEST_f_f (floor, -9007199254740991.0000000000001L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740992.0000000000001L, -9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740993.0000000000001L, -9007199254740994.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740991.5000000000001L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740992.5000000000001L, -9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740993.5000000000001L, -9007199254740994.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740991.0000000000001L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740992.0000000000001L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740993.0000000000001L, -9007199254740994.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740991.5000000000001L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740992.5000000000001L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740993.5000000000001L, -9007199254740994.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (floor, 72057594037927935.5L, 72057594037927935.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 72057594037927936.25L, 72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 72057594037927936.5L, 72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 72057594037927936.75L, 72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 72057594037927937.5L, 72057594037927937.0L, ERRNO_UNCHANGED),
-
-    TEST_f_f (floor, -72057594037927935.5L, -72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -72057594037927936.25L, -72057594037927937.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -72057594037927936.5L, -72057594037927937.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -72057594037927936.75L, -72057594037927937.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -72057594037927937.5L, -72057594037927938.0L, ERRNO_UNCHANGED),
-
-    TEST_f_f (floor, 10141204801825835211973625643007.5L, 10141204801825835211973625643007.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 10141204801825835211973625643008.5L, 10141204801825835211973625643008.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 10141204801825835211973625643008.75L, 10141204801825835211973625643008.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 10141204801825835211973625643009.5L, 10141204801825835211973625643009.0L, ERRNO_UNCHANGED),
-
-    TEST_f_f (floor, 0xf.ffffffffffffff8p+47L, 0xf.fffffffffffep+47L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -0x8.000000000000004p+48L, -0x8.000000000001p+48L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, 72057594037927935.5L, 72057594037927935.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 72057594037927936.25L, 72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 72057594037927936.5L, 72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 72057594037927936.75L, 72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 72057594037927937.5L, 72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_f_f (floor, -72057594037927935.5L, -72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -72057594037927936.25L, -72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -72057594037927936.5L, -72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -72057594037927936.75L, -72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -72057594037927937.5L, -72057594037927938.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_f_f (floor, 10141204801825835211973625643007.5L, 10141204801825835211973625643007.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 10141204801825835211973625643008.5L, 10141204801825835211973625643008.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 10141204801825835211973625643008.75L, 10141204801825835211973625643008.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 10141204801825835211973625643009.5L, 10141204801825835211973625643009.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_f_f (floor, 0xf.ffffffffffffff8p+47L, 0xf.fffffffffffep+47L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -0x8.000000000000004p+48L, -0x8.000000000001p+48L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 #endif
   };
 
diff --git a/sysdeps/i386/fpu/s_floor.S b/sysdeps/i386/fpu/s_floor.S
index 2d6287d..ed837da 100644
--- a/sysdeps/i386/fpu/s_floor.S
+++ b/sysdeps/i386/fpu/s_floor.S
@@ -9,10 +9,10 @@ RCSID("$NetBSD: s_floor.S,v 1.4 1995/05/09 00:01:59 jtc Exp $")
 
 ENTRY(__floor)
 	fldl	4(%esp)
-	subl	$8,%esp
-	cfi_adjust_cfa_offset (8)
+	subl	$32,%esp
+	cfi_adjust_cfa_offset (32)
 
-	fstcw	4(%esp)			/* store fpu control word */
+	fnstenv	4(%esp)			/* store fpu environment */
 
 	/* We use here %edx although only the low 1 bits are defined.
 	   But none of the operations should care and they are faster
@@ -25,10 +25,10 @@ ENTRY(__floor)
 
 	frndint				/* round */
 
-	fldcw	4(%esp)			/* restore original control word */
+	fldenv	4(%esp)			/* restore original environment */
 
-	addl	$8,%esp
-	cfi_adjust_cfa_offset (-8)
+	addl	$32,%esp
+	cfi_adjust_cfa_offset (-32)
 	ret
 END (__floor)
 weak_alias (__floor, floor)
diff --git a/sysdeps/i386/fpu/s_floorf.S b/sysdeps/i386/fpu/s_floorf.S
index e969fbe..84b6f7e 100644
--- a/sysdeps/i386/fpu/s_floorf.S
+++ b/sysdeps/i386/fpu/s_floorf.S
@@ -9,10 +9,10 @@ RCSID("$NetBSD: s_floorf.S,v 1.3 1995/05/09 00:04:32 jtc Exp $")
 
 ENTRY(__floorf)
 	flds	4(%esp)
-	subl	$8,%esp
-	cfi_adjust_cfa_offset (8)
+	subl	$32,%esp
+	cfi_adjust_cfa_offset (32)
 
-	fstcw	4(%esp)			/* store fpu control word */
+	fnstenv	4(%esp)			/* store fpu environment */
 
 	/* We use here %edx although only the low 1 bits are defined.
 	   But none of the operations should care and they are faster
@@ -25,10 +25,10 @@ ENTRY(__floorf)
 
 	frndint				/* round */
 
-	fldcw	4(%esp)			/* restore original control word */
+	fldenv	4(%esp)			/* restore original environment */
 
-	addl	$8,%esp
-	cfi_adjust_cfa_offset (-8)
+	addl	$32,%esp
+	cfi_adjust_cfa_offset (-32)
 	ret
 END (__floorf)
 weak_alias (__floorf, floorf)
diff --git a/sysdeps/i386/fpu/s_floorl.S b/sysdeps/i386/fpu/s_floorl.S
index 1206554..dc74a0c 100644
--- a/sysdeps/i386/fpu/s_floorl.S
+++ b/sysdeps/i386/fpu/s_floorl.S
@@ -10,10 +10,10 @@ RCSID("$NetBSD: $")
 
 ENTRY(__floorl)
 	fldt	4(%esp)
-	subl	$8,%esp
-	cfi_adjust_cfa_offset (8)
+	subl	$32,%esp
+	cfi_adjust_cfa_offset (32)
 
-	fstcw	4(%esp)			/* store fpu control word */
+	fnstenv	4(%esp)			/* store fpu environment */
 
 	/* We use here %edx although only the low 1 bits are defined.
 	   But none of the operations should care and they are faster
@@ -26,10 +26,15 @@ ENTRY(__floorl)
 
 	frndint				/* round */
 
-	fldcw	4(%esp)			/* restore original control word */
+	/* Preserve "invalid" exceptions from sNaN input.  */
+	fnstsw
+	andl	$0x1, %eax
+	orl	%eax, 8(%esp)
 
-	addl	$8,%esp
-	cfi_adjust_cfa_offset (-8)
+	fldenv	4(%esp)			/* restore original environment */
+
+	addl	$32,%esp
+	cfi_adjust_cfa_offset (-32)
 	ret
 END (__floorl)
 weak_alias (__floorl, floorl)
diff --git a/sysdeps/x86_64/fpu/s_floorl.S b/sysdeps/x86_64/fpu/s_floorl.S
index f9ecc38..535fdd8 100644
--- a/sysdeps/x86_64/fpu/s_floorl.S
+++ b/sysdeps/x86_64/fpu/s_floorl.S
@@ -10,20 +10,25 @@
 ENTRY(__floorl)
 	fldt	8(%rsp)
 
-	fstcw	-4(%rsp)		/* store fpu control word */
+	fnstenv	-28(%rsp)		/* store fpu environment */
 
 	/* We use here %edx although only the low 1 bits are defined.
 	   But none of the operations should care and they are faster
 	   than the 16 bit operations.  */
 	movl	$0x400,%edx		/* round towards -oo */
-	orl	-4(%rsp),%edx
+	orl	-28(%rsp),%edx
 	andl	$0xf7ff,%edx
-	movl	%edx,-8(%rsp)
-	fldcw	-8(%rsp)		/* load modified control word */
+	movl	%edx,-32(%rsp)
+	fldcw	-32(%rsp)		/* load modified control word */
 
 	frndint				/* round */
 
-	fldcw	-4(%rsp)		/* restore original control word */
+	/* Preserve "invalid" exceptions from sNaN input.  */
+	fnstsw
+	andl	$0x1, %eax
+	orl	%eax, -24(%rsp)
+
+	fldenv	-28(%rsp)		/* restore original environment */
 
 	ret
 END (__floorl)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=26b0bf96000a825ad3381be52ebd8adf2afc785f

commit 26b0bf96000a825ad3381be52ebd8adf2afc785f
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Mon Jun 27 17:23:19 2016 +0000

    Avoid "inexact" exceptions in i386/x86_64 ceil functions (bug 15479).
    
    As discussed in
    <https://sourceware.org/ml/libc-alpha/2016-05/msg00577.html>, TS
    18661-1 disallows ceil, floor, round and trunc functions from raising
    the "inexact" exception, in accordance with general IEEE 754 semantics
    for when that exception is raised.  Fixing this for x87 floating point
    is more complicated than for the other versions of these functions,
    because they use the frndint instruction that raises "inexact" and
    this can only be avoided by saving and restoring the whole
    floating-point environment.
    
    As I noted in
    <https://sourceware.org/ml/libc-alpha/2016-06/msg00128.html>, I have
    now implemented a GCC option -fno-fp-int-builtin-inexact for GCC 7,
    such that GCC will inline these functions on x86, without caring about
    "inexact", when the default -ffp-int-builtin-inexact is in effect.
    This allows users to get optimized code depending on the options they
    pass to the compiler, while making the out-of-line functions follow TS
    18661-1 semantics and avoid "inexact".
    
    This patch duly fixes the out-of-line ceil function implementations to
    avoid "inexact", in the same way as the nearbyint implementations.
    
    I do not know how the performance of implementations such as these
    based on saving the environment and changing the rounding mode
    temporarily compares to that of the C versions or SSE 4.1 versions (of
    course, for 32-bit x86 SSE implementations still need to get the
    return value in an x87 register); it's entirely possible other
    implementations could be faster in some cases.
    
    Tested for x86_64 and x86.
    
    	[BZ #15479]
    	* sysdeps/i386/fpu/s_ceil.S (__ceil): Save and restore
    	floating-point environment rather than just control word.
    	* sysdeps/i386/fpu/s_ceilf.S (__ceilf): Likewise.
    	* sysdeps/i386/fpu/s_ceill.S (__ceill): Save and restore
    	floating-point environment, with "invalid" exceptions merged in,
    	rather than just control word.
    	* sysdeps/x86_64/fpu/s_ceill.S (__ceill): Likewise.
    	* math/libm-test.inc (ceil_test_data): Do not allow spurious
    	"inexact" exceptions.

diff --git a/ChangeLog b/ChangeLog
index 0847c8d..d9d93ed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2016-06-27  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #15479]
+	* sysdeps/i386/fpu/s_ceil.S (__ceil): Save and restore
+	floating-point environment rather than just control word.
+	* sysdeps/i386/fpu/s_ceilf.S (__ceilf): Likewise.
+	* sysdeps/i386/fpu/s_ceill.S (__ceill): Save and restore
+	floating-point environment, with "invalid" exceptions merged in,
+	rather than just control word.
+	* sysdeps/x86_64/fpu/s_ceill.S (__ceill): Likewise.
+	* math/libm-test.inc (ceil_test_data): Do not allow spurious
+	"inexact" exceptions.
+
 2016-06-21  Aurelien Jarno  <aurelien@aurel32.net>
 
 	* sysdeps/unix/sysv/linux/mips/vfork.S (__vfork): Rename into
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 7334a48..ad97da1 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -6078,14 +6078,13 @@ static const struct test_f_f_data ceil_test_data[] =
     TEST_f_f (ceil, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
     TEST_f_f (ceil, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
 
-    /* Bug 15479: spurious "inexact" exception may occur.  */
-    TEST_f_f (ceil, lit_pi, 4.0, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -lit_pi, -3.0, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, min_subnorm_value, 1.0, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, min_value, 1.0, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 0.1, 1.0, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 0.25, 1.0, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 0.625, 1.0, ERRNO_UNCHANGED),
+    TEST_f_f (ceil, lit_pi, 4.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -lit_pi, -3.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, min_subnorm_value, 1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, min_value, 1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 0.1, 1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 0.25, 1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 0.625, 1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (ceil, 1, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (ceil, 2, 2, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (ceil, 0x1p23, 0x1p23, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
@@ -6104,11 +6103,11 @@ static const struct test_f_f_data ceil_test_data[] =
     TEST_f_f (ceil, 0x1p113, 0x1p113, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (ceil, 0x1p114, 0x1p114, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (ceil, max_value, max_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -min_subnorm_value, minus_zero, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -min_value, minus_zero, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -0.1, minus_zero, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -0.25, minus_zero, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -0.625, minus_zero, ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -min_subnorm_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -min_value, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -0.1, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -0.25, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -0.625, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (ceil, -1, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (ceil, -2, -2, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (ceil, -0x1p23, -0x1p23, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
@@ -6130,81 +6129,81 @@ static const struct test_f_f_data ceil_test_data[] =
 
 #if MANT_DIG >= 64
     /* The result can only be represented in long double.  */
-    TEST_f_f (ceil, 4503599627370495.5L, 4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 4503599627370496.25L, 4503599627370497.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 4503599627370496.5L, 4503599627370497.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 4503599627370496.75L, 4503599627370497.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 4503599627370497.5L, 4503599627370498.0L, ERRNO_UNCHANGED),
-
-    TEST_f_f (ceil, -4503599627370495.5L, -4503599627370495.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -4503599627370496.25L, -4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -4503599627370496.5L, -4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -4503599627370496.75L, -4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -4503599627370497.5L, -4503599627370497.0L, ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 4503599627370495.5L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 4503599627370496.25L, 4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 4503599627370496.5L, 4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 4503599627370496.75L, 4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 4503599627370497.5L, 4503599627370498.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_f_f (ceil, -4503599627370495.5L, -4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -4503599627370496.25L, -4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -4503599627370496.5L, -4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -4503599627370496.75L, -4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -4503599627370497.5L, -4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 # if MANT_DIG > 100
-    TEST_f_f (ceil, 4503599627370494.5000000000001L, 4503599627370495.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 4503599627370495.5000000000001L, 4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 4503599627370496.5000000000001L, 4503599627370497.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -4503599627370494.5000000000001L, -4503599627370494.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -4503599627370495.5000000000001L, -4503599627370495.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -4503599627370496.5000000000001L, -4503599627370496.0L, ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 4503599627370494.5000000000001L, 4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 4503599627370495.5000000000001L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 4503599627370496.5000000000001L, 4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -4503599627370494.5000000000001L, -4503599627370494.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -4503599627370495.5000000000001L, -4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -4503599627370496.5000000000001L, -4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (ceil, 9007199254740991.5L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 9007199254740992.25L, 9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 9007199254740992.5L, 9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 9007199254740992.75L, 9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 9007199254740993.5L, 9007199254740994.0L, ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 9007199254740991.5L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 9007199254740992.25L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 9007199254740992.5L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 9007199254740992.75L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 9007199254740993.5L, 9007199254740994.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
-    TEST_f_f (ceil, -9007199254740991.5L, -9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -9007199254740992.25L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -9007199254740992.5L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -9007199254740992.75L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -9007199254740993.5L, -9007199254740993.0L, ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -9007199254740991.5L, -9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -9007199254740992.25L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -9007199254740992.5L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -9007199254740992.75L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -9007199254740993.5L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 # if MANT_DIG > 100
-    TEST_f_f (ceil, 9007199254740991.0000000000001L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 9007199254740992.0000000000001L, 9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 9007199254740993.0000000000001L, 9007199254740994.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 9007199254740991.5000000000001L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 9007199254740992.5000000000001L, 9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 9007199254740993.5000000000001L, 9007199254740994.0L, ERRNO_UNCHANGED),
-
-    TEST_f_f (ceil, -9007199254740991.0000000000001L, -9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -9007199254740992.0000000000001L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -9007199254740993.0000000000001L, -9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -9007199254740991.5000000000001L, -9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -9007199254740992.5000000000001L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -9007199254740993.5000000000001L, -9007199254740993.0L, ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 9007199254740991.0000000000001L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 9007199254740992.0000000000001L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 9007199254740993.0000000000001L, 9007199254740994.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 9007199254740991.5000000000001L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 9007199254740992.5000000000001L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 9007199254740993.5000000000001L, 9007199254740994.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_f_f (ceil, -9007199254740991.0000000000001L, -9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -9007199254740992.0000000000001L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -9007199254740993.0000000000001L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -9007199254740991.5000000000001L, -9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -9007199254740992.5000000000001L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -9007199254740993.5000000000001L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (ceil, 72057594037927935.5L, 72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 72057594037927936.25L, 72057594037927937.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 72057594037927936.5L, 72057594037927937.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 72057594037927936.75L, 72057594037927937.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 72057594037927937.5L, 72057594037927938.0L, ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 72057594037927935.5L, 72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 72057594037927936.25L, 72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 72057594037927936.5L, 72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 72057594037927936.75L, 72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 72057594037927937.5L, 72057594037927938.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
-    TEST_f_f (ceil, -72057594037927935.5L, -72057594037927935.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -72057594037927936.25L, -72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -72057594037927936.5L, -72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -72057594037927936.75L, -72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -72057594037927937.5L, -72057594037927937.0L, ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -72057594037927935.5L, -72057594037927935.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -72057594037927936.25L, -72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -72057594037927936.5L, -72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -72057594037927936.75L, -72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -72057594037927937.5L, -72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
     /* Check cases where first double is a exact integer higher than 2^52 and
        the precision is determined by second long double for IBM long double.  */
-    TEST_f_f (ceil,  34503599627370498.515625L, 34503599627370499.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -34503599627370498.515625L, -34503599627370498.0L, ERRNO_UNCHANGED),
+    TEST_f_f (ceil,  34503599627370498.515625L, 34503599627370499.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -34503599627370498.515625L, -34503599627370498.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # if MANT_DIG >= 106
-    TEST_f_f (ceil,  1192568192774434123539907640624.484375L, 1192568192774434123539907640625.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, -1192568192774434123539907640624.484375L, -1192568192774434123539907640624.0L, ERRNO_UNCHANGED),
+    TEST_f_f (ceil,  1192568192774434123539907640624.484375L, 1192568192774434123539907640625.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, -1192568192774434123539907640624.484375L, -1192568192774434123539907640624.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (ceil, 10141204801825835211973625643007.5L, 10141204801825835211973625643008.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 10141204801825835211973625643008.25L, 10141204801825835211973625643009.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 10141204801825835211973625643008.5L, 10141204801825835211973625643009.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 10141204801825835211973625643008.75L, 10141204801825835211973625643009.0L, ERRNO_UNCHANGED),
-    TEST_f_f (ceil, 10141204801825835211973625643009.5L, 10141204801825835211973625643010.0L, ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 10141204801825835211973625643007.5L, 10141204801825835211973625643008.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 10141204801825835211973625643008.25L, 10141204801825835211973625643009.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 10141204801825835211973625643008.5L, 10141204801825835211973625643009.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 10141204801825835211973625643008.75L, 10141204801825835211973625643009.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (ceil, 10141204801825835211973625643009.5L, 10141204801825835211973625643010.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 #endif
   };
 
diff --git a/sysdeps/i386/fpu/s_ceil.S b/sysdeps/i386/fpu/s_ceil.S
index f32fa26..1226bb2 100644
--- a/sysdeps/i386/fpu/s_ceil.S
+++ b/sysdeps/i386/fpu/s_ceil.S
@@ -9,10 +9,10 @@ RCSID("$NetBSD: s_ceil.S,v 1.4 1995/05/08 23:52:13 jtc Exp $")
 
 ENTRY(__ceil)
 	fldl	4(%esp)
-	subl	$8,%esp
-	cfi_adjust_cfa_offset (8)
+	subl	$32,%esp
+	cfi_adjust_cfa_offset (32)
 
-	fstcw	4(%esp)			/* store fpu control word */
+	fnstenv	4(%esp)			/* store fpu environment */
 
 	/* We use here %edx although only the low 1 bits are defined.
 	   But none of the operations should care and they are faster
@@ -25,10 +25,10 @@ ENTRY(__ceil)
 
 	frndint				/* round */
 
-	fldcw	4(%esp)			/* restore original control word */
+	fldenv	4(%esp)			/* restore original environment */
 
-	addl	$8,%esp
-	cfi_adjust_cfa_offset (-8)
+	addl	$32,%esp
+	cfi_adjust_cfa_offset (-32)
 	ret
 END (__ceil)
 weak_alias (__ceil, ceil)
diff --git a/sysdeps/i386/fpu/s_ceilf.S b/sysdeps/i386/fpu/s_ceilf.S
index 4fe703b..d345c09 100644
--- a/sysdeps/i386/fpu/s_ceilf.S
+++ b/sysdeps/i386/fpu/s_ceilf.S
@@ -9,10 +9,10 @@ RCSID("$NetBSD: s_ceilf.S,v 1.3 1995/05/08 23:52:44 jtc Exp $")
 
 ENTRY(__ceilf)
 	flds	4(%esp)
-	subl	$8,%esp
-	cfi_adjust_cfa_offset (8)
+	subl	$32,%esp
+	cfi_adjust_cfa_offset (32)
 
-	fstcw	4(%esp)			/* store fpu control word */
+	fnstenv	4(%esp)			/* store fpu environment */
 
 	/* We use here %edx although only the low 1 bits are defined.
 	   But none of the operations should care and they are faster
@@ -25,10 +25,10 @@ ENTRY(__ceilf)
 
 	frndint				/* round */
 
-	fldcw	4(%esp)			/* restore original control word */
+	fldenv	4(%esp)			/* restore original environment */
 
-	addl	$8,%esp
-	cfi_adjust_cfa_offset (-8)
+	addl	$32,%esp
+	cfi_adjust_cfa_offset (-32)
 	ret
 END (__ceilf)
 weak_alias (__ceilf, ceilf)
diff --git a/sysdeps/i386/fpu/s_ceill.S b/sysdeps/i386/fpu/s_ceill.S
index 4b272c5..7c08f43 100644
--- a/sysdeps/i386/fpu/s_ceill.S
+++ b/sysdeps/i386/fpu/s_ceill.S
@@ -10,10 +10,10 @@ RCSID("$NetBSD: $")
 
 ENTRY(__ceill)
 	fldt	4(%esp)
-	subl	$8,%esp
-	cfi_adjust_cfa_offset (8)
+	subl	$32,%esp
+	cfi_adjust_cfa_offset (32)
 
-	fstcw	4(%esp)			/* store fpu control word */
+	fnstenv	4(%esp)			/* store fpu environment */
 
 	/* We use here %edx although only the low 1 bits are defined.
 	   But none of the operations should care and they are faster
@@ -26,10 +26,15 @@ ENTRY(__ceill)
 
 	frndint				/* round */
 
-	fldcw	4(%esp)			/* restore original control word */
+	/* Preserve "invalid" exceptions from sNaN input.  */
+	fnstsw
+	andl	$0x1, %eax
+	orl	%eax, 8(%esp)
 
-	addl	$8,%esp
-	cfi_adjust_cfa_offset (-8)
+	fldenv	4(%esp)			/* restore original environment */
+
+	addl	$32,%esp
+	cfi_adjust_cfa_offset (-32)
 	ret
 END (__ceill)
 weak_alias (__ceill, ceill)
diff --git a/sysdeps/x86_64/fpu/s_ceill.S b/sysdeps/x86_64/fpu/s_ceill.S
index 910c371..9d8b79d 100644
--- a/sysdeps/x86_64/fpu/s_ceill.S
+++ b/sysdeps/x86_64/fpu/s_ceill.S
@@ -11,20 +11,25 @@
 ENTRY(__ceill)
 	fldt	8(%rsp)
 
-	fstcw	-4(%rsp)		/* store fpu control word */
+	fnstenv	-28(%rsp)		/* store fpu environment */
 
 	/* We use here %edx although only the low 1 bits are defined.
 	   But none of the operations should care and they are faster
 	   than the 16 bit operations.  */
 	movl	$0x0800,%edx		/* round towards +oo */
-	orl	-4(%rsp),%edx
+	orl	-28(%rsp),%edx
 	andl	$0xfbff,%edx
-	movl	%edx,-8(%rsp)
-	fldcw	-8(%rsp)		/* load modified control word */
+	movl	%edx,-32(%rsp)
+	fldcw	-32(%rsp)		/* load modified control word */
 
 	frndint				/* round */
 
-	fldcw	-4(%rsp)		/* restore original control word */
+	/* Preserve "invalid" exceptions from sNaN input.  */
+	fnstsw
+	andl	$0x1, %eax
+	orl	%eax, -24(%rsp)
+
+	fldenv	-28(%rsp)		/* restore original environment */
 
 	ret
 END (__ceill)

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                     |   35 ++++
 math/libm-test.inc            |  429 ++++++++++++++++++++---------------------
 sysdeps/i386/fpu/s_ceil.S     |   12 +-
 sysdeps/i386/fpu/s_ceilf.S    |   12 +-
 sysdeps/i386/fpu/s_ceill.S    |   17 +-
 sysdeps/i386/fpu/s_floor.S    |   12 +-
 sysdeps/i386/fpu/s_floorf.S   |   12 +-
 sysdeps/i386/fpu/s_floorl.S   |   17 +-
 sysdeps/i386/fpu/s_trunc.S    |   12 +-
 sysdeps/i386/fpu/s_truncf.S   |   12 +-
 sysdeps/i386/fpu/s_truncl.S   |   15 +-
 sysdeps/x86_64/fpu/s_ceill.S  |   15 +-
 sysdeps/x86_64/fpu/s_floorl.S |   15 +-
 sysdeps/x86_64/fpu/s_truncl.S |   13 +-
 14 files changed, 343 insertions(+), 285 deletions(-)


hooks/post-receive
-- 
GNU C Library master sources


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