This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

[PATCH INSTALLED]: Handle NaN in fmin/fmax [take 2]


This is take 2 of my patch to fold fmin/fmax with NaN arguments
originally posted here:
http://gcc.gnu.org/ml/gcc-patches/2006-11/msg01709.html

I've incorporated Roger's suggestions for removing the `else'
statement and checking HONOR_SNANS (if we have an actual signalling
NaN, which we can determine).

In addition to folding the result to the right type, we have to make
it a non-lvalue.  Using omit_one_operand does both for us, so I
decided to use it rather than call non_lvalue on top of fold_convert.

Andrew's particular case from here:
http://gcc.gnu.org/ml/gcc-patches/2006-11/msg01730.html
is caught by the C frontend, however since we may arrive here through
some other pathway, we should strive to be bullet-proof.  Thanks
Andrew.

Bootstrapped on sparc-sun-solaris2.10, no regressions and the new test
cases pass.  I installed it per Roger's preapproval here:
http://gcc.gnu.org/ml/gcc-patches/2006-11/msg01723.html
although this is slightly different than he requested.  Roger let me know
if you have any objections and I'll correct it.

		Thanks,
		--Kaveh


2006-11-25  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

	* builtins.c (fold_builtin_fmin_fmax): Handle NaN arguments.

testsuite:
	* gcc.dg/torture/builtin-minmax-1.c: Test NaN in fmin/fmax.
	Don't ever inline the testcase.

diff -rup orig/egcc-SVN20061124/gcc/builtins.c egcc-SVN20061124/gcc/builtins.c
--- orig/egcc-SVN20061124/gcc/builtins.c	2006-11-23 20:01:12.000000000 -0500
+++ egcc-SVN20061124/gcc/builtins.c	2006-11-25 18:51:34.468498555 -0500
@@ -8734,6 +8734,20 @@ fold_builtin_fmin_fmax (tree arglist, tr
       if (res)
 	return res;

+      /* If either argument is NaN, return the other one.  Avoid the
+	 transformation if we get (and honor) a signalling NaN.  Using
+	 omit_one_operand() ensures we create a non-lvalue.  */
+      if (TREE_CODE (arg0) == REAL_CST
+	  && real_isnan (&TREE_REAL_CST (arg0))
+	  && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+	      || ! TREE_REAL_CST (arg0).signalling))
+	return omit_one_operand (type, arg1, arg0);
+      if (TREE_CODE (arg1) == REAL_CST
+	  && real_isnan (&TREE_REAL_CST (arg1))
+	  && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
+	      || ! TREE_REAL_CST (arg1).signalling))
+	return omit_one_operand (type, arg0, arg1);
+
       /* Transform fmin/fmax(x,x) -> x.  */
       if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
 	return omit_one_operand (type, arg0, arg1);
diff -rup orig/egcc-SVN20061124/gcc/testsuite/gcc.dg/torture/builtin-minmax-1.c egcc-SVN20061124/gcc/testsuite/gcc.dg/torture/builtin-minmax-1.c
--- orig/egcc-SVN20061124/gcc/testsuite/gcc.dg/torture/builtin-minmax-1.c	2006-11-18 15:52:22.000000000 -0500
+++ egcc-SVN20061124/gcc/testsuite/gcc.dg/torture/builtin-minmax-1.c	2006-11-25 19:04:47.573943571 -0500
@@ -74,7 +74,25 @@ extern int pure(int) __attribute__ ((__p
     link_error(__LINE__); \
   } while (0)

-void foo (float xf, double x, long double xl,
+/* Test that FUNC(NaN,x) == x.  We cast to (long) so "!=" folds.  Set
+   parameter SIGNAL to `s' for testing signaling NaN.  */
+#define TEST_NAN(FUNC,SIGNAL) do { \
+  if ((long)FUNC##f(__builtin_nan##SIGNAL##f(""),xf) != (long)xf) \
+    link_error(__LINE__); \
+  if ((long)FUNC##f(xf,__builtin_nan##SIGNAL##f("")) != (long)xf) \
+    link_error(__LINE__); \
+  if ((long)FUNC(__builtin_nan##SIGNAL(""),x) != (long)x) \
+    link_error(__LINE__); \
+  if ((long)FUNC(x,__builtin_nan##SIGNAL("")) != (long)x) \
+    link_error(__LINE__); \
+  if ((long)FUNC##l(__builtin_nan##SIGNAL##l(""),xl) != (long)xl) \
+    link_error(__LINE__); \
+  if ((long)FUNC##l(xl,__builtin_nan##SIGNAL##l("")) != (long)xl) \
+    link_error(__LINE__); \
+  } while (0)
+
+void __attribute__ ((__noinline__))
+     foo (float xf, double x, long double xl,
 	  float yf, double y, long double yl,
 	  int i, int j)
 {
@@ -91,6 +109,11 @@ void foo (float xf, double x, long doubl

   TEST_NONNEG(fmin);
   TEST_NONNEG(fmax);
+
+  TEST_NAN(fmin,);
+  TEST_NAN(fmax,);
+  TEST_NAN(fmin,s);
+  TEST_NAN(fmax,s);
 }

 int main()


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