This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Move some complex simplifications to match.pd


On Sun, Aug 30, 2015 at 9:44 AM, Marc Glisse <marc.glisse@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.glisse@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"} } */
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]