diff options
author | ghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-04-20 20:09:17 +0000 |
---|---|---|
committer | ghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-04-20 20:09:17 +0000 |
commit | c2373fdb4d683d1e14f62981bf0b8c1da8b8b684 (patch) | |
tree | 69005f1c685a98a731edd08d1cb85b99b722570f | |
parent | a4d2e7049d31bc26fc9f7dd62e80d8c4f2b468c1 (diff) | |
download | gcc-c2373fdb4d683d1e14f62981bf0b8c1da8b8b684.tar.gz |
* builtins.c (build_complex_cproj, fold_builtin_cproj): New.
(fold_builtin_1): Fold builtin cproj.
* builtins.def (BUILT_IN_CPROJ, BUILT_IN_CPROJF, BUILT_IN_CPROJL):
Use ATTR_CONST_NOTHROW_LIST.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158573 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/builtins.c | 47 | ||||
-rw-r--r-- | gcc/builtins.def | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/builtin-cproj-1.c | 88 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/builtin-cproj-2.c | 46 |
6 files changed, 196 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d4608caa6d8..72c4c9a43cd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2010-04-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * builtins.c (build_complex_cproj, fold_builtin_cproj): New. + (fold_builtin_1): Fold builtin cproj. + * builtins.def (BUILT_IN_CPROJ, BUILT_IN_CPROJF, BUILT_IN_CPROJL): + Use ATTR_CONST_NOTHROW_LIST. + 2010-04-20 Uros Bizjak <ubizjak@gmail.com> * config/i386/i386.md (ffs<mode>2): Macroize expander from ffs_cmove diff --git a/gcc/builtins.c b/gcc/builtins.c index 65940ddf4f7..8c3c8e0f4be 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -7042,6 +7042,50 @@ fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl) return NULL_TREE; } +/* Build a complex (inf +- 0i) for the result of cproj. TYPE is the + complex tree type of the result. If NEG is true, the imaginary + zero is negative. */ + +static tree +build_complex_cproj (tree type, bool neg) +{ + REAL_VALUE_TYPE rinf, rzero = dconst0; + + real_inf (&rinf); + rzero.sign = neg; + return build_complex (type, build_real (TREE_TYPE (type), rinf), + build_real (TREE_TYPE (type), rzero)); +} + +/* Fold call to builtin cproj, cprojf or cprojl with argument ARG. TYPE is the + return type. Return NULL_TREE if no simplification can be made. */ + +static tree +fold_builtin_cproj (location_t loc, tree arg, tree type) +{ + if (!validate_arg (arg, COMPLEX_TYPE) + || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE) + return NULL_TREE; + + /* If there are no infinities, return arg. */ + if (! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (type)))) + return non_lvalue_loc (loc, arg); + + /* Calculate the result when the argument is a constant. */ + if (TREE_CODE (arg) == COMPLEX_CST) + { + const REAL_VALUE_TYPE *real = TREE_REAL_CST_PTR (TREE_REALPART (arg)); + const REAL_VALUE_TYPE *imag = TREE_REAL_CST_PTR (TREE_IMAGPART (arg)); + + if (real_isinf (real) || real_isinf (imag)) + return build_complex_cproj (type, imag->sign); + else + return arg; + } + + return NULL_TREE; +} + /* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG. Return NULL_TREE if no simplification can be made. */ @@ -9799,6 +9843,9 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore) CASE_FLT_FN (BUILT_IN_CCOSH): return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ true); + CASE_FLT_FN (BUILT_IN_CPROJ): + return fold_builtin_cproj(loc, arg0, type); + CASE_FLT_FN (BUILT_IN_CSIN): if (validate_arg (arg0, COMPLEX_TYPE) && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) diff --git a/gcc/builtins.def b/gcc/builtins.def index 09177a9001a..4e4eb3edc03 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -479,9 +479,9 @@ DEF_C99_BUILTIN (BUILT_IN_CONJL, "conjl", BT_FN_COMPLEX_LONGDOUBLE_COMPLE DEF_C99_BUILTIN (BUILT_IN_CPOW, "cpow", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_CPOWF, "cpowf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_CPOWL, "cpowl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) -DEF_C99_BUILTIN (BUILT_IN_CPROJ, "cproj", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) -DEF_C99_BUILTIN (BUILT_IN_CPROJF, "cprojf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING) -DEF_C99_BUILTIN (BUILT_IN_CPROJL, "cprojl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_C99_BUILTIN (BUILT_IN_CPROJ, "cproj", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_CONST_NOTHROW_LIST) +DEF_C99_BUILTIN (BUILT_IN_CPROJF, "cprojf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_CONST_NOTHROW_LIST) +DEF_C99_BUILTIN (BUILT_IN_CPROJL, "cprojl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST) DEF_C99_BUILTIN (BUILT_IN_CREAL, "creal", BT_FN_DOUBLE_COMPLEX_DOUBLE, ATTR_CONST_NOTHROW_LIST) DEF_C99_BUILTIN (BUILT_IN_CREALF, "crealf", BT_FN_FLOAT_COMPLEX_FLOAT, ATTR_CONST_NOTHROW_LIST) DEF_C99_BUILTIN (BUILT_IN_CREALL, "creall", BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 186c8ae256c..c2082071b29 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-04-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * gcc.dg/torture/builtin-cproj-1.c: New. + * gcc.dg/torture/builtin-cproj-2.c: New. + 2010-04-20 Dodji Seketeli <dodji@redhat.com> PR c++/43800 diff --git a/gcc/testsuite/gcc.dg/torture/builtin-cproj-1.c b/gcc/testsuite/gcc.dg/torture/builtin-cproj-1.c new file mode 100644 index 00000000000..24540310b66 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/builtin-cproj-1.c @@ -0,0 +1,88 @@ +/* Copyright (C) 2010 Free Software Foundation. + + Verify that folding of built-in cproj is correctly performed by the + compiler. + + Origin: Kaveh R. Ghazi, April 9, 2010. */ + +/* { dg-do link } */ + +/* All references to link_error should go away at compile-time. The + argument is the __LINE__ number. It appears in the tree dump file + and aids in debugging should any of the tests fail. */ +extern void link_error(int); + +#define CPROJ(X) __builtin_cproj(X) +#define CPROJF(X) __builtin_cprojf(X) +#define CPROJL(X) __builtin_cprojl(X) +#define INF __builtin_inff() +#define I 1i +#define CPSGN(X,Y) __builtin_copysignf((X),(Y)) +#define CIMAG(X) __builtin_cimagf(X) +#define CREAL(X) __builtin_crealf(X) + +/* Check that the signs of the real and/or imaginary parts of two + complex numbers match. */ +#define CKSGN(X,Y) (CKSGN_R(X,Y) || CKSGN_I(X,Y)) +#define CKSGN_R(X,Y) (CPSGN(1,CREAL(X)) != CPSGN(1,CREAL(Y))) +#define CKSGN_I(X,Y) (CPSGN(1,CIMAG(X)) != CPSGN(1,CIMAG(Y))) + +/* Test that (cproj(X) == ZERO+Inf) and that the signs of the + imaginary parts match. ZERO is +/- 0i. */ +#define TEST_CST_INF(X,ZERO) do { \ + if (CPROJF(X) != ZERO+INF || CKSGN_I(CPROJF(X),ZERO+INF)) \ + link_error(__LINE__); \ + if (CPROJ(X) != ZERO+INF || CKSGN_I(CPROJ(X),ZERO+INF)) \ + link_error(__LINE__); \ + if (CPROJL(X) != ZERO+INF || CKSGN_I(CPROJL(X),ZERO+INF)) \ + link_error(__LINE__); \ +} while (0) + +/* Test that (cproj(X) == X) for all finite (X). */ +#define TEST_CST(X) do { \ + if (CPROJF(X) != (X) || CKSGN(CPROJF(X),(X))) \ + link_error(__LINE__); \ +} while (0) + +void foo (void) +{ + TEST_CST_INF (INF+0I, 0); + TEST_CST_INF (INF-0I, -0.FI); + TEST_CST_INF (INF+4I, 0); + TEST_CST_INF (INF-4I, -0.FI); + TEST_CST_INF (-INF+0I, 0); + TEST_CST_INF (-INF-0I, -0.FI); + TEST_CST_INF (-INF+4I, 0); + TEST_CST_INF (-INF-4I, -0.FI); + + TEST_CST_INF (0+I*INF, 0); + TEST_CST_INF (0-I*INF, -0.FI); + TEST_CST_INF (23+I*INF, 0); + TEST_CST_INF (23-I*INF, -0.FI); + TEST_CST_INF (-0.F+I*INF, 0); + TEST_CST_INF (-0.F-I*INF, -0.FI); + TEST_CST_INF (-23+I*INF, 0); + TEST_CST_INF (-23-I*INF, -0.FI); + + TEST_CST_INF (INF+I*INF, 0); + TEST_CST_INF (INF-I*INF, -0.FI); + TEST_CST_INF (-INF+I*INF, 0); + TEST_CST_INF (-INF-I*INF, -0.FI); + + TEST_CST (0); + TEST_CST (-0.F); + TEST_CST (0-0.FI); + TEST_CST (-0.F-0.FI); + + TEST_CST (22+3I); + TEST_CST (22-3I); + TEST_CST (-22+3I); + TEST_CST (-22-3I); + + return; +} + +int main (void) +{ + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/builtin-cproj-2.c b/gcc/testsuite/gcc.dg/torture/builtin-cproj-2.c new file mode 100644 index 00000000000..39331651f19 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/builtin-cproj-2.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2010 Free Software Foundation. + + Verify that folding of built-in cproj is correctly performed by the + compiler. With -ffinite-math-only all cproj calls should be + eliminated regardless of what the argument is, or what is known + about it. + + Origin: Kaveh R. Ghazi, April 9, 2010. */ + +/* { dg-do link } */ +/* { dg-options "-ffinite-math-only" } */ + +/* All references to link_error should go away at compile-time. The + argument is the __LINE__ number. It appears in the tree dump file + and aids in debugging should any of the tests fail. */ +extern void link_error(int); + +#define CPROJ(X) __builtin_cproj(X) +#define CPROJF(X) __builtin_cprojf(X) +#define CPROJL(X) __builtin_cprojl(X) + +/* Test that the supplied expressions eliminte the cproj call. */ +#define TEST_EXPRS(LD_EXPR, D_EXPR, F_EXPR) do { \ + if (CPROJF(F_EXPR) != (F_EXPR)) \ + link_error (__LINE__); \ + if (CPROJ(D_EXPR) != (D_EXPR)) \ + link_error (__LINE__); \ + if (CPROJL(LD_EXPR) != (LD_EXPR)) \ + link_error (__LINE__); \ +} while (0) + +void foo (_Complex long double cld, _Complex double cd, _Complex float cf) +{ +#ifdef __OPTIMIZE__ + TEST_EXPRS (cld, cd, cf); + TEST_EXPRS (cld*2, cd*2, cf*2); + TEST_EXPRS (cld*cld, cd*cd, cf*cf); +#endif + + return; +} + +int main (void) +{ + return 0; +} |