diff options
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/builtins.c | 59 | ||||
-rw-r--r-- | gcc/match.pd | 24 | ||||
-rw-r--r-- | gcc/tree.c | 15 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
5 files changed, 49 insertions, 60 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7385acdc788..bd5aef52c91 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2015-10-22 Richard Sandiford <richard.sandiford@arm.com> + + * builtins.c (fold_builtin_cproj): Delete. + (fold_builtin_1): Handle constant arguments here. + (build_complex_cproj): Move and rename to... + * tree.c: (build_complex_inf): ...this. + * tree.h (build_complex_inf): Declare. + * match.pd: Fold cproj(x)->x if x has no infinity. + Use build_complex_inf for existing cproj rules. + 2015-10-22 Andreas Krebbel <krebbel@linux.vnet.ibm.com> PR target/68015 diff --git a/gcc/builtins.c b/gcc/builtins.c index 2318b2859fc..eec4b8898c1 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -7538,50 +7538,6 @@ fold_fixed_mathfn (location_t loc, tree fndecl, tree arg) 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)) - 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 function call to builtin tan, tanf, or tanl with argument ARG. Return NULL_TREE if no simplification can be made. */ @@ -9504,7 +9460,20 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0) break; CASE_FLT_FN (BUILT_IN_CPROJ): - return fold_builtin_cproj (loc, arg0, type); + if (TREE_CODE (arg0) == COMPLEX_CST + && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) + { + const REAL_VALUE_TYPE *real + = TREE_REAL_CST_PTR (TREE_REALPART (arg0)); + const REAL_VALUE_TYPE *imag + = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0)); + + if (real_isinf (real) || real_isinf (imag)) + return build_complex_inf (type, imag->sign); + else + return arg0; + } + break; CASE_FLT_FN (BUILT_IN_CSIN): if (validate_arg (arg0, COMPLEX_TYPE) diff --git a/gcc/match.pd b/gcc/match.pd index 0a9598e1f79..6b181897e2b 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2479,30 +2479,24 @@ along with GCC; see the file COPYING3. If not see (CABS (complex @0 @0)) (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); }))) +/* cproj(x) -> x if we're ignoring infinities. */ +(simplify + (CPROJ @0) + (if (!HONOR_INFINITIES (type)) + @0)) + /* If the real part is inf and the imag part is known to be nonnegative, return (inf + 0i). */ (simplify (CPROJ (complex REAL_CST@0 tree_expr_nonnegative_p@1)) (if (real_isinf (TREE_REAL_CST_PTR (@0))) - (with - { - REAL_VALUE_TYPE rinf; - real_inf (&rinf); - } - { build_complex (type, build_real (TREE_TYPE (type), rinf), - build_zero_cst (TREE_TYPE (type))); }))) + { build_complex_inf (type, false); })) + /* If the imag part is inf, return (inf+I*copysign(0,imag)). */ (simplify (CPROJ (complex @0 REAL_CST@1)) (if (real_isinf (TREE_REAL_CST_PTR (@1))) - (with - { - REAL_VALUE_TYPE rinf, rzero = dconst0; - real_inf (&rinf); - rzero.sign = TREE_REAL_CST_PTR (@1)->sign; - } - { build_complex (type, build_real (TREE_TYPE (type), rinf), - build_real (TREE_TYPE (type), rzero)); }))) + { build_complex_inf (type, TREE_REAL_CST_PTR (@1)->sign); })) /* Narrowing of arithmetic and logical operations. diff --git a/gcc/tree.c b/gcc/tree.c index adc874847ff..09df67ebf88 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1986,6 +1986,21 @@ build_complex (tree type, tree real, tree imag) return t; } +/* Build a complex (inf +- 0i), such as for the result of cproj. + TYPE is the complex tree type of the result. If NEG is true, the + imaginary zero is negative. */ + +tree +build_complex_inf (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)); +} + /* Return the constant 1 in type TYPE. If TYPE has several elements, each element is set to 1. In particular, this is 1 + i for complex types. */ diff --git a/gcc/tree.h b/gcc/tree.h index 300077cac05..ece083bed3e 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3853,6 +3853,7 @@ extern tree build_constructor_from_list (tree, tree); extern tree build_constructor_va (tree, int, ...); extern tree build_real_from_int_cst (tree, const_tree); extern tree build_complex (tree, tree, tree); +extern tree build_complex_inf (tree, bool); extern tree build_each_one_cst (tree); extern tree build_one_cst (tree); extern tree build_minus_one_cst (tree); |