diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fed6835d9c7267caa8d7e32066e0b63e039b2b79..8271924da317b926d2db78edfa428dd2c862fb9a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2015-10-21 Richard Sandiford <richard.sandiford@arm.com> + + * builtins.c (fold_builtin_cabs): Delete. + (fold_builtin_1): Update accordingly. Handle constant arguments here. + * match.pd: Add rules previously handled by fold_builtin_cabs. + 2015-10-21 Richard Sandiford <richard.sandiford@arm.com> * fold-const.h (fold_strip_sign_ops): Delete. diff --git a/gcc/builtins.c b/gcc/builtins.c index fa02d26651b819ede9f19eb21f86e7bace22ca33..2318b2859fcfa5684b7cd28f8494bc2a250f9dcf 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -7538,82 +7538,6 @@ fold_fixed_mathfn (location_t loc, tree fndecl, tree arg) return NULL_TREE; } -/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the - return type. Return NULL_TREE if no simplification can be made. */ - -static tree -fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl) -{ - tree res; - - if (!validate_arg (arg, COMPLEX_TYPE) - || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE) - return NULL_TREE; - - /* Calculate the result when the argument is a constant. */ - if (TREE_CODE (arg) == COMPLEX_CST - && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg), - type, mpfr_hypot))) - return res; - - if (TREE_CODE (arg) == COMPLEX_EXPR) - { - tree real = TREE_OPERAND (arg, 0); - tree imag = TREE_OPERAND (arg, 1); - - /* If either part is zero, cabs is fabs of the other. */ - if (real_zerop (real)) - return fold_build1_loc (loc, ABS_EXPR, type, imag); - if (real_zerop (imag)) - return fold_build1_loc (loc, ABS_EXPR, type, real); - - /* cabs(x+xi) -> fabs(x)*sqrt(2). */ - if (flag_unsafe_math_optimizations - && operand_equal_p (real, imag, OEP_PURE_SAME)) - { - STRIP_NOPS (real); - return fold_build2_loc (loc, MULT_EXPR, type, - fold_build1_loc (loc, ABS_EXPR, type, real), - build_real_truncate (type, dconst_sqrt2 ())); - } - } - - /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */ - if (TREE_CODE (arg) == NEGATE_EXPR - || TREE_CODE (arg) == CONJ_EXPR) - return build_call_expr_loc (loc, fndecl, 1, TREE_OPERAND (arg, 0)); - - /* Don't do this when optimizing for size. */ - if (flag_unsafe_math_optimizations - && optimize && optimize_function_for_speed_p (cfun)) - { - tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT); - - if (sqrtfn != NULL_TREE) - { - tree rpart, ipart, result; - - arg = builtin_save_expr (arg); - - rpart = fold_build1_loc (loc, REALPART_EXPR, type, arg); - ipart = fold_build1_loc (loc, IMAGPART_EXPR, type, arg); - - rpart = builtin_save_expr (rpart); - ipart = builtin_save_expr (ipart); - - result = fold_build2_loc (loc, PLUS_EXPR, type, - fold_build2_loc (loc, MULT_EXPR, type, - rpart, rpart), - fold_build2_loc (loc, MULT_EXPR, type, - ipart, ipart)); - - return build_call_expr_loc (loc, sqrtfn, 1, result); - } - } - - 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. */ @@ -9655,7 +9579,11 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0) break; CASE_FLT_FN (BUILT_IN_CABS): - return fold_builtin_cabs (loc, arg0, type, fndecl); + if (TREE_CODE (arg0) == COMPLEX_CST + && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) + return do_mpfr_arg2 (TREE_REALPART (arg0), TREE_IMAGPART (arg0), + type, mpfr_hypot); + break; CASE_FLT_FN (BUILT_IN_CARG): return fold_builtin_carg (loc, arg0, type); diff --git a/gcc/match.pd b/gcc/match.pd index c5aa001cd71e0d3021384646d463f86155121a86..0a9598e1f799e76852b425aca1283de69bcd4b92 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -68,6 +68,7 @@ along with GCC; see the file COPYING3. If not see (define_operator_list COPYSIGN BUILT_IN_COPYSIGNF BUILT_IN_COPYSIGN BUILT_IN_COPYSIGNL) +(define_operator_list CABS BUILT_IN_CABSF BUILT_IN_CABS BUILT_IN_CABSL) /* Simplifications of operations with one constant operand and simplifications to constants or single values. */ @@ -394,6 +395,13 @@ along with GCC; see the file COPYING3. If not see (ccoss (negate @0)) (ccoss @0))) +/* cabs(-x) and cos(conj(x)) -> cabs(x). */ +(for ops (conj negate) + (for cabss (CABS) + (simplify + (cabss (ops @0)) + (cabss @0)))) + /* Fold (a * (1 << b)) into (a << b) */ (simplify (mult:c @0 (convert? (lshift integer_onep@1 @2))) @@ -2368,6 +2376,11 @@ along with GCC; see the file COPYING3. If not see (cbrts (exps @0)) (exps (mult @0 { build_real_truncate (type, dconst_third ()); }))))) +/* cabs(x+0i) or cabs(0+xi) -> abs(x). */ +(simplify + (CABS (complex:c @0 real_zerop@1)) + (abs @0)) + /* Canonicalization of sequences of math builtins. These rules represent IL simplifications but are not necessarily optimizations. @@ -2459,7 +2472,12 @@ along with GCC; see the file COPYING3. If not see /* cbrt(pow(x,y)) -> pow(x,y/3), iff x is nonnegative. */ (simplify (cbrts (pows tree_expr_nonnegative_p@0 @1)) - (pows @0 (mult @1 { build_real_truncate (type, dconst_third ()); }))))) + (pows @0 (mult @1 { build_real_truncate (type, dconst_third ()); })))) + + /* cabs(x+xi) -> fabs(x)*sqrt(2). */ + (simplify + (CABS (complex @0 @0)) + (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); }))) /* If the real part is inf and the imag part is known to be nonnegative, return (inf + 0i). */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4abdf50ff9bbb31dcfcb815e92bc67a552185f99..9c76295c91689b74f21d6103d79448bce244912a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2015-10-21 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.dg/lto/20110201-1_0.c: Restrict to sqrt_insn targets. + Add associated options for arm*-*-*. + (sqrt): Remove dummy definition. + 2015-10-21 Richard Sandiford <richard.sandiford@arm.com> * gcc.dg/torture/builtin-symmetric-1.c: Don't run at -O0. diff --git a/gcc/testsuite/gcc.dg/lto/20110201-1_0.c b/gcc/testsuite/gcc.dg/lto/20110201-1_0.c index 5073a50fc52099d9a0d7013124b355dd3b00f2f7..068dddc3a84f7c4fd823fe8558e476c7d9bed9b4 100644 --- a/gcc/testsuite/gcc.dg/lto/20110201-1_0.c +++ b/gcc/testsuite/gcc.dg/lto/20110201-1_0.c @@ -1,6 +1,8 @@ /* { dg-lto-do run } */ /* { dg-lto-options { { -O0 -flto } } } */ +/* { dg-lto-options { "-O0 -flto -mfloat-abi=softfp -mfpu=neon-vfpv4" } { target arm*-*-* } } */ /* { dg-require-linker-plugin "" } */ +/* { dg-require-effective-target sqrt_insn } */ /* We require a linker plugin because otherwise we'd need to link against libm which we are not sure here has cabs on all targets. @@ -16,13 +18,4 @@ foo (_Complex double x, int b) return cabs(x); } -/* We provide a dummy sqrt to avoid link failures on targets that do not - expand sqrt inline. Note that we do not link against libm in order - to ensure cabs is not satisfied by the library, but must be folded. */ -double __attribute__((used)) -sqrt (double x) -{ - return x; -} - int main() { return 0; }