On Sun, Aug 30, 2015 at 9:44 AM, Marc Glisse <marc.gli...@inria.fr> wrote: > Hello, > > just trying to shrink fold-const.c a bit more. > > The tests "if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)" seem useless, > I did one bootstrap+testsuite with asserts there to make sure, so I am > dropping them. The CONJ_EXPR simplifications don't seem very useful, as far > as I can tell CONJ_EXPR is immediatly replaced with a piecewise operation > (where the transformations are obvious), but it seemed easier to keep the > transformations, in case they are not completely useless. I may have been a > bit too enthusiastic with the :s on some transformations, but again they > seem to be dead code... The converts also seem to be not so useful since > they are expanded piecewise, even the ones that should be NOPS, > so for > _Complex unsigned f(_Complex int i){return i;} > we generate: > movl %edi, %eax > shrq $32, %rdi > salq $32, %rdi > orq %rdi, %rax > ...
Yeah, it might help for GENERIC folding but on gimple we lower things pretty quickly (partly during gimplification). > Bootstrap+testsuite on ppc64le-redhat-linux. Ok. Thanks, Richard. > 2015-08-31 Marc Glisse <marc.gli...@inria.fr> > > gcc/ > * match.pd (SIN, COS, TAN, COSH): Reorder for consistency. > (CEXPI): New operator list. > (real (conj (x)), imag (conj (x)), real (x +- y), real (cexpi (x)), > imag (cexpi (x)), conj (conj (x)), conj (complex (x, y))): > Converted from ... > * fold-const.c (fold_unary_loc, fold_binary_loc): ... here. Remove. > > gcc/testsuite/ > * gcc.dg/tree-ssa/complex-7.c: New file. > > -- > Marc Glisse > Index: gcc/fold-const.c > =================================================================== > --- gcc/fold-const.c (revision 227316) > +++ gcc/fold-const.c (working copy) > @@ -7725,35 +7725,20 @@ fold_unary_loc (location_t loc, enum tre > /* Strip sign ops from argument. */ > if (TREE_CODE (type) == REAL_TYPE) > { > tem = fold_strip_sign_ops (arg0); > if (tem) > return fold_build1_loc (loc, ABS_EXPR, type, > fold_convert_loc (loc, type, tem)); > } > return NULL_TREE; > > - case CONJ_EXPR: > - if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE) > - return fold_convert_loc (loc, type, arg0); > - if (TREE_CODE (arg0) == COMPLEX_EXPR) > - { > - tree itype = TREE_TYPE (type); > - tree rpart = fold_convert_loc (loc, itype, TREE_OPERAND (arg0, > 0)); > - tree ipart = fold_convert_loc (loc, itype, TREE_OPERAND (arg0, > 1)); > - return fold_build2_loc (loc, COMPLEX_EXPR, type, rpart, > - negate_expr (ipart)); > - } > - if (TREE_CODE (arg0) == CONJ_EXPR) > - return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)); > - return NULL_TREE; > - > case BIT_NOT_EXPR: > /* Convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */ > if (TREE_CODE (arg0) == BIT_XOR_EXPR > && (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type, > fold_convert_loc (loc, type, > TREE_OPERAND (arg0, > 0))))) > return fold_build2_loc (loc, BIT_XOR_EXPR, type, tem, > fold_convert_loc (loc, type, > TREE_OPERAND (arg0, 1))); > else if (TREE_CODE (arg0) == BIT_XOR_EXPR > @@ -7769,95 +7754,20 @@ fold_unary_loc (location_t loc, enum tre > case TRUTH_NOT_EXPR: > /* Note that the operand of this must be an int > and its values must be 0 or 1. > ("true" is a fixed value perhaps depending on the language, > but we don't handle values other than 1 correctly yet.) */ > tem = fold_truth_not_expr (loc, arg0); > if (!tem) > return NULL_TREE; > return fold_convert_loc (loc, type, tem); > > - case REALPART_EXPR: > - if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE) > - return fold_convert_loc (loc, type, arg0); > - if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) > - { > - tree itype = TREE_TYPE (TREE_TYPE (arg0)); > - tem = fold_build2_loc (loc, TREE_CODE (arg0), itype, > - fold_build1_loc (loc, REALPART_EXPR, itype, > - TREE_OPERAND (arg0, 0)), > - fold_build1_loc (loc, REALPART_EXPR, itype, > - TREE_OPERAND (arg0, 1))); > - return fold_convert_loc (loc, type, tem); > - } > - if (TREE_CODE (arg0) == CONJ_EXPR) > - { > - tree itype = TREE_TYPE (TREE_TYPE (arg0)); > - tem = fold_build1_loc (loc, REALPART_EXPR, itype, > - TREE_OPERAND (arg0, 0)); > - return fold_convert_loc (loc, type, tem); > - } > - if (TREE_CODE (arg0) == CALL_EXPR) > - { > - tree fn = get_callee_fndecl (arg0); > - if (fn && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL) > - switch (DECL_FUNCTION_CODE (fn)) > - { > - CASE_FLT_FN (BUILT_IN_CEXPI): > - fn = mathfn_built_in (type, BUILT_IN_COS); > - if (fn) > - return build_call_expr_loc (loc, fn, 1, CALL_EXPR_ARG > (arg0, 0)); > - break; > - > - default: > - break; > - } > - } > - return NULL_TREE; > - > - case IMAGPART_EXPR: > - if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE) > - return build_zero_cst (type); > - if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) > - { > - tree itype = TREE_TYPE (TREE_TYPE (arg0)); > - tem = fold_build2_loc (loc, TREE_CODE (arg0), itype, > - fold_build1_loc (loc, IMAGPART_EXPR, itype, > - TREE_OPERAND (arg0, 0)), > - fold_build1_loc (loc, IMAGPART_EXPR, itype, > - TREE_OPERAND (arg0, 1))); > - return fold_convert_loc (loc, type, tem); > - } > - if (TREE_CODE (arg0) == CONJ_EXPR) > - { > - tree itype = TREE_TYPE (TREE_TYPE (arg0)); > - tem = fold_build1_loc (loc, IMAGPART_EXPR, itype, TREE_OPERAND > (arg0, 0)); > - return fold_convert_loc (loc, type, negate_expr (tem)); > - } > - if (TREE_CODE (arg0) == CALL_EXPR) > - { > - tree fn = get_callee_fndecl (arg0); > - if (fn && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL) > - switch (DECL_FUNCTION_CODE (fn)) > - { > - CASE_FLT_FN (BUILT_IN_CEXPI): > - fn = mathfn_built_in (type, BUILT_IN_SIN); > - if (fn) > - return build_call_expr_loc (loc, fn, 1, CALL_EXPR_ARG > (arg0, 0)); > - break; > - > - default: > - break; > - } > - } > - return NULL_TREE; > - > case INDIRECT_REF: > /* Fold *&X to X if X is an lvalue. */ > if (TREE_CODE (op0) == ADDR_EXPR) > { > tree op00 = TREE_OPERAND (op0, 0); > if ((TREE_CODE (op00) == VAR_DECL > || TREE_CODE (op00) == PARM_DECL > || TREE_CODE (op00) == RESULT_DECL) > && !TREE_READONLY (op00)) > return op00; > Index: gcc/match.pd > =================================================================== > --- gcc/match.pd (revision 227316) > +++ gcc/match.pd (working copy) > @@ -48,24 +48,25 @@ along with GCC; see the file COPYING3. > (define_operator_list LOG BUILT_IN_LOGF BUILT_IN_LOG BUILT_IN_LOGL) > (define_operator_list EXP BUILT_IN_EXPF BUILT_IN_EXP BUILT_IN_EXPL) > (define_operator_list LOG2 BUILT_IN_LOG2F BUILT_IN_LOG2 BUILT_IN_LOG2L) > (define_operator_list EXP2 BUILT_IN_EXP2F BUILT_IN_EXP2 BUILT_IN_EXP2L) > (define_operator_list LOG10 BUILT_IN_LOG10F BUILT_IN_LOG10 BUILT_IN_LOG10L) > (define_operator_list EXP10 BUILT_IN_EXP10F BUILT_IN_EXP10 BUILT_IN_EXP10L) > (define_operator_list POW BUILT_IN_POWF BUILT_IN_POW BUILT_IN_POWL) > (define_operator_list POW10 BUILT_IN_POW10F BUILT_IN_POW10 BUILT_IN_POW10L) > (define_operator_list SQRT BUILT_IN_SQRTF BUILT_IN_SQRT BUILT_IN_SQRTL) > (define_operator_list CBRT BUILT_IN_CBRTF BUILT_IN_CBRT BUILT_IN_CBRTL) > -(define_operator_list SIN BUILT_IN_SIN BUILT_IN_SINL BUILT_IN_SINF) > -(define_operator_list COS BUILT_IN_COS BUILT_IN_COSL BUILT_IN_COSF) > -(define_operator_list TAN BUILT_IN_TAN BUILT_IN_TANL BUILT_IN_TANF) > -(define_operator_list COSH BUILT_IN_COSH BUILT_IN_COSHL BUILT_IN_COSHF) > +(define_operator_list SIN BUILT_IN_SINF BUILT_IN_SIN BUILT_IN_SINL) > +(define_operator_list COS BUILT_IN_COSF BUILT_IN_COS BUILT_IN_COSL) > +(define_operator_list TAN BUILT_IN_TANF BUILT_IN_TAN BUILT_IN_TANL) > +(define_operator_list COSH BUILT_IN_COSHF BUILT_IN_COSH BUILT_IN_COSHL) > +(define_operator_list CEXPI BUILT_IN_CEXPIF BUILT_IN_CEXPI BUILT_IN_CEXPIL) > > /* Simplifications of operations with one constant operand and > simplifications to constants or single values. */ > > (for op (plus pointer_plus minus bit_ior bit_xor) > (simplify > (op @0 integer_zerop) > (non_lvalue @0))) > > /* 0 +p index -> (type)index */ > @@ -1305,20 +1306,50 @@ along with GCC; see the file COPYING3. > (simplify > (complex (realpart @0) (imagpart @0)) > @0) > (simplify > (realpart (complex @0 @1)) > @0) > (simplify > (imagpart (complex @0 @1)) > @1) > > +/* Sometimes we only care about half of a complex expression. */ > +(simplify > + (realpart (convert?:s (conj:s @0))) > + (convert (realpart @0))) > +(simplify > + (imagpart (convert?:s (conj:s @0))) > + (convert (negate (imagpart @0)))) > +(for part (realpart imagpart) > + (for op (plus minus) > + (simplify > + (part (convert?:s@2 (op:s @0 @1))) > + (convert (op (part @0) (part @1)))))) > +(simplify > + (realpart (convert?:s (CEXPI:s @0))) > + (convert (COS @0))) > +(simplify > + (imagpart (convert?:s (CEXPI:s @0))) > + (convert (SIN @0))) > + > +/* conj(conj(x)) -> x */ > +(simplify > + (conj (convert? (conj @0))) > + (if (tree_nop_conversion_p (TREE_TYPE (@0), type)) > + (convert @0))) > + > +/* conj({x,y}) -> {x,-y} */ > +(simplify > + (conj (convert?:s (complex:s @0 @1))) > + (with { tree itype = TREE_TYPE (type); } > + (complex (convert:itype @0) (negate (convert:itype @1))))) > > /* BSWAP simplifications, transforms checked by gcc.dg/builtin-bswap-8.c. > */ > (for bswap (BUILT_IN_BSWAP16 BUILT_IN_BSWAP32 BUILT_IN_BSWAP64) > (simplify > (bswap (bswap @0)) > @0) > (simplify > (bswap (bit_not (bswap @0))) > (bit_not @0)) > (for bitop (bit_xor bit_ior bit_and) > Index: gcc/testsuite/gcc.dg/tree-ssa/complex-7.c > =================================================================== > --- gcc/testsuite/gcc.dg/tree-ssa/complex-7.c (revision 0) > +++ gcc/testsuite/gcc.dg/tree-ssa/complex-7.c (working copy) > @@ -0,0 +1,15 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O -fdump-tree-forwprop1" } */ > + > +float f(_Complex float x, _Complex float y){ > + x += y; > + return __builtin_cimagf (x); > +} > + > +double g(double x){ > + _Complex double c = __builtin_cexpi (x); > + return __builtin_creal (c); > +} > + > +/* { dg-final { scan-tree-dump "__builtin_cos" "forwprop1"} } */ > +/* { dg-final { scan-tree-dump-times "IMAGPART_EXPR" 2 "forwprop1"} } */ >