On Tue, Oct 20, 2015 at 11:03 AM, Richard Sandiford <richard.sandif...@arm.com> wrote: > Richi and I both had patches for cproj. I thought I might as well > post a rebased version of what I had, since for the other patches I'd > been moving the constant handling into fold_builtin_1 (where functions > without combinatorial folds also handled constants). I'm hoping the > switch statement there will eventually become the switch statement > for folding a function with constant arguments. > > The patch also makes build_complex_cproj available globally and uses it > for the existing match.pd rules. > > Certainly not a big deal or a big improvement, but... tested on > x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi. OK to install?
Ok with build_complex_cproj renamed to sth more descriptive - build_complex_inf? After all it builds a complex Inf with an imag -0 eventually. Richard. > Thanks, > Richard > > > gcc/ > * builtins.c (fold_builtin_cproj): Delete. > (fold_builtin_1): Handle constant arguments here. > (build_complex_cproj): Move to... > * tree.c: ...here. > * tree.h (build_complex_cproj): Declare. > * match.pd: Fold cproj(x)->x if x has no infinity. > Use build_complex_cproj for existing cproj rules. > > diff --git a/gcc/builtins.c b/gcc/builtins.c > index a9872c4..16f3bfd 100644 > --- a/gcc/builtins.c > +++ b/gcc/builtins.c > @@ -7539,50 +7539,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. */ > > @@ -9505,7 +9461,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_cproj (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 aaca3a0..7d16c52 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -2448,30 +2448,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_cproj (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_cproj (type, TREE_REAL_CST_PTR (@1)->sign); })) > > > /* Narrowing of arithmetic and logical operations. > diff --git a/gcc/tree.c b/gcc/tree.c > index 9d0e9de..1405328 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) 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_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)); > +} > + > /* 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 f62cd27..2dbd81b 100644 > --- a/gcc/tree.h > +++ b/gcc/tree.h > @@ -3847,6 +3847,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_cproj (tree, bool); > extern tree build_each_one_cst (tree); > extern tree build_one_cst (tree); > extern tree build_minus_one_cst (tree); >