* builtins.c (fold_fixed_mathfn): New function.
(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.
From-SVN: r81403
+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
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. */
}
}
- return 0;
+ return fold_fixed_mathfn (exp);
}
/* Fold function call to builtin ffs, clz, ctz, popcount and parity
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:
+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
--- /dev/null
+/* 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;
+}
#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);
int main (void)
{
+ test (1, 2);
return 0;
}