This is the mail archive of the libc-alpha@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]

Fix nearbyint scheduling of arithmetic past fesetenv (bug 15490)


Bug 15490 is C nearbyintf being scheduled so that an operation that
raises the "inexact" exception runs after the fesetenv intended to
clear that exception, showing up as test-float testsuite failures.

This patch adds appropriate calls to math_force_eval to prevent that
scheduling.  Tested x86_64 (--disable-multi-arch).

The dbl-64/wordsize-64 version of nearbyint already has
math_opt_barrier calls in the relevant places that should serve to
prevent the problematic scheduling (though I believe math_force_eval
is sufficient and math_opt_barrier isn't required - if it were
required in any case, it would be needed right after feholdexcept, to
stop things being scheduled before that call, in addition
math_force_eval right before fesetenv).

We could certainly do with running the libm tests for all the IFUNC
variants that can be run on the system running tests (this is already
on the wiki todo list), to help detect such issues quicker.

2013-05-19  Joseph Myers  <joseph@codesourcery.com>

	[BZ #15490]
	* sysdeps/ieee754/dbl-64/s_nearbyint.c (__nearbyint): Use
	math_force_eval before restoring floating-point envrionment.
	* sysdeps/ieee754/flt-32/s_nearbyintf.c (__nearbyintf): Likewise.
	* sysdeps/ieee754/ldbl-128/s_nearbyintl.c (__nearbyintl):
	Likewise.
	* sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c: Include
	<math_private.h>.
	(__nearbyintl): Use math_force_eval before restoring
	floating-point environment.
	* sysdeps/ieee754/ldbl-96/s_nearbyintl.c (__nearbyintl): Likewise.

diff --git a/sysdeps/ieee754/dbl-64/s_nearbyint.c b/sysdeps/ieee754/dbl-64/s_nearbyint.c
index eb40c29..5017f47 100644
--- a/sysdeps/ieee754/dbl-64/s_nearbyint.c
+++ b/sysdeps/ieee754/dbl-64/s_nearbyint.c
@@ -47,6 +47,7 @@ double __nearbyint(double x)
 		libc_feholdexcept (&env);
 	        w = TWO52[sx]+x;
 	        t =  w-TWO52[sx];
+		math_force_eval (t);
 		libc_fesetenv (&env);
 		GET_HIGH_WORD(i0,t);
 		SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
@@ -59,6 +60,7 @@ double __nearbyint(double x)
 	libc_feholdexcept (&env);
 	w = TWO52[sx]+x;
 	t = w-TWO52[sx];
+	math_force_eval (t);
 	libc_fesetenv (&env);
 	return t;
 }
diff --git a/sysdeps/ieee754/flt-32/s_nearbyintf.c b/sysdeps/ieee754/flt-32/s_nearbyintf.c
index 48debad..5aebefa 100644
--- a/sysdeps/ieee754/flt-32/s_nearbyintf.c
+++ b/sysdeps/ieee754/flt-32/s_nearbyintf.c
@@ -39,6 +39,7 @@ __nearbyintf(float x)
 		libc_feholdexceptf (&env);
 		w = TWO23[sx]+x;
 		t =  w-TWO23[sx];
+		math_force_eval (t);
 		libc_fesetenvf (&env);
 		GET_FLOAT_WORD(i0,t);
 		SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31));
@@ -51,6 +52,7 @@ __nearbyintf(float x)
 	libc_feholdexceptf (&env);
 	w = TWO23[sx]+x;
 	t = w-TWO23[sx];
+	math_force_eval (t);
 	libc_fesetenvf (&env);
 	return t;
 }
diff --git a/sysdeps/ieee754/ldbl-128/s_nearbyintl.c b/sysdeps/ieee754/ldbl-128/s_nearbyintl.c
index d2afc10..2017c04 100644
--- a/sysdeps/ieee754/ldbl-128/s_nearbyintl.c
+++ b/sysdeps/ieee754/ldbl-128/s_nearbyintl.c
@@ -47,6 +47,7 @@ long double __nearbyintl(long double x)
 		feholdexcept (&env);
 	        w = TWO112[sx]+x;
 	        t = w-TWO112[sx];
+		math_force_eval (t);
 	        fesetenv (&env);
 		GET_LDOUBLE_MSW64(i0,t);
 		SET_LDOUBLE_MSW64(t,(i0&0x7fffffffffffffffLL)|(sx<<63));
@@ -59,6 +60,7 @@ long double __nearbyintl(long double x)
 	feholdexcept (&env);
 	w = TWO112[sx]+x;
 	t = w-TWO112[sx];
+	math_force_eval (t);
 	fesetenv (&env);
 	return t;
 }
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c b/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c
index b654bf5..bfcd110 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c
@@ -21,6 +21,7 @@
    when it's coded in C.  */
 
 #include <math.h>
+#include <math_private.h>
 #include <fenv.h>
 #include <math_ldbl_opt.h>
 #include <float.h>
@@ -53,6 +54,8 @@ __nearbyintl (long double x)
 	}
       u.dd[0] = high;
       u.dd[1] = 0.0;
+      math_force_eval (u.dd[0]);
+      math_force_eval (u.dd[1]);
       fesetenv (&env);
     }
   else if (fabs (u.dd[1]) < TWO52 && u.dd[1] != 0.0)
@@ -109,6 +112,8 @@ __nearbyintl (long double x)
 	}
       u.dd[0] = high + low;
       u.dd[1] = high - u.dd[0] + low;
+      math_force_eval (u.dd[0]);
+      math_force_eval (u.dd[1]);
       fesetenv (&env);
     }
 
diff --git a/sysdeps/ieee754/ldbl-96/s_nearbyintl.c b/sysdeps/ieee754/ldbl-96/s_nearbyintl.c
index ed9836c..c1d77f0 100644
--- a/sysdeps/ieee754/ldbl-96/s_nearbyintl.c
+++ b/sysdeps/ieee754/ldbl-96/s_nearbyintl.c
@@ -54,6 +54,7 @@ long double __nearbyintl(long double x)
 		feholdexcept (&env);
 	        w = TWO63[sx]+x;
 	        t = w-TWO63[sx];
+		math_force_eval (t);
 		fesetenv (&env);
 		GET_LDOUBLE_EXP(i0,t);
 		SET_LDOUBLE_EXP(t,(i0&0x7fff)|(sx<<15));
@@ -80,6 +81,7 @@ long double __nearbyintl(long double x)
 	feholdexcept (&env);
 	w = TWO63[sx]+x;
 	t = w-TWO63[sx];
+	math_force_eval (t);
 	fesetenv (&env);
 	return t;
 }

-- 
Joseph S. Myers
joseph@codesourcery.com


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