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]: fold constant arguments to lround et al.


This patch implements folding of constant arguments passed to lround*
and llround*.  (Pretty self-explanatory.)

In adding testcases, I consolidated the other tests for rounding
functions along with the new ones into one file in the dg torture
framework and deleted the old tests.

I also noticed a comment nit which I fixed.

Bootstrapped/regtested on mips-sgi-irix6.5.

Ok for mainline?

		Thanks,
		--Kaveh


2004-04-29  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

	* builtins.c (fold_builtin_round): Fix comment typo.
	(fold_builtin_lround): New function.
	(fold_builtin): Use it.

testsuite:
	* gcc.dg/torture/builtin-rounding-1.c: New test.
	* gcc.dg/builtins-25.c: Delete.
	* gcc.dg/builtins-29.c: Delete.

diff -rup orig/egcc-CVS20040429/gcc/builtins.c egcc-CVS20040429/gcc/builtins.c
--- orig/egcc-CVS20040429/gcc/builtins.c	Thu Apr 29 17:23:18 2004
+++ egcc-CVS20040429/gcc/builtins.c	Thu Apr 29 22:09:43 2004
@@ -6254,7 +6254,7 @@ fold_builtin_round (tree exp)
   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
     return 0;
 
-  /* Optimize ceil of constant value.  */
+  /* Optimize round of constant value.  */
   arg = TREE_VALUE (arglist);
   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
     {
@@ -6274,6 +6274,42 @@ fold_builtin_round (tree exp)
   return fold_trunc_transparent_mathfn (exp);
 }
 
+/* Fold function call to builtin lround, lroundf or lroundl (or the
+   corresponding long long versions).  Return NULL_TREE if no
+   simplification can be made.  */
+
+static tree
+fold_builtin_lround (tree exp)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  tree arg;
+
+  if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+    return 0;
+
+  /* Optimize lround of constant value.  */
+  arg = TREE_VALUE (arglist);
+  if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
+    {
+      const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
+
+      if (! REAL_VALUE_ISNAN (x) && ! REAL_VALUE_ISINF (x))
+	{
+	  tree itype = TREE_TYPE (exp), ftype = TREE_TYPE (arg), result;
+	  HOST_WIDE_INT hi, lo;
+	  REAL_VALUE_TYPE r;
+
+	  real_round (&r, TYPE_MODE (ftype), &x);
+	  REAL_VALUE_TO_INT (&lo, &hi, r);
+	  result = build_int_2 (lo, hi);
+	  if (int_fits_type_p (result, itype))
+	    return fold_convert (itype, result);
+	}
+    }
+
+  return 0;
+}
+
 /* Fold function call to builtin ffs, clz, ctz, popcount and parity
    and their long and long long variants (i.e. ffsl and ffsll).
    Return NULL_TREE if no simplification can be made.  */
@@ -7375,6 +7411,14 @@ fold_builtin (tree exp)
     case BUILT_IN_RINTF:
     case BUILT_IN_RINTL:
       return fold_trunc_transparent_mathfn (exp);
+
+    case BUILT_IN_LROUND:
+    case BUILT_IN_LROUNDF:
+    case BUILT_IN_LROUNDL:
+    case BUILT_IN_LLROUND:
+    case BUILT_IN_LLROUNDF:
+    case BUILT_IN_LLROUNDL:
+      return fold_builtin_lround (exp);
 
     case BUILT_IN_FFS:
     case BUILT_IN_FFSL:



/* Copyright (C) 2004 Free Software Foundation.

   Check that constant folding of the rounding math functions doesn't
   break anything and produces the expected results.

   Written by Kaveh Ghazi, 2004-04-29.  */

/* { dg-do link } */

#define PROTOTYPE(FN) \
  PROTOTYPE_LINK_ERROR(FN) \
  extern double FN (double); \
  extern float FN##f (float); \
  extern long double FN##l (long double);

#define PROTOTYPE_RET(FN, RET) \
  PROTOTYPE_LINK_ERROR(FN) \
  extern RET FN (double); \
  extern RET FN##f (float); \
  extern RET FN##l (long double);

#define PROTOTYPE_LINK_ERROR(FN) \
  extern void link_error_##FN(void); \
  extern void link_error_##FN##f(void); \
  extern void link_error_##FN##l(void);

#define TEST(FN, VALUE, RESULT) \
  if (FN (VALUE) != RESULT) link_error_##FN(); \
  if (FN##f (VALUE) != RESULT) link_error_##FN##f(); \
  if (FN##l (VALUE) != RESULT) link_error_##FN##l(); \

PROTOTYPE (trunc);
PROTOTYPE (floor);
PROTOTYPE (ceil);
PROTOTYPE (round);
PROTOTYPE_RET (lround, long);
PROTOTYPE_RET (llround, long long);

int
main (void)
{
  TEST(trunc,   0, 0);
  TEST(floor,   0, 0);
  TEST(ceil,    0, 0);
  TEST(round,   0, 0);
  TEST(lround,  0, 0);
  TEST(llround, 0, 0);
  
  TEST(trunc,   6, 6);
  TEST(floor,   6, 6);
  TEST(ceil,    6, 6);
  TEST(round,   6, 6);
  TEST(lround,  6, 6);
  TEST(llround, 6, 6);
  
  TEST(trunc,   -8, -8);
  TEST(floor,   -8, -8);
  TEST(ceil,    -8, -8);
  TEST(round,   -8, -8);
  TEST(lround,  -8, -8);
  TEST(llround, -8, -8);
  
  TEST(trunc,   3.2, 3);
  TEST(floor,   3.2, 3);
  TEST(ceil,    3.2, 4);
  TEST(round,   3.2, 3);
  TEST(lround,  3.2, 3);
  TEST(llround, 3.2, 3);

  TEST(trunc,   -2.8, -2);
  TEST(floor,   -2.8, -3);
  TEST(ceil,    -2.8, -2);
  TEST(round,   -2.8, -3);
  TEST(lround,  -2.8, -3);
  TEST(llround, -2.8, -3);

  TEST(trunc,   0.01, 0);
  TEST(floor,   0.01, 0);
  TEST(ceil,    0.01, 1);
  TEST(round,   0.01, 0);
  TEST(lround,  0.01, 0);
  TEST(llround, 0.01, 0);

  TEST(trunc,   -0.7, 0);
  TEST(floor,   -0.7, -1);
  TEST(ceil,    -0.7, 0);
  TEST(round,   -0.7, -1);
  TEST(lround,  -0.7, -1);
  TEST(llround, -0.7, -1);

  TEST(trunc,   2.5, 2);
  TEST(floor,   2.5, 2);
  TEST(ceil,    2.5, 3);
  TEST(round,   2.5, 3);
  TEST(lround,  2.5, 3);
  TEST(llround, 2.5, 3);

  TEST(trunc,   -1.5, -1);
  TEST(floor,   -1.5, -2);
  TEST(ceil,    -1.5, -1);
  TEST(round,   -1.5, -2);
  TEST(lround,  -1.5, -2);
  TEST(llround, -1.5, -2);

  return 0;
}


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