]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/28473 (with -O, casting result of round(x) to uint64_t produces...
authorRoger Sayle <roger@eyesopen.com>
Sun, 30 Jul 2006 13:21:59 +0000 (13:21 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Sun, 30 Jul 2006 13:21:59 +0000 (13:21 +0000)
PR middle-end/28473
Backport from mainline.
* convert.c (convert_to_integer): When transforming (T)foo(x) into
bar(x) check that bar's result type can represent all the values of T.
* builtins.c (fold_fixed_mathfn): When long and long long are the
same size, canonicalize llceil*, llfloor*, llround* and llrint*
functions to their lceil*, lfloor*, lround* and lrint* forms.

* gcc.dg/fold-convround-1.c: New test case.
* gcc.dg/builtins-55.c: New test case.

From-SVN: r115821

gcc/ChangeLog
gcc/builtins.c
gcc/convert.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-55.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/fold-convround-1.c [new file with mode: 0644]

index e990f778a6e1c694475abcabb34880016fada4d7..4878692eb3893190229dea2df04ce782b4fef35e 100644 (file)
@@ -1,3 +1,13 @@
+2006-07-30  Roger Sayle  <roger@eyesopen.com>
+
+       PR middle-end/28473
+       Backport from mainline.
+       * convert.c (convert_to_integer): When transforming (T)foo(x) into
+       bar(x) check that bar's result type can represent all the values of T.
+       * builtins.c (fold_fixed_mathfn): When long and long long are the
+       same size, canonicalize llceil*, llfloor*, llround* and llrint*
+       functions to their lceil*, lfloor*, lround* and lrint* forms.
+
 2006-07-26  Richard Sandiford  <richard@codesourcery.com>
 
        PR middle-end/28403
index 62458c3923a445b171f55612002260ca01bba701..963b19f2962a50646bf0e29b9b91001c730f98ac 100644 (file)
@@ -6268,6 +6268,38 @@ fold_fixed_mathfn (tree exp)
          return build_function_call_expr (decl, arglist);
        }
     }
+
+  /* Canonicalize llround (x) to lround (x) on LP64 targets where
+     sizeof (long long) == sizeof (long).  */
+  if (TYPE_PRECISION (long_long_integer_type_node)
+      == TYPE_PRECISION (long_integer_type_node))
+    {
+      tree newfn = NULL_TREE;
+      switch (fcode)
+       {
+       case BUILT_IN_LLROUND:
+       case BUILT_IN_LLROUNDF:
+       case BUILT_IN_LLROUNDL:
+         newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
+         break;
+
+       case BUILT_IN_LLRINT:
+       case BUILT_IN_LLRINTF:
+       case BUILT_IN_LLRINTL:
+         newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
+         break;
+
+       default:
+         break;
+       }
+
+      if (newfn)
+       {
+         tree newcall = build_function_call_expr (newfn, arglist);
+         return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), newcall);
+       }
+    }
+
   return 0;
 }
 
index 375cf98d6ba2989ca1a586a58beb84b88188eda9..1cd012441fb78ab6d7798ca4b29b570de6c216d7 100644 (file)
@@ -1,6 +1,6 @@
 /* Utility routines for data type conversion for GCC.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1997, 1998,
-   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -350,10 +350,13 @@ convert_to_integer (tree type, tree expr)
       switch (fcode)
         {
        case BUILT_IN_ROUND: case BUILT_IN_ROUNDF: case BUILT_IN_ROUNDL:
-         if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node))
-           fn = mathfn_built_in (s_intype, BUILT_IN_LLROUND);
-         else
+         if (outprec < TYPE_PRECISION (long_integer_type_node)
+             || (outprec == TYPE_PRECISION (long_integer_type_node)
+                 && !TYPE_UNSIGNED (type)))
            fn = mathfn_built_in (s_intype, BUILT_IN_LROUND);
+         else if (outprec == TYPE_PRECISION (long_long_integer_type_node)
+                  && !TYPE_UNSIGNED (type))
+           fn = mathfn_built_in (s_intype, BUILT_IN_LLROUND);
          break;
 
        case BUILT_IN_RINT: case BUILT_IN_RINTF: case BUILT_IN_RINTL:
@@ -361,11 +364,16 @@ convert_to_integer (tree type, tree expr)
          if (flag_trapping_math)
            break;
          /* ... Fall through ...  */
-       case BUILT_IN_NEARBYINT: case BUILT_IN_NEARBYINTF: case BUILT_IN_NEARBYINTL:
-         if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node))
-            fn = mathfn_built_in (s_intype, BUILT_IN_LLRINT);
-         else
-            fn = mathfn_built_in (s_intype, BUILT_IN_LRINT);
+       case BUILT_IN_NEARBYINT:
+       case BUILT_IN_NEARBYINTF:
+       case BUILT_IN_NEARBYINTL:
+         if (outprec < TYPE_PRECISION (long_integer_type_node)
+             || (outprec == TYPE_PRECISION (long_integer_type_node)
+                 && !TYPE_UNSIGNED (type)))
+           fn = mathfn_built_in (s_intype, BUILT_IN_LRINT);
+         else if (outprec == TYPE_PRECISION (long_long_integer_type_node)
+                  && !TYPE_UNSIGNED (type))
+           fn = mathfn_built_in (s_intype, BUILT_IN_LLRINT);
          break;
        default:
          break;
index 768c8e15285949244ee7a70d3197b5356e113a08..9a809b68009aa640bceddcf86913c816c045e39b 100644 (file)
@@ -1,3 +1,9 @@
+2006-07-30  Roger Sayle  <roger@eyesopen.com>
+
+       PR middle-end/28473
+       * gcc.dg/fold-convround-1.c: New test case.
+       * gcc.dg/builtins-55.c: New test case.
+
 2006-07-26  Richard Sandiford  <richard@codesourcery.com>
 
        PR middle-end/28403
diff --git a/gcc/testsuite/gcc.dg/builtins-55.c b/gcc/testsuite/gcc.dg/builtins-55.c
new file mode 100644 (file)
index 0000000..d804f29
--- /dev/null
@@ -0,0 +1,75 @@
+/* { dg-do link } */
+/* { dg-options "-O2 -ffast-math" } */
+/* { dg-options "-ffast-math -mmacosx-version-min=10.3" { target powerpc-*-darwin* } } */
+/* { dg-options "-O2 -ffast-math -std=c99" { target *-*-solaris2* } } */
+
+#include "builtins-config.h"
+
+void link_error (void);
+
+extern long lround(double);
+extern long lrint(double);
+
+extern long long llround(double);
+extern long long llrint(double);
+
+extern long lroundf(float);
+extern long lrintf(float);
+
+extern long long llroundf(float);
+extern long long llrintf(float);
+
+extern long lroundl(long double);
+extern long lrintl(long double);
+
+extern long long llroundl(long double);
+extern long long llrintl(long double);
+
+
+void test(double x)
+{
+#ifdef HAVE_C99_RUNTIME
+  if (sizeof(long) != sizeof(long long))
+    return;
+
+  if (lround(x) != llround(x))
+    link_error();
+  if (lrint(x) != llrint(x))
+    link_error();
+#endif
+}
+
+void testf(float x)
+{
+#ifdef HAVE_C99_RUNTIME
+  if (sizeof(long) != sizeof(long long))
+    return;
+
+  if (lroundf(x) != llroundf(x))
+    link_error();
+  if (lrintf(x) != llrintf(x))
+    link_error();
+#endif
+}
+
+void testl(long double x)
+{
+#ifdef HAVE_C99_RUNTIME
+  if (sizeof(long) != sizeof(long long))
+    return;
+
+  if (lroundl(x) != llroundl(x))
+    link_error();
+  if (lrintl(x) != llrintl(x))
+    link_error();
+#endif
+}
+
+int main()
+{
+  test(0.0);
+  testf(0.0);
+  testl(0.0);
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/fold-convround-1.c b/gcc/testsuite/gcc.dg/fold-convround-1.c
new file mode 100644 (file)
index 0000000..86612aa
--- /dev/null
@@ -0,0 +1,30 @@
+/* PR middle-end/28473.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+
+extern double round(double);
+extern double floor(double);
+extern double ceil(double);
+
+unsigned long long test1(double x)
+{
+  return (unsigned long long) round(x);
+}
+
+unsigned long long test2(double x)
+{
+  return (unsigned long long) floor(x);
+}
+unsigned long long test3(double x)
+{
+  return (unsigned long long) ceil(x);
+}
+
+/* { dg-final { scan-tree-dump-times "__builtin_lround" 0 "original" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_llround" 0 "original" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_lfloor" 0 "original" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_llfloor" 0 "original" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_lceil" 0 "original" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_llceil" 0 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
+