From 9ed65c7f36b3bffcbd178a65cadda9eb6c165e21 Mon Sep 17 00:00:00 2001 From: ghazi Date: Sun, 2 May 2004 02:53:05 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@81403 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 5 ++ gcc/builtins.c | 49 +++++++++++++++++++- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/torture/builtin-convert-3.c | 56 +++++++++++++++++++++++ gcc/testsuite/gcc.dg/torture/builtin-integral-1.c | 53 +++++++++++++++------ 5 files changed, 153 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/builtin-convert-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 353e6b0..9fa5652 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2004-05-01 Kaveh R. Ghazi + + * builtins.c (fold_fixed_mathfn): New function. + (fold_builtin_lround, fold_builtin): Use it. + 2004-05-01 Jakub Jelinek * config/sparc/linux64.h (TARGET_DEFAULT): Make 64-bit by default diff --git a/gcc/builtins.c b/gcc/builtins.c index 0d04f03..96d365a 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -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: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 596e8ed..822cb30 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-05-01 Kaveh R. Ghazi + + * 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 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 index 0000000..9901cec --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/builtin-convert-3.c @@ -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; +} diff --git a/gcc/testsuite/gcc.dg/torture/builtin-integral-1.c b/gcc/testsuite/gcc.dg/torture/builtin-integral-1.c index 1f2990d..0aeb7ff 100644 --- a/gcc/testsuite/gcc.dg/torture/builtin-integral-1.c +++ b/gcc/testsuite/gcc.dg/torture/builtin-integral-1.c @@ -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; } -- 2.7.4