Message ID | 87611xy6ch.fsf@e105548-lin.cambridge.arm.com |
---|---|
State | New |
Headers | show |
On Fri, Oct 23, 2015 at 5:03 PM, Richard Sandiford <richard.sandiford@arm.com> wrote: > This required reinstating support for captures in the result > of a simplification. That part (genmatch.c) is by Richard B. > > Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi. > OK to install? > > Thanks, > Richard > > > gcc/ > 2015-10-20 Richard Sandiford <richard.sandiford@arm.com> > Richard Biener <rguenther@suse.de> > > * genmatch.c (dt_simplify::gen): Skip captures that are > part of the result. > (parser::parse_expr): Allow captures in results too. > * builtins.c (fold_builtin_cexp): Delete. > (fold_builtin_1): Handle constant cexp arguments here. > * match.pd: Fold cexp(x+yi) to exp(x) * cexpi(y). > > diff --git a/gcc/builtins.c b/gcc/builtins.c > index 02bf9f6..e5e65ba 100644 > --- a/gcc/builtins.c > +++ b/gcc/builtins.c > @@ -7577,74 +7577,6 @@ fold_builtin_sincos (location_t loc, > build1 (REALPART_EXPR, type, call))); > } > > -/* Fold function call to builtin cexp, cexpf, or cexpl. Return > - NULL_TREE if no simplification can be made. */ > - > -static tree > -fold_builtin_cexp (location_t loc, tree arg0, tree type) > -{ > - tree rtype; > - tree realp, imagp, ifn; > - tree res; > - > - if (!validate_arg (arg0, COMPLEX_TYPE) > - || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE) > - return NULL_TREE; > - > - /* Calculate the result when the argument is a constant. */ > - if ((res = do_mpc_arg1 (arg0, type, mpc_exp))) > - return res; > - > - rtype = TREE_TYPE (TREE_TYPE (arg0)); > - > - /* In case we can figure out the real part of arg0 and it is constant zero > - fold to cexpi. */ > - if (!targetm.libc_has_function (function_c99_math_complex)) > - return NULL_TREE; > - ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI); > - if (!ifn) > - return NULL_TREE; > - > - if ((realp = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0)) > - && real_zerop (realp)) > - { > - tree narg = fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0); > - return build_call_expr_loc (loc, ifn, 1, narg); > - } > - > - /* In case we can easily decompose real and imaginary parts split cexp > - to exp (r) * cexpi (i). */ > - if (flag_unsafe_math_optimizations > - && realp) > - { > - tree rfn, rcall, icall; > - > - rfn = mathfn_built_in (rtype, BUILT_IN_EXP); > - if (!rfn) > - return NULL_TREE; > - > - imagp = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0); > - if (!imagp) > - return NULL_TREE; > - > - icall = build_call_expr_loc (loc, ifn, 1, imagp); > - icall = builtin_save_expr (icall); > - rcall = build_call_expr_loc (loc, rfn, 1, realp); > - rcall = builtin_save_expr (rcall); > - return fold_build2_loc (loc, COMPLEX_EXPR, type, > - fold_build2_loc (loc, MULT_EXPR, rtype, > - rcall, > - fold_build1_loc (loc, REALPART_EXPR, > - rtype, icall)), > - fold_build2_loc (loc, MULT_EXPR, rtype, > - rcall, > - fold_build1_loc (loc, IMAGPART_EXPR, > - rtype, icall))); > - } > - > - return NULL_TREE; > -} > - > /* Fold function call to builtin trunc, truncf or truncl with argument ARG. > Return NULL_TREE if no simplification can be made. */ > > @@ -9589,7 +9521,10 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0) > break; > > CASE_FLT_FN (BUILT_IN_CEXP): > - return fold_builtin_cexp (loc, arg0, type); > + if (validate_arg (arg0, COMPLEX_TYPE) > + && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) > + return do_mpc_arg1 (arg0, type, mpc_exp); > + break; > > CASE_FLT_FN (BUILT_IN_CEXPI): > if (validate_arg (arg0, REAL_TYPE)) > diff --git a/gcc/genmatch.c b/gcc/genmatch.c > index b05760e..b5a0fff 100644 > --- a/gcc/genmatch.c > +++ b/gcc/genmatch.c > @@ -3163,7 +3163,11 @@ dt_simplify::gen (FILE *f, int indent, bool gimple) > s->capture_max + 1, indexes[0]->get_name (opname)); > > for (int i = 1; i <= s->capture_max; ++i) > - fprintf (f, ", %s", indexes[i]->get_name (opname)); > + { > + if (!indexes[i]) > + break; > + fprintf (f, ", %s", indexes[i]->get_name (opname)); > + } > fprintf (f, " };\n"); > } > > @@ -3831,7 +3835,7 @@ parser::parse_expr () > > if (token->type == CPP_ATSIGN > && !(token->flags & PREV_WHITE)) > - op = parse_capture (e, !parsing_match_operand); > + op = parse_capture (e, false); > else if (force_capture) > { > unsigned num = capture_ids->elements (); > diff --git a/gcc/match.pd b/gcc/match.pd > index b399786..98bb903 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see > (define_operator_list TAN BUILT_IN_TANF BUILT_IN_TAN BUILT_IN_TANL) > (define_operator_list ATAN BUILT_IN_ATANF BUILT_IN_ATAN BUILT_IN_ATANL) > (define_operator_list COSH BUILT_IN_COSHF BUILT_IN_COSH BUILT_IN_COSHL) > +(define_operator_list CEXP BUILT_IN_CEXPF BUILT_IN_CEXP BUILT_IN_CEXPL) > (define_operator_list CEXPI BUILT_IN_CEXPIF BUILT_IN_CEXPI BUILT_IN_CEXPIL) > (define_operator_list CPROJ BUILT_IN_CPROJF BUILT_IN_CPROJ BUILT_IN_CPROJL) > (define_operator_list CCOS BUILT_IN_CCOSF BUILT_IN_CCOS BUILT_IN_CCOSL) > @@ -1530,6 +1531,11 @@ along with GCC; see the file COPYING3. If not see > (mult @0 integer_minus_onep) > (negate @0)) > > +/* True if we can easily extract the real and imaginary parts of a complex > + number. */ > +(match (compositional_complex) argument-less predicates should have their name not parentized > + (convert?:s (complex @0 @1))) :s has no effect in (match ...), so you can drop it. Ok with those changes. Richard. > + > /* COMPLEX_EXPR and REALPART/IMAGPART_EXPR cancellations. */ > (simplify > (complex (realpart @0) (imagpart @0)) > @@ -2535,7 +2541,18 @@ along with GCC; see the file COPYING3. If not see > /* cabs(x+xi) -> fabs(x)*sqrt(2). */ > (simplify > (CABS (complex @0 @0)) > - (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); }))) > + (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); })) > + > + /* cexp(x+yi) -> exp(x)*cexpi(y). */ > + (for cexps (CEXP) > + exps (EXP) > + cexpis (CEXPI) > + (simplify > + (cexps compositional_complex@0) > + (if (targetm.libc_has_function (function_c99_math_complex)) > + (complex > + (mult (exps@1 (realpart @0)) (realpart (cexpis:type@2 (imagpart @0)))) > + (mult @1 (imagpart @2))))))) > > /* cproj(x) -> x if we're ignoring infinities. */ > (simplify >
diff --git a/gcc/builtins.c b/gcc/builtins.c index 02bf9f6..e5e65ba 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -7577,74 +7577,6 @@ fold_builtin_sincos (location_t loc, build1 (REALPART_EXPR, type, call))); } -/* Fold function call to builtin cexp, cexpf, or cexpl. Return - NULL_TREE if no simplification can be made. */ - -static tree -fold_builtin_cexp (location_t loc, tree arg0, tree type) -{ - tree rtype; - tree realp, imagp, ifn; - tree res; - - if (!validate_arg (arg0, COMPLEX_TYPE) - || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE) - return NULL_TREE; - - /* Calculate the result when the argument is a constant. */ - if ((res = do_mpc_arg1 (arg0, type, mpc_exp))) - return res; - - rtype = TREE_TYPE (TREE_TYPE (arg0)); - - /* In case we can figure out the real part of arg0 and it is constant zero - fold to cexpi. */ - if (!targetm.libc_has_function (function_c99_math_complex)) - return NULL_TREE; - ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI); - if (!ifn) - return NULL_TREE; - - if ((realp = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0)) - && real_zerop (realp)) - { - tree narg = fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0); - return build_call_expr_loc (loc, ifn, 1, narg); - } - - /* In case we can easily decompose real and imaginary parts split cexp - to exp (r) * cexpi (i). */ - if (flag_unsafe_math_optimizations - && realp) - { - tree rfn, rcall, icall; - - rfn = mathfn_built_in (rtype, BUILT_IN_EXP); - if (!rfn) - return NULL_TREE; - - imagp = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0); - if (!imagp) - return NULL_TREE; - - icall = build_call_expr_loc (loc, ifn, 1, imagp); - icall = builtin_save_expr (icall); - rcall = build_call_expr_loc (loc, rfn, 1, realp); - rcall = builtin_save_expr (rcall); - return fold_build2_loc (loc, COMPLEX_EXPR, type, - fold_build2_loc (loc, MULT_EXPR, rtype, - rcall, - fold_build1_loc (loc, REALPART_EXPR, - rtype, icall)), - fold_build2_loc (loc, MULT_EXPR, rtype, - rcall, - fold_build1_loc (loc, IMAGPART_EXPR, - rtype, icall))); - } - - return NULL_TREE; -} - /* Fold function call to builtin trunc, truncf or truncl with argument ARG. Return NULL_TREE if no simplification can be made. */ @@ -9589,7 +9521,10 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0) break; CASE_FLT_FN (BUILT_IN_CEXP): - return fold_builtin_cexp (loc, arg0, type); + if (validate_arg (arg0, COMPLEX_TYPE) + && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) + return do_mpc_arg1 (arg0, type, mpc_exp); + break; CASE_FLT_FN (BUILT_IN_CEXPI): if (validate_arg (arg0, REAL_TYPE)) diff --git a/gcc/genmatch.c b/gcc/genmatch.c index b05760e..b5a0fff 100644 --- a/gcc/genmatch.c +++ b/gcc/genmatch.c @@ -3163,7 +3163,11 @@ dt_simplify::gen (FILE *f, int indent, bool gimple) s->capture_max + 1, indexes[0]->get_name (opname)); for (int i = 1; i <= s->capture_max; ++i) - fprintf (f, ", %s", indexes[i]->get_name (opname)); + { + if (!indexes[i]) + break; + fprintf (f, ", %s", indexes[i]->get_name (opname)); + } fprintf (f, " };\n"); } @@ -3831,7 +3835,7 @@ parser::parse_expr () if (token->type == CPP_ATSIGN && !(token->flags & PREV_WHITE)) - op = parse_capture (e, !parsing_match_operand); + op = parse_capture (e, false); else if (force_capture) { unsigned num = capture_ids->elements (); diff --git a/gcc/match.pd b/gcc/match.pd index b399786..98bb903 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see (define_operator_list TAN BUILT_IN_TANF BUILT_IN_TAN BUILT_IN_TANL) (define_operator_list ATAN BUILT_IN_ATANF BUILT_IN_ATAN BUILT_IN_ATANL) (define_operator_list COSH BUILT_IN_COSHF BUILT_IN_COSH BUILT_IN_COSHL) +(define_operator_list CEXP BUILT_IN_CEXPF BUILT_IN_CEXP BUILT_IN_CEXPL) (define_operator_list CEXPI BUILT_IN_CEXPIF BUILT_IN_CEXPI BUILT_IN_CEXPIL) (define_operator_list CPROJ BUILT_IN_CPROJF BUILT_IN_CPROJ BUILT_IN_CPROJL) (define_operator_list CCOS BUILT_IN_CCOSF BUILT_IN_CCOS BUILT_IN_CCOSL) @@ -1530,6 +1531,11 @@ along with GCC; see the file COPYING3. If not see (mult @0 integer_minus_onep) (negate @0)) +/* True if we can easily extract the real and imaginary parts of a complex + number. */ +(match (compositional_complex) + (convert?:s (complex @0 @1))) + /* COMPLEX_EXPR and REALPART/IMAGPART_EXPR cancellations. */ (simplify (complex (realpart @0) (imagpart @0)) @@ -2535,7 +2541,18 @@ along with GCC; see the file COPYING3. If not see /* cabs(x+xi) -> fabs(x)*sqrt(2). */ (simplify (CABS (complex @0 @0)) - (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); }))) + (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); })) + + /* cexp(x+yi) -> exp(x)*cexpi(y). */ + (for cexps (CEXP) + exps (EXP) + cexpis (CEXPI) + (simplify + (cexps compositional_complex@0) + (if (targetm.libc_has_function (function_c99_math_complex)) + (complex + (mult (exps@1 (realpart @0)) (realpart (cexpis:type@2 (imagpart @0)))) + (mult @1 (imagpart @2))))))) /* cproj(x) -> x if we're ignoring infinities. */ (simplify