[PATCH]: fix conversion of nearbyint/rint -> lrint

Kaveh R. GHAZI ghazi@caip.rutgers.edu
Mon Mar 5 05:55:00 GMT 2007


I noticed that the code which converts nearbyint/rint (whose result is
cast to an int type) into lrint is wrong.  Currently it unconditionally
converts nearbyint into lrint, and only converts rint into lrint when
-fno-trapping-math is set.  This is backwards, what it should do is the
opposite.

The result is that people using nearbyint under the expectation that it
preserves the exception status are getting lrint which sets fp exceptions.
Also we're needlessly pessimizing the rint case.

We have a testcase that checks that both nearbyint/rint get converted when
trapping math is off, and it passes correctly.  However we have nothing
that checks for nearbyint staying put when trapping math is on.

This bug is present on all active branches.

Patch tested on sparc-sun-solaris2.10, no regressions.

Okay for mainline/4.2/4.1?

		Thanks,
		--Kaveh


2007-03-04  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

	* convert.c (convert_to_integer): Fix nearbyint/rint -> *lrint
	conversion.

testsuite:
	* gcc.dg/torture/builtin-convert-4.c: New test.

diff -rup orig/egcc-SVN20070303/gcc/convert.c egcc-SVN20070303/gcc/convert.c
--- orig/egcc-SVN20070303/gcc/convert.c	2007-02-15 20:04:02.000000000 -0500
+++ egcc-SVN20070303/gcc/convert.c	2007-03-04 13:13:19.286558801 -0500
@@ -413,12 +413,12 @@ convert_to_integer (tree type, tree expr
 	    fn = mathfn_built_in (s_intype, BUILT_IN_LLROUND);
 	  break;

-	CASE_FLT_FN (BUILT_IN_RINT):
-	  /* Only convert rint* if we can ignore math exceptions.  */
+	CASE_FLT_FN (BUILT_IN_NEARBYINT):
+	  /* Only convert nearbyint* if we can ignore math exceptions.  */
 	  if (flag_trapping_math)
 	    break;
 	  /* ... Fall through ...  */
-	CASE_FLT_FN (BUILT_IN_NEARBYINT):
+	CASE_FLT_FN (BUILT_IN_RINT):
 	  if (outprec < TYPE_PRECISION (long_integer_type_node)
 	      || (outprec == TYPE_PRECISION (long_integer_type_node)
 		  && !TYPE_UNSIGNED (type)))
diff -rup orig/egcc-SVN20070303/gcc/testsuite/gcc.dg/torture/builtin-convert-4.c egcc-SVN20070303/gcc/testsuite/gcc.dg/torture/builtin-convert-4.c
--- orig/egcc-SVN20070303/gcc/testsuite/gcc.dg/torture/builtin-convert-4.c	2007-03-04 13:44:11.640217603 -0500
+++ egcc-SVN20070303/gcc/testsuite/gcc.dg/torture/builtin-convert-4.c	2007-03-04 13:40:32.899508379 -0500
@@ -0,0 +1,37 @@
+/* Copyright (C) 2007  Free Software Foundation.
+
+   Verify that nearbyint isn't transformed into e.g. rint or lrint
+   when -ftrapping-math is set.
+
+   Written by Kaveh ghazi, 2007-03-04.  */
+
+/* { dg-do compile } */
+/* { dg-options "-ftrapping-math -fdump-tree-original" } */
+/* { dg-options "-ftrapping-math -fdump-tree-original -mmacosx-version-min=10.3" { target powerpc-*-darwin* } } */
+/* { dg-options "-ftrapping-math -fdump-tree-original -std=c99" { target *-*-solaris2* } } */
+
+#include "../builtins-config.h"
+
+extern void bar (long);
+
+#define TESTIT(FUNC) do { \
+  bar (__builtin_##FUNC(d)); \
+  bar (__builtin_##FUNC##f(f)); \
+  bar (__builtin_##FUNC##l(ld)); \
+} while (0)
+
+void __attribute__ ((__noinline__)) foo (double d, float f, long double ld)
+{
+  TESTIT(nearbyint);
+}
+
+int main()
+{
+  foo (1.0, 2.0, 3.0);
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "nearbyint " 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "nearbyintf" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "nearbyintl" 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */



More information about the Gcc-patches mailing list