* builtins.c (fold_fixed_mathfn): New function.
authorghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 2 May 2004 02:53:05 +0000 (02:53 +0000)
committerghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 2 May 2004 02:53:05 +0000 (02:53 +0000)
(fold_builtin_lround, fold_builtin): Use it.

testsuite:
* gcc.dg/torture/builtin-integral-1.c: Reorg and add more cases.
* gcc.dg/torture/builtin-convert-3.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@81403 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/builtin-convert-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/builtin-integral-1.c

index 353e6b0..9fa5652 100644 (file)
@@ -1,3 +1,8 @@
+2004-05-01  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * builtins.c (fold_fixed_mathfn): New function.
+       (fold_builtin_lround, fold_builtin): Use it.
+
 2004-05-01  Jakub Jelinek  <jakub@redhat.com>
 
        * config/sparc/linux64.h (TARGET_DEFAULT): Make 64-bit by default
index 0d04f03..96d365a 100644 (file)
@@ -6075,6 +6075,45 @@ fold_trunc_transparent_mathfn (tree exp)
   return 0;
 }
 
+/* EXP is assumed to be builtin call which can narrow the FP type of
+   the argument, for instance lround((double)f) -> lroundf (f).  */
+
+static tree
+fold_fixed_mathfn (tree exp)
+{
+  tree fndecl = get_callee_fndecl (exp);
+  tree arglist = TREE_OPERAND (exp, 1);
+  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+  tree arg;
+
+  if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+    return 0;
+
+  arg = TREE_VALUE (arglist);
+
+  /* If argument is already integer valued, and we don't need to worry
+     about setting errno, there's no need to perform rounding.  */
+  if (! flag_errno_math && integer_valued_real_p (arg))
+    return fold (build1 (FIX_TRUNC_EXPR, TREE_TYPE (exp), arg));
+
+  if (optimize)
+    {
+      tree ftype = TREE_TYPE (arg);
+      tree arg0 = strip_float_extensions (arg);
+      tree newtype = TREE_TYPE (arg0);
+      tree decl;
+
+      if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
+         && (decl = mathfn_built_in (newtype, fcode)))
+       {
+         arglist =
+           build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
+         return build_function_call_expr (decl, arglist);
+       }
+    }
+  return 0;
+}
+
 /* Fold function call to builtin cabs, cabsf or cabsl.  ARGLIST
    is the argument list and TYPE is the return type.  Return
    NULL_TREE if no if no simplification can be made.  */
@@ -6307,7 +6346,7 @@ fold_builtin_lround (tree exp)
        }
     }
 
-  return 0;
+  return fold_fixed_mathfn (exp);
 }
 
 /* Fold function call to builtin ffs, clz, ctz, popcount and parity
@@ -7420,6 +7459,14 @@ fold_builtin (tree exp)
     case BUILT_IN_LLROUNDL:
       return fold_builtin_lround (exp);
 
+    case BUILT_IN_LRINT:
+    case BUILT_IN_LRINTF:
+    case BUILT_IN_LRINTL:
+    case BUILT_IN_LLRINT:
+    case BUILT_IN_LLRINTF:
+    case BUILT_IN_LLRINTL:
+      return fold_fixed_mathfn (exp);
+
     case BUILT_IN_FFS:
     case BUILT_IN_FFSL:
     case BUILT_IN_FFSLL:
index 596e8ed..822cb30 100644 (file)
@@ -1,3 +1,8 @@
+2004-05-01  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * gcc.dg/torture/builtin-integral-1.c: Reorg and add more cases.
+       * gcc.dg/torture/builtin-convert-3.c: New test.
+
 2004-05-01  Ulrich Weigand  <uweigand@de.ibm.com>
 
        PR middle-end/15054
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-convert-3.c b/gcc/testsuite/gcc.dg/torture/builtin-convert-3.c
new file mode 100644 (file)
index 0000000..9901cec
--- /dev/null
@@ -0,0 +1,56 @@
+/* Copyright (C) 2004  Free Software Foundation.
+
+   Verify that builtin math functions (with fixed point return types)
+   are converted to smaller FP types correctly by the compiler.
+
+   Written by Kaveh Ghazi, 2004-05-01.  */
+
+/* { dg-do link } */
+/* { dg-options "-ffast-math" } */
+
+#include "../builtins-config.h"
+
+#define PROTOTYPE1_RET(FN, RET) \
+  extern RET FN(double); \
+  extern RET FN##f(float); \
+  extern RET FN##l(long double);
+
+/* Test converting math builtins to narrower FP types based on if the
+   argument is a narrower type (perhaps implicitly) cast to a wider
+   one.  */
+#define INNER_CAST1(MATHFN, RET) \
+ PROTOTYPE1_RET (MATHFN, RET); \
+ extern void link_failure_inner_##MATHFN##l_##MATHFN(void); \
+ extern void link_failure_inner_##MATHFN##l_##MATHFN##f(void); \
+ extern void link_failure_inner_##MATHFN##_##MATHFN##f(void); \
+ if (sizeof (long double) > sizeof (double) \
+     && MATHFN##l(d1) != MATHFN(d1)) \
+    link_failure_inner_##MATHFN##l_##MATHFN(); \
+ if (sizeof (long double) > sizeof (float) \
+     && MATHFN##l(f1) != MATHFN##f(f1)) \
+    link_failure_inner_##MATHFN##l_##MATHFN##f(); \
+ if (sizeof (long double) > sizeof (float) \
+     && MATHFN##l((double)f1) != MATHFN##f(f1)) \
+    link_failure_inner_##MATHFN##l_##MATHFN##f(); \
+ if (sizeof (double) > sizeof (float) \
+     && MATHFN(f1) != MATHFN##f(f1)) \
+    link_failure_inner_##MATHFN##_##MATHFN##f()
+
+void __attribute__ ((__noinline__)) test (double d1, float f1)
+{
+#ifdef __OPTIMIZE__
+#ifdef HAVE_C99_RUNTIME
+  /* We're converting to implicitly generated C99 functions.  */
+  INNER_CAST1 (lround, long);
+  INNER_CAST1 (llround, long long);
+  INNER_CAST1 (lrint, long);
+  INNER_CAST1 (llrint, long long);
+#endif /* HAVE_C99_RUNTIME */
+#endif /* __OPTIMIZE__ */
+}
+
+int main (void)
+{
+  test (1, 2);
+  return 0;
+}
index 1f2990d..0aeb7ff 100644 (file)
@@ -9,33 +9,57 @@
 
 #define PROTOTYPE1(FN) extern double FN(double); extern float FN##f(float); \
   extern long double FN##l(long double);
+#define PROTOTYPE1_RET(FN, RET) extern RET FN(double); extern RET FN##f(float); \
+  extern RET FN##l(long double);
+#define PROTOTYPE_LINK_FAILURE(FN) extern void link_failure_##FN(void); \
+ extern void link_failure_##FN##f(void); \
+ extern void link_failure_##FN##l(void); \
 
 PROTOTYPE1(fabs)
+PROTOTYPE1(ceil)
+PROTOTYPE1(floor)
+PROTOTYPE1(nearbyint)
+PROTOTYPE1(rint)
+PROTOTYPE1(round)
+PROTOTYPE1(trunc)
+PROTOTYPE1_RET(lround, long)
+PROTOTYPE1_RET(llround, long long)
+PROTOTYPE1_RET(lrint, long)
+PROTOTYPE1_RET(llrint, long long)
 
-void test(int i1, int i2)
-{
-  /* Test that the various FP truncation builtins detect integral
-     arguments.  */
+/* Test that the various FP truncation builtins detect integral
+   arguments.  */
 #define CHECK_FN(MATHFN) \
- PROTOTYPE1 (MATHFN) \
- extern void link_failure_##MATHFN(void); \
- extern void link_failure_##MATHFN##f(void); \
- extern void link_failure_##MATHFN##l(void); \
+ PROTOTYPE_LINK_FAILURE(MATHFN); \
  if (MATHFN(i1) != i1) link_failure_##MATHFN(); \
  if (MATHFN##f(i1) != i1) link_failure_##MATHFN##f(); \
- if (MATHFN##l(i1) != i1) link_failure_##MATHFN##l(); \
+ if (MATHFN##l(i1) != i1) link_failure_##MATHFN##l();
+
+#define CHECK_FN_RET(MATHFN, RET) \
+ PROTOTYPE_LINK_FAILURE(MATHFN); \
+ if (MATHFN(i1) != (RET)(double)i1) link_failure_##MATHFN(); \
+ if (MATHFN##f(i1) != (RET)(float)i1) link_failure_##MATHFN##f(); \
+ if (MATHFN##l(i1) != (RET)(long double)i1) link_failure_##MATHFN##l();
+
+  /* Check that various other integral expressions are detected.  */
+#define CHECK_EXPR(EXPR,NAME) \
+ extern void link_failure_FP_##NAME(void); \
+ extern void link_failure_fixed_##NAME(void); \
+ if (ceill(EXPR) != (EXPR)) link_failure_FP_##NAME(); \
+ if (lroundl(EXPR) != (long)(long double)(EXPR)) link_failure_fixed_##NAME();
 
+void __attribute__ ((__noinline__)) test (int i1, int i2)
+{
   CHECK_FN(ceil);
   CHECK_FN(floor);
   CHECK_FN(nearbyint);
   CHECK_FN(rint);
   CHECK_FN(round);
   CHECK_FN(trunc);
-
-  /* Check that various other integral expressions are detected.  */
-#define CHECK_EXPR(EXPR,NAME) \
- extern void link_failure_##NAME(void); \
- if (ceill(EXPR) != (EXPR)) link_failure_##NAME(); \
+  CHECK_FN_RET(lround, long);
+  CHECK_FN_RET(llround, long long);
+  CHECK_FN_RET(lrint, long);
+  CHECK_FN_RET(llrint, long long);
 
   CHECK_EXPR (5.0, REAL_CST);
   CHECK_EXPR (5.0F, REAL_CSTf);
@@ -54,5 +78,6 @@ void test(int i1, int i2)
 
 int main (void)
 {
+  test (1, 2);
   return 0;
 }