From 332d782c3d9ed810c76f2e3088545d61e0f3c37c Mon Sep 17 00:00:00 2001 From: "Kaveh R. Ghazi" Date: Thu, 29 Apr 2004 00:36:20 +0000 Subject: [PATCH] convert.c (convert_to_integer): Convert (long)round -> lround, etc. * convert.c (convert_to_integer): Convert (long)round -> lround, etc. testsuite: * gcc.dg/torture/builtin-convert-2.c: New test. From-SVN: r81269 --- gcc/ChangeLog | 5 ++ gcc/convert.c | 46 +++++++++++ gcc/testsuite/ChangeLog | 4 + .../gcc.dg/torture/builtin-convert-2.c | 79 +++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/torture/builtin-convert-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 176ca3801ba..e67e0f84775 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2004-04-28 Kaveh R. Ghazi + + * convert.c (convert_to_integer): Convert (long)round -> lround, + etc. + 2004-04-28 Andrew Pinski * config/rs6000/rs6000.c (registers_ok_for_quad_peep): diff --git a/gcc/convert.c b/gcc/convert.c index dcab84a9aa9..c7d12b50200 100644 --- a/gcc/convert.c +++ b/gcc/convert.c @@ -332,6 +332,52 @@ convert_to_integer (tree type, tree expr) return error_mark_node; } + /* Convert e.g. (long)round(d) -> lround(d). */ + /* If we're converting to char, we may encounter differing behavior + between converting from double->char vs double->long->char. + We're in "undefined" territory but we prefer to be conservative, + so only proceed in "unsafe" math mode. */ + if (optimize + && (flag_unsafe_math_optimizations + || outprec >= TYPE_PRECISION (long_integer_type_node))) + { + tree s_expr = strip_float_extensions (expr); + tree s_intype = TREE_TYPE (s_expr); + const enum built_in_function fcode = builtin_mathfn_code (s_expr); + tree fn = 0; + + 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 + fn = mathfn_built_in (s_intype, BUILT_IN_LROUND); + break; + + case BUILT_IN_RINT: case BUILT_IN_RINTF: case BUILT_IN_RINTL: + /* Only convert rint* if we can ignore math exceptions. */ + 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); + break; + default: + break; + } + + if (fn) + { + tree arglist = TREE_OPERAND (s_expr, 1); + tree newexpr = build_function_call_expr (fn, arglist); + return convert_to_integer (type, newexpr); + } + } + switch (TREE_CODE (intype)) { case POINTER_TYPE: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 87f7a59535b..718a92eb2dc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2004-04-28 Kaveh R. Ghazi + + * gcc.dg/torture/builtin-convert-2.c: New test. + 2004-04-28 Andrew Pinski * gcc.dg/rs6000-power2-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/torture/builtin-convert-2.c b/gcc/testsuite/gcc.dg/torture/builtin-convert-2.c new file mode 100644 index 00000000000..62e5f0764fe --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/builtin-convert-2.c @@ -0,0 +1,79 @@ +/* Copyright (C) 2004 Free Software Foundation. + + Verify that built-in math function conversion into integer rounding + functions is correctly performed by the compiler. + + Written by Kaveh ghazi, 2004-04-26. */ + +/* { dg-do link } */ +/* { dg-options "-ffast-math" } */ + +#include "./builtins-config.h" + +#define PROTOTYPE(FN) extern double FN(double); \ + extern float FN##f(float); \ + extern long double FN##l(long double); +#define PROTOTYPE_RET(FN, RET) extern RET FN(double); \ + extern RET FN##f(float); \ + extern RET FN##l(long double); + +/* Macro to do all FP type combinations. The second half tests + narrowing the FP type. */ +#define TEST_FP2FIXED(FN1, FN2) \ + PROTOTYPE(FN1) \ + PROTOTYPE_RET(FN2, long) \ + PROTOTYPE_RET(l##FN2, long long) \ + extern void link_error_##FN1##_##FN2(void); \ + extern void link_error_##FN1##f_##FN2##f(void); \ + extern void link_error_##FN1##l_##FN2##l(void); \ + extern void link_error_##FN1##_l##FN2(void); \ + extern void link_error_##FN1##f_l##FN2##f(void); \ + extern void link_error_##FN1##l_l##FN2##l(void); \ + if ((long)FN1(d) != FN2(d)) \ + link_error_##FN1##_##FN2(); \ + if ((long)FN1##f(f) != FN2##f(f)) \ + link_error_##FN1##f_##FN2##f(); \ + if ((long)FN1##l(ld) != FN2##l(ld)) \ + link_error_##FN1##l_##FN2##l(); \ + if ((long long)FN1(d) != l##FN2(d)) \ + link_error_##FN1##_l##FN2(); \ + if ((long long)FN1##f(f) != l##FN2##f(f)) \ + link_error_##FN1##f_l##FN2##f(); \ + if ((long long)FN1##l(ld) != l##FN2##l(ld)) \ + link_error_##FN1##l_l##FN2##l(); \ + extern void link_error_##FN1##_##FN2##f(void); \ + extern void link_error_##FN1##l_##FN2(void); \ + extern void link_error_##FN1##l_##FN2##f(void); \ + extern void link_error_##FN1##_l##FN2##f(void); \ + extern void link_error_##FN1##l_l##FN2(void); \ + extern void link_error_##FN1##l_l##FN2##f(void); \ + if (sizeof(double) > sizeof(float) && (long)FN1(f) != FN2##f(f)) \ + link_error_##FN1##_##FN2##f(); \ + if (sizeof(long double) > sizeof(double) && (long)FN1##l(d) != FN2(d)) \ + link_error_##FN1##l_##FN2(); \ + if (sizeof(long double) > sizeof(float) && (long)FN1##l(f) != FN2##f(f)) \ + link_error_##FN1##l_##FN2##f(); \ + if (sizeof(double) > sizeof(float) && (long long)FN1(f) != l##FN2##f(f)) \ + link_error_##FN1##_l##FN2##f(); \ + if (sizeof(long double) > sizeof(double) && (long long)FN1##l(d) != l##FN2(d)) \ + link_error_##FN1##l_l##FN2(); \ + if (sizeof(long double) > sizeof(float) && (long long)FN1##l(f) != l##FN2##f(f)) \ + link_error_##FN1##l_l##FN2##f() + +void __attribute__ ((__noinline__)) foo (double d, float f, long double ld) +{ +#ifdef __OPTIMIZE__ +# ifdef HAVE_C99_RUNTIME + /* The resulting transformation functions are all C99. */ + TEST_FP2FIXED (round, lround); + TEST_FP2FIXED (nearbyint, lrint); + TEST_FP2FIXED (rint, lrint); +# endif +#endif +} + +int main() +{ + foo (1.0, 2.0, 3.0); + return 0; +} -- 2.30.2